diff --git a/filetests/regalloc/spill.cton b/filetests/regalloc/spill.cton index a43ba4cf8f..eaea391504 100644 --- a/filetests/regalloc/spill.cton +++ b/filetests/regalloc/spill.cton @@ -62,3 +62,16 @@ ebb0(v1: i32): return v21 ; 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 +} diff --git a/lib/cretonne/src/regalloc/affinity.rs b/lib/cretonne/src/regalloc/affinity.rs index e7ee0515ad..a7c95df99f 100644 --- a/lib/cretonne/src/regalloc/affinity.rs +++ b/lib/cretonne/src/regalloc/affinity.rs @@ -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? pub fn is_stack(self) -> bool { match self { diff --git a/lib/cretonne/src/regalloc/spilling.rs b/lib/cretonne/src/regalloc/spilling.rs index 8938944952..da0453f549 100644 --- a/lib/cretonne/src/regalloc/spilling.rs +++ b/lib/cretonne/src/regalloc/spilling.rs @@ -152,14 +152,25 @@ impl<'a> Context<'a> { // // Spills should be removed from tracker. Otherwise they could be double-counted by // free_regs below. + let call_sig = dfg.call_signature(inst); // Update the live value tracker with this instruction. let (throughs, kills, defs) = tracker.process_inst(inst, dfg, self.liveness); - // Remove kills from the pressure tracker. 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. // Dead defs are included here. They need a register too. // No need to process call return values, they are in fixed registers.