Allow spilling of EBB arguments.

When the spiller needs to make a register available for a conditional
branch instruction, it can be necessary to spill some of the EBB
arguments on the branch instruction. This is ok because EBB argument
values belong to the same virtual register as the corresponding EBB
parameter and we spill the whole virtreg to the same slot.

Also make sure free_regs() can handle values that are killed by the
current instruction *and* spilled.
This commit is contained in:
Jakob Stoklund Olesen
2017-12-14 10:57:10 -06:00
parent d617d5e0f3
commit febe8e0e51
2 changed files with 38 additions and 3 deletions

View File

@@ -155,8 +155,10 @@ impl<'a> Context<'a> {
fn free_regs(&mut self, kills: &[LiveValue]) {
for lv in kills {
if let Affinity::Reg(rci) = lv.affinity {
let rc = self.reginfo.rc(rci);
self.pressure.free(rc);
if !self.spills.contains(&lv.value) {
let rc = self.reginfo.rc(rci);
self.pressure.free(rc);
}
}
}
}
@@ -402,8 +404,17 @@ impl<'a> Context<'a> {
dbg!("Copy of {} reg causes spill", rc);
// Spill a live register that is *not* used by the current instruction.
// Spilling a use wouldn't help.
//
// Do allow spilling of EBB arguments on branches. This is safe since we spill
// the whole virtual register which includes the matching EBB parameter value
// at the branch destination. It is also necessary since there can be
// arbitrarily many EBB arguments.
match {
let args = self.cur.func.dfg.inst_args(inst);
let args = if self.cur.func.dfg[inst].opcode().is_branch() {
self.cur.func.dfg.inst_fixed_args(inst)
} else {
self.cur.func.dfg.inst_args(inst)
};
self.spill_candidate(
mask,
tracker.live().iter().filter(|lv| !args.contains(&lv.value)),