Reload for spilled call return values.
When the return value from a call has been spilled, the reload pass needs to insert a spill instruction right after the call instruction which returns its results in registers.
This commit is contained in:
19
cranelift/filetests/regalloc/reload.cton
Normal file
19
cranelift/filetests/regalloc/reload.cton
Normal file
@@ -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
|
||||
}
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user