diff --git a/cranelift/filetests/regalloc/reload.cton b/cranelift/filetests/regalloc/reload.cton new file mode 100644 index 0000000000..3db769eea8 --- /dev/null +++ b/cranelift/filetests/regalloc/reload.cton @@ -0,0 +1,19 @@ +test regalloc +isa riscv enable_e + +; regex: V=v\d+ + +; Check that we can handle a function return value that got spilled. +function %spill_return() -> i32 { + fn0 = function %foo() -> i32 native + +ebb0: + v0 = call fn0() + ; check: $(reg=$V) = call $fn0 + ; check: $v0 = spill $reg + v2 = call fn0() + ; check: $v2 = call $fn0 + return v0 + ; check: $(reload=$V) = fill $v0 + ; check: return $reload +} diff --git a/lib/cretonne/src/regalloc/liveness.rs b/lib/cretonne/src/regalloc/liveness.rs index 2c3c430534..8faa8131c6 100644 --- a/lib/cretonne/src/regalloc/liveness.rs +++ b/lib/cretonne/src/regalloc/liveness.rs @@ -213,6 +213,12 @@ fn get_or_create<'a>( .operand_constraints(func.encodings[inst]) .and_then(|rc| rc.outs.get(rnum)) .map(Affinity::new) + .or_else(|| { + // If this is a call, get the return value affinity. + func.dfg.call_signature(inst).map(|sig| { + Affinity::abi(&func.dfg.signatures[sig].return_types[rnum], isa) + }) + }) .unwrap_or_default(); } ValueDef::Arg(ebb, num) => { diff --git a/lib/cretonne/src/regalloc/reload.rs b/lib/cretonne/src/regalloc/reload.rs index 51aded85e0..aed4f040ba 100644 --- a/lib/cretonne/src/regalloc/reload.rs +++ b/lib/cretonne/src/regalloc/reload.rs @@ -183,6 +183,8 @@ impl<'a> Context<'a> { encoding: Encoding, tracker: &mut LiveValueTracker, ) { + self.cur.use_srcloc(inst); + // Get the operand constraints for `inst` that we are trying to satisfy. let constraints = self.encinfo.operand_constraints(encoding).expect( "Missing instruction encoding", @@ -253,6 +255,27 @@ impl<'a> Context<'a> { self.insert_spill(ebb, lv.value, reg); } } + + // Same thing for spilled call return values. + let retvals = &defs[constraints.outs.len()..]; + if !retvals.is_empty() { + let sig = self.cur.func.dfg.call_signature(inst).expect( + "Extra results on non-call instruction", + ); + for (i, lv) in retvals.iter().enumerate() { + let abi = self.cur.func.dfg.signatures[sig].return_types[i]; + debug_assert!(abi.location.is_reg()); + if lv.affinity.is_stack() { + let reg = self.cur.func.dfg.replace_result(lv.value, abi.value_type); + self.liveness.create_dead( + reg, + inst, + Affinity::abi(&abi, self.cur.isa), + ); + self.insert_spill(ebb, lv.value, reg); + } + } + } } // Find reload candidates for `inst` and add them to `self.condidates`.