From 18b2f1215096eec0cd7f1d8f813bd55bfce724c3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 9 Apr 2018 22:33:54 -0700 Subject: [PATCH] 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. --- .../isa/intel/prologue-epilogue.cton | 22 +++++++++++++++++++ lib/cretonne/src/isa/intel/abi.rs | 20 +++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/cranelift/filetests/isa/intel/prologue-epilogue.cton b/cranelift/filetests/isa/intel/prologue-epilogue.cton index 0eadcd27d7..ef42836a5a 100644 --- a/cranelift/filetests/isa/intel/prologue-epilogue.cton +++ b/cranelift/filetests/isa/intel/prologue-epilogue.cton @@ -207,3 +207,25 @@ ebb0(v0: i64, v1: i64): ; nextln: v54 = x86_pop.i64 ; nextln: return v54, v55, v56, v57, v58, v59 ; 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 diff --git a/lib/cretonne/src/isa/intel/abi.rs b/lib/cretonne/src/isa/intel/abi.rs index f1abd1cb42..488f8a3d49 100644 --- a/lib/cretonne/src/isa/intel/abi.rs +++ b/lib/cretonne/src/isa/intel/abi.rs @@ -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); return used; }