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:
Jakob Stoklund Olesen
2017-09-29 11:09:21 -07:00
parent 711e5cd644
commit 45888ab84e
3 changed files with 48 additions and 0 deletions

View 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
}

View File

@@ -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) => {

View File

@@ -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`.