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])
|
.operand_constraints(func.encodings[inst])
|
||||||
.and_then(|rc| rc.outs.get(rnum))
|
.and_then(|rc| rc.outs.get(rnum))
|
||||||
.map(Affinity::new)
|
.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();
|
.unwrap_or_default();
|
||||||
}
|
}
|
||||||
ValueDef::Arg(ebb, num) => {
|
ValueDef::Arg(ebb, num) => {
|
||||||
|
|||||||
@@ -183,6 +183,8 @@ impl<'a> Context<'a> {
|
|||||||
encoding: Encoding,
|
encoding: Encoding,
|
||||||
tracker: &mut LiveValueTracker,
|
tracker: &mut LiveValueTracker,
|
||||||
) {
|
) {
|
||||||
|
self.cur.use_srcloc(inst);
|
||||||
|
|
||||||
// Get the operand constraints for `inst` that we are trying to satisfy.
|
// Get the operand constraints for `inst` that we are trying to satisfy.
|
||||||
let constraints = self.encinfo.operand_constraints(encoding).expect(
|
let constraints = self.encinfo.operand_constraints(encoding).expect(
|
||||||
"Missing instruction encoding",
|
"Missing instruction encoding",
|
||||||
@@ -253,6 +255,27 @@ impl<'a> Context<'a> {
|
|||||||
self.insert_spill(ebb, lv.value, reg);
|
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`.
|
// Find reload candidates for `inst` and add them to `self.condidates`.
|
||||||
|
|||||||
Reference in New Issue
Block a user