Spill values live across calls.

Calls clobber many registers, so spill everything that is live across a
call for now.

In the future, we may add support for callee-saved registers.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-14 08:55:01 -07:00
parent 5a23f975fc
commit f2f162f37e
3 changed files with 33 additions and 1 deletions

View File

@@ -62,3 +62,16 @@ ebb0(v1: i32):
return v21 return v21
; check: return $v21, $rlink2 ; check: return $v21, $rlink2
} }
; All values live across a call must be spilled
function %across_call(i32) {
fn0 = function %foo(i32)
ebb0(v1: i32):
; check: $v1 = spill
call fn0(v1)
; check: call $fn0
call fn0(v1)
; check: fill $v1
; check: call $fn0
return
}

View File

@@ -64,6 +64,14 @@ impl Affinity {
} }
} }
/// Is this the `Reg` affinity?
pub fn is_reg(self) -> bool {
match self {
Affinity::Reg(_) => true,
_ => false,
}
}
/// Is this the `Stack` affinity? /// Is this the `Stack` affinity?
pub fn is_stack(self) -> bool { pub fn is_stack(self) -> bool {
match self { match self {

View File

@@ -152,14 +152,25 @@ impl<'a> Context<'a> {
// //
// Spills should be removed from tracker. Otherwise they could be double-counted by // Spills should be removed from tracker. Otherwise they could be double-counted by
// free_regs below. // free_regs below.
let call_sig = dfg.call_signature(inst);
// Update the live value tracker with this instruction. // Update the live value tracker with this instruction.
let (throughs, kills, defs) = tracker.process_inst(inst, dfg, self.liveness); let (throughs, kills, defs) = tracker.process_inst(inst, dfg, self.liveness);
// Remove kills from the pressure tracker. // Remove kills from the pressure tracker.
self.free_regs(kills); self.free_regs(kills);
// If inst is a call, spill all register values that are live across the call.
// This means that we don't currently take advantage of callee-saved registers.
// TODO: Be more sophisticated.
if call_sig.is_some() {
for lv in throughs {
if lv.affinity.is_reg() && !self.spills.contains(&lv.value) {
self.spill_reg(lv.value);
}
}
}
// Make sure we have enough registers for the register defs. // Make sure we have enough registers for the register defs.
// Dead defs are included here. They need a register too. // Dead defs are included here. They need a register too.
// No need to process call return values, they are in fixed registers. // No need to process call return values, they are in fixed registers.