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:
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user