diff --git a/cranelift/src/filetest/binemit.rs b/cranelift/src/filetest/binemit.rs index f1a493c749..da0e2012a0 100644 --- a/cranelift/src/filetest/binemit.rs +++ b/cranelift/src/filetest/binemit.rs @@ -114,6 +114,7 @@ impl SubTest for TestBinEmit { let is_compressed = isa.flags().is_compressed(); // Give an encoding to any instruction that doesn't already have one. + let mut divert = RegDiversions::new(); for ebb in func.layout.ebbs() { for inst in func.layout.ebb_insts(ebb) { if !func.encodings[inst].is_legal() { @@ -128,7 +129,7 @@ impl SubTest for TestBinEmit { legal_encodings .filter(|e| { let recipe_constraints = &encinfo.constraints[e.recipe()]; - recipe_constraints.satisfied(inst, &func) + recipe_constraints.satisfied(inst, &divert, &func) }) .min_by_key(|&e| encinfo.bytes(e)) } else { @@ -140,6 +141,7 @@ impl SubTest for TestBinEmit { func.encodings[inst] = enc; } } + divert.apply(&func.dfg[inst]); } } @@ -178,8 +180,8 @@ impl SubTest for TestBinEmit { } // Now emit all instructions. + divert.clear(); let mut sink = TextSink::new(isa); - let mut divert = RegDiversions::new(); for ebb in func.layout.ebbs() { divert.clear(); // Correct header offsets should have been computed by `relax_branches()`. diff --git a/lib/cretonne/src/isa/constraints.rs b/lib/cretonne/src/isa/constraints.rs index d9fc3aa8ea..9efcf7bb4f 100644 --- a/lib/cretonne/src/isa/constraints.rs +++ b/lib/cretonne/src/isa/constraints.rs @@ -10,6 +10,7 @@ use binemit::CodeOffset; use isa::{RegClass, RegUnit}; use ir::{Function, ValueLoc, Inst}; +use regalloc::RegDiversions; /// Register constraint for a single value operand or instruction result. pub struct OperandConstraint { @@ -109,9 +110,9 @@ pub struct RecipeConstraints { impl RecipeConstraints { /// Check that these constraints are satisfied by the operands on `inst`. - pub fn satisfied(&self, inst: Inst, func: &Function) -> bool { + pub fn satisfied(&self, inst: Inst, divert: &RegDiversions, func: &Function) -> bool { for (&arg, constraint) in func.dfg.inst_args(inst).iter().zip(self.ins) { - let loc = func.locations[arg]; + let loc = divert.get(arg, &func.locations); if let ConstraintKind::Tied(out_index) = constraint.kind { let out_val = func.dfg.inst_results(inst)[out_index as usize]; @@ -127,7 +128,7 @@ impl RecipeConstraints { } for (&arg, constraint) in func.dfg.inst_results(inst).iter().zip(self.outs) { - let loc = func.locations[arg]; + let loc = divert.get(arg, &func.locations); if !constraint.satisfied(loc) { return false; } diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index 9d241ebcdd..c6d25f543e 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -8,6 +8,7 @@ //! EBB. use ir::{Value, ValueLoc, ValueLocations, StackSlot}; +use ir::{InstructionData, Opcode}; use isa::{RegUnit, RegInfo}; use std::fmt; @@ -118,6 +119,34 @@ impl RegDiversions { self.divert(value, ValueLoc::Stack(from), ValueLoc::Reg(to)); } + /// Apply the effect of `inst`. + /// + /// If `inst` is a `regmove`, `regfill`, or `regspill` instruction, update the diversions to + /// match. + pub fn apply(&mut self, inst: &InstructionData) { + match *inst { + InstructionData::RegMove { + opcode: Opcode::Regmove, + arg, + src, + dst, + } => self.regmove(arg, src, dst), + InstructionData::RegSpill { + opcode: Opcode::Regspill, + arg, + src, + dst, + } => self.regspill(arg, src, dst), + InstructionData::RegFill { + opcode: Opcode::Regfill, + arg, + src, + dst, + } => self.regfill(arg, src, dst), + _ => {} + } + } + /// Drop any recorded move for `value`. /// /// Returns the `to` location of the removed diversion.