Save/restore callee-saved registers used in regmove/regfill.
The regmove and regfill instructions temporarily divert a value's location, and these temporary diversions are not reflected in `func.locations`. For now, make an extra scan through the instructions of the function to find any regmove or regfill instructions in order to find all used callee-saved registers. This fixes #296.
This commit is contained in:
@@ -207,3 +207,25 @@ ebb0(v0: i64, v1: i64):
|
|||||||
; nextln: v54 = x86_pop.i64
|
; nextln: v54 = x86_pop.i64
|
||||||
; nextln: return v54, v55, v56, v57, v58, v59
|
; nextln: return v54, v55, v56, v57, v58, v59
|
||||||
; nextln: }
|
; nextln: }
|
||||||
|
|
||||||
|
; A function which uses diverted registers.
|
||||||
|
|
||||||
|
function %divert(i32) -> i32 system_v {
|
||||||
|
ebb0(v0: i32):
|
||||||
|
v2 = iconst.i32 0
|
||||||
|
v3 = iconst.i32 1
|
||||||
|
jump ebb3(v0, v3, v2)
|
||||||
|
|
||||||
|
ebb3(v4: i32, v5: i32, v6: i32):
|
||||||
|
brz v4, ebb4
|
||||||
|
v7 = iadd v5, v6
|
||||||
|
v8 = iadd_imm v4, -1
|
||||||
|
jump ebb3(v8, v7, v5)
|
||||||
|
|
||||||
|
ebb4:
|
||||||
|
return v5
|
||||||
|
}
|
||||||
|
|
||||||
|
; check: function %divert
|
||||||
|
; check: regmove v5, %rcx -> %rbx
|
||||||
|
; check: [RexOp1popq#58,%rbx] v15 = x86_pop.i64
|
||||||
|
|||||||
@@ -184,6 +184,26 @@ fn callee_saved_gprs_used(flags: &shared_settings::Flags, func: &ir::Function) -
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// regmove and regfill instructions may temporarily divert values into other registers,
|
||||||
|
// and these are not reflected in `func.locations`. Scan the function for such instructions
|
||||||
|
// and note which callee-saved registers they use.
|
||||||
|
//
|
||||||
|
// TODO: Consider re-evaluating how regmove/regfill/regspill work and whether it's possible
|
||||||
|
// to avoid this step.
|
||||||
|
for ebb in &func.layout {
|
||||||
|
for inst in func.layout.ebb_insts(ebb) {
|
||||||
|
match func.dfg[inst] {
|
||||||
|
ir::instructions::InstructionData::RegMove { dst, .. } |
|
||||||
|
ir::instructions::InstructionData::RegFill { dst, .. } => {
|
||||||
|
if !used.is_avail(GPR, dst) {
|
||||||
|
used.free(GPR, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
used.intersect(&all_callee_saved);
|
used.intersect(&all_callee_saved);
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user