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:
Dan Gohman
2018-04-09 22:33:54 -07:00
parent eab57c0a40
commit 18b2f12150
2 changed files with 42 additions and 0 deletions

View File

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

View File

@@ -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;
} }