From 34ab664ed4ba6ae24e283ca18d1ea53ae4be8421 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Thu, 27 Jul 2017 15:48:48 -0700 Subject: [PATCH] Rerun reg predict on ARM if codegen temps increase the frame size. When compiling for ARM, we need to reserve an additional register if the frame size exceeds a particular watermark. We currently evaluate whether or not we need to reserve this register in two places: first before register prediction and then again during register prediction but after allocating registers for lclVars. The latter evalutation is used to check whether or not we can remove the register reservation if the frame size shrinks due to lclVar register allocation. Unfortunately, its frame size estimate does not include codegen temps, so we can end up undoing the register reservation in a frame that requires the reserved register once the number of temps is estimated. This change adds an additional check to the register predictor after temp estimation has occurred and reruns prediction if the frame size has increased and now requires a register reservation that it did not beforehand. Fixes VSO 469217. --- src/jit/lclvars.cpp | 2 +- src/jit/regalloc.cpp | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp index c3dcaa1..065753a 100644 --- a/src/jit/lclvars.cpp +++ b/src/jit/lclvars.cpp @@ -4477,7 +4477,7 @@ unsigned Compiler::lvaGetMaxSpillTempSize() void Compiler::lvaAssignFrameOffsets(FrameLayoutState curState) { - noway_assert(lvaDoneFrameLayout < curState); + noway_assert((lvaDoneFrameLayout < curState) || (curState == REGALLOC_FRAME_LAYOUT)); lvaDoneFrameLayout = curState; diff --git a/src/jit/regalloc.cpp b/src/jit/regalloc.cpp index 8280503..c1c9fb3 100644 --- a/src/jit/regalloc.cpp +++ b/src/jit/regalloc.cpp @@ -6256,23 +6256,12 @@ void Compiler::rpPredictRegUse() mustPredict |= rpLostEnreg; #ifdef _TARGET_ARM_ - // See if we previously reserved REG_R10 and try to make it available if we have a small frame now - // - if ((rpPasses == 0) && (codeGen->regSet.rsMaskResvd & RBM_OPT_RSVD)) + if ((rpPasses == 0) && ((codeGen->regSet.rsMaskResvd & RBM_OPT_RSVD) != 0) && !compRsvdRegCheck(REGALLOC_FRAME_LAYOUT)) { - if (compRsvdRegCheck(REGALLOC_FRAME_LAYOUT)) - { - // We must keep reserving R10 in this case - codeGen->regSet.rsMaskResvd |= RBM_OPT_RSVD; - } - else - { - // We can release our reservation on R10 and use it to color registers - // - codeGen->regSet.rsMaskResvd &= ~RBM_OPT_RSVD; - allAcceptableRegs |= RBM_OPT_RSVD; - } + // We can release our reservation on R10 and use it to color registers + codeGen->regSet.rsMaskResvd &= ~RBM_OPT_RSVD; + allAcceptableRegs |= RBM_OPT_RSVD; } #endif @@ -6470,6 +6459,17 @@ void Compiler::rpPredictRegUse() /* Decide whether we need to set mustPredict */ mustPredict = false; +#ifdef _TARGET_ARM_ + // The spill count may be now high enough that we now need to reserve r10. If this is the case, we'll need to + // reservation r10 and if it was used repredict. + if (((codeGen->regSet.rsMaskResvd & RBM_OPT_RSVD) == 0) && compRsvdRegCheck(REGALLOC_FRAME_LAYOUT)) + { + codeGen->regSet.rsMaskResvd |= RBM_OPT_RSVD; + allAcceptableRegs &= ~RBM_OPT_RSVD; + mustPredict = (regUsed & RBM_OPT_RSVD) != 0; + } +#endif + if (rpAddedVarIntf) { mustPredict = true; -- 2.7.4