From 12a8d6cce1f98337f6c5c19dca859285b8524767 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 6 Oct 2017 14:50:33 -0700 Subject: [PATCH] Avoid diverting values that are live on an outgoing CFG edge. When try_add_var is looking for values that can be moved out of the way in order to satisfy constraints for the current instruction, avoid values that are live on a CFG edge originating at the current (branch) instruction. These values must be in their globally assigned location when entering the branch destination EBB. This is covered by the existing regalloc/iterate.cton test case which fails with an upcoming commit. --- lib/cretonne/src/regalloc/coloring.rs | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/cretonne/src/regalloc/coloring.rs b/lib/cretonne/src/regalloc/coloring.rs index 2aad6093a3..a7a0d23883 100644 --- a/lib/cretonne/src/regalloc/coloring.rs +++ b/lib/cretonne/src/regalloc/coloring.rs @@ -711,7 +711,9 @@ impl<'a> Context<'a> { if let Affinity::Reg(rci) = lv.affinity { let rc2 = self.reginfo.rc(rci); let reg2 = self.divert.reg(lv.value, &self.cur.func.locations); - if rc.contains(reg2) && self.solver.can_add_var(lv.value, rc2, reg2) { + if rc.contains(reg2) && self.solver.can_add_var(lv.value, rc2, reg2) && + !self.is_live_on_outgoing_edge(lv.value) + { // The new variable gets to roam the whole top-level register class because // it is not actually constrained by the instruction. We just want it out // of the way. @@ -724,6 +726,31 @@ impl<'a> Context<'a> { false } + /// Determine if `value` is live on a CFG edge from the current instruction. + /// + /// This means that the current instruction is a branch and `value` is live in to one of the + /// branch destinations. Branch arguments and EBB parameters are not considered live on the + /// edge. + fn is_live_on_outgoing_edge(&self, value: Value) -> bool { + use ir::instructions::BranchInfo::*; + + let inst = self.cur.current_inst().expect("Not on an instruction"); + match self.cur.func.dfg[inst].analyze_branch(&self.cur.func.dfg.value_lists) { + NotABranch => false, + SingleDest(ebb, _) => { + let lr = &self.liveness[value]; + lr.is_livein(ebb, &self.cur.func.layout) + } + Table(jt) => { + let lr = &self.liveness[value]; + !lr.is_local() && + self.cur.func.jump_tables[jt].entries().any(|(_, ebb)| { + lr.is_livein(ebb, &self.cur.func.layout) + }) + } + } + } + /// Emit `regmove` instructions as needed to move the live registers into place before the /// instruction. Also update `self.divert` accordingly. ///