From 6c5f5e1147a2356532f5c2bd81a89272be6f05f4 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 30 Jun 2017 08:41:54 -0700 Subject: [PATCH] Hook up the handling of tied register constraints. Tests are forthcoming, we need to implement Intel ABI lowering first. --- lib/cretonne/src/regalloc/liverange.rs | 9 ++++++++- lib/cretonne/src/regalloc/spilling.rs | 14 +++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 95dfb49f2e..9174e0cdba 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -399,7 +399,7 @@ impl LiveRange { } } - /// Check if this live range reaches a use at `inst` in `ebb`. + /// Check if this live range reaches a use at `user` in `ebb`. pub fn reaches_use(&self, user: Inst, ebb: Ebb, order: &PO) -> bool where PO: ProgramOrder { @@ -415,6 +415,13 @@ impl LiveRange { None => false, } } + + /// Check if this live range is killed at `user` in `ebb`. + pub fn killed_at(&self, user: Inst, ebb: Ebb, order: &PO) -> bool + where PO: ProgramOrder + { + self.def_local_end() == user.into() || self.livein_local_end(ebb, order) == Some(user) + } } /// Allow a `LiveRange` to be stored in a `SparseMap` indexed by values. diff --git a/lib/cretonne/src/regalloc/spilling.rs b/lib/cretonne/src/regalloc/spilling.rs index 58f8fdc7fa..37ff870a26 100644 --- a/lib/cretonne/src/regalloc/spilling.rs +++ b/lib/cretonne/src/regalloc/spilling.rs @@ -155,7 +155,7 @@ impl<'a> Context<'a> { pos.goto_top(ebb); while let Some(inst) = pos.next_inst() { if let Some(constraints) = self.encinfo.operand_constraints(self.encodings[inst]) { - self.visit_inst(inst, constraints, &mut pos, dfg, tracker); + self.visit_inst(inst, ebb, constraints, &mut pos, dfg, tracker); } else { let (_throughs, kills) = tracker.process_ghost(inst); self.free_regs(kills); @@ -240,6 +240,7 @@ impl<'a> Context<'a> { fn visit_inst(&mut self, inst: Inst, + ebb: Ebb, constraints: &RecipeConstraints, pos: &mut Cursor, dfg: &mut DataFlowGraph, @@ -248,7 +249,7 @@ impl<'a> Context<'a> { // We may need to resolve register constraints if there are any noteworthy uses. assert!(self.reg_uses.is_empty()); - self.collect_reg_uses(inst, constraints, dfg); + self.collect_reg_uses(inst, ebb, constraints, dfg, pos.layout); // Calls usually have fixed register uses. let call_sig = dfg.call_signature(inst); @@ -315,20 +316,23 @@ impl<'a> Context<'a> { // operands are always compatible. fn collect_reg_uses(&mut self, inst: Inst, + ebb: Ebb, constraints: &RecipeConstraints, - dfg: &DataFlowGraph) { + dfg: &DataFlowGraph, + layout: &Layout) { let args = dfg.inst_args(inst); for (idx, (op, &arg)) in constraints.ins.iter().zip(args).enumerate() { let mut reguse = RegUse::new(arg, idx, op.regclass.into()); + let lr = &self.liveness[arg]; match op.kind { ConstraintKind::Stack => continue, ConstraintKind::FixedReg(_) => reguse.fixed = true, ConstraintKind::Tied(_) => { - // TODO: If `arg` isn't killed here, we need a copy + // A tied operand must kill the used value. + reguse.tied = !lr.killed_at(inst, ebb, layout); } ConstraintKind::Reg => {} } - let lr = &self.liveness[arg]; if lr.affinity.is_stack() { reguse.spilled = true; }