Only lock unlocked registers in `rsUnspillRegPair`.
authorPat Gavlin <pagavlin@microsoft.com>
Fri, 28 Jul 2017 18:42:16 +0000 (11:42 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Fri, 28 Jul 2017 22:45:02 +0000 (15:45 -0700)
`rsUnspillRegPair` needs to lock the hi/lo part of the reg pair when
unspilling the lo/hi part in order to ensure that the two parts of the
pair do not end up in the same register. However, the register to be
locked may already be locked if it is a multi-use register. In this case
`rsUnspillRegPair` does not need to re-lock the register.

Fixes #12910.

src/jit/regset.cpp

index 7204663..20551fa 100644 (file)
@@ -2666,17 +2666,24 @@ void RegSet::rsUnspillRegPair(GenTreePtr tree, regMaskTP needReg, KeepReg keepRe
 
         if (rsIsTreeInReg(regHi, tree))
         {
-            /* Temporarily lock the high part */
-
-            rsLockUsedReg(genRegMask(regHi));
+            // Temporarily lock the high part if necessary. If this register is a multi-use register that is shared
+            // with another tree, the register may already be locked.
+            const regMaskTP regHiMask = genRegMask(regHi);
+            const bool lockReg = (rsMaskLock & regHiMask) == 0;
+            if (lockReg)
+            {
+                rsLockUsedReg(regHiMask);
+            }
 
             /* Pick a new home for the lower half */
 
             regLo = rsUnspillOneReg(tree, regLo, keepReg, needReg);
 
             /* We can unlock the high part now */
-
-            rsUnlockUsedReg(genRegMask(regHi));
+            if (lockReg)
+            {
+                rsUnlockUsedReg(regHiMask);
+            }
         }
         else
         {
@@ -2700,17 +2707,24 @@ void RegSet::rsUnspillRegPair(GenTreePtr tree, regMaskTP needReg, KeepReg keepRe
         {
             regMaskTP regLoUsed;
 
-            /* Temporarily lock the low part so it doesnt get spilled */
-
-            rsLockReg(genRegMask(regLo), &regLoUsed);
+            // Temporarily lock the low part if necessary. If this register is a multi-use register that is shared
+            // with another tree, the register may already be locked.
+            const regMaskTP regLoMask = genRegMask(regLo);
+            const bool lockReg = (rsMaskLock & regLoMask) == 0;
+            if (lockReg)
+            {
+                rsLockReg(regLoMask, &regLoUsed);
+            }
 
             /* Pick a new home for the upper half */
 
             regHi = rsUnspillOneReg(tree, regHi, keepReg, needReg);
 
             /* We can unlock the low register now */
-
-            rsUnlockReg(genRegMask(regLo), regLoUsed);
+            if (lockReg)
+            {
+                rsUnlockReg(regLoMask, regLoUsed);
+            }
         }
         else
         {