Rerun reg predict on ARM if codegen temps increase the frame size.
authorPat Gavlin <pagavlin@microsoft.com>
Thu, 27 Jul 2017 22:48:48 +0000 (15:48 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Thu, 27 Jul 2017 22:48:48 +0000 (15:48 -0700)
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
src/jit/regalloc.cpp

index c3dcaa1..065753a 100644 (file)
@@ -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;
 
index 8280503..c1c9fb3 100644 (file)
@@ -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;