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.
This commit is contained in:
@@ -711,7 +711,9 @@ impl<'a> Context<'a> {
|
|||||||
if let Affinity::Reg(rci) = lv.affinity {
|
if let Affinity::Reg(rci) = lv.affinity {
|
||||||
let rc2 = self.reginfo.rc(rci);
|
let rc2 = self.reginfo.rc(rci);
|
||||||
let reg2 = self.divert.reg(lv.value, &self.cur.func.locations);
|
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
|
// 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
|
// it is not actually constrained by the instruction. We just want it out
|
||||||
// of the way.
|
// of the way.
|
||||||
@@ -724,6 +726,31 @@ impl<'a> Context<'a> {
|
|||||||
false
|
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
|
/// Emit `regmove` instructions as needed to move the live registers into place before the
|
||||||
/// instruction. Also update `self.divert` accordingly.
|
/// instruction. Also update `self.divert` accordingly.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user