Fix to issue 8356.
authorsivarv <sivarv@microsoft.com>
Wed, 7 Dec 2016 00:19:55 +0000 (16:19 -0800)
committersivarv <sivarv@microsoft.com>
Wed, 7 Dec 2016 00:49:37 +0000 (16:49 -0800)
Commit migrated from https://github.com/dotnet/coreclr/commit/bdfe0ed89115ab8b52e7450c607701f5d6e31e75

src/coreclr/src/jit/lsra.cpp

index bb8c190..6813beb 100644 (file)
@@ -3931,7 +3931,7 @@ void LinearScan::buildRefPositionsForNode(GenTree*                  tree,
     {
         // Build RefPositions for saving any live large vectors.
         // This must be done after the kills, so that we know which large vectors are still live.
-        VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc));
+        VarSetOps::AssignNoCopy(compiler, liveLargeVectors, buildUpperVectorSaveRefPositions(tree, currentLoc + 1));
     }
 #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE
 
@@ -4015,7 +4015,8 @@ void LinearScan::buildRefPositionsForNode(GenTree*                  tree,
     }
 
 #if FEATURE_PARTIAL_SIMD_CALLEE_SAVE
-    buildUpperVectorRestoreRefPositions(tree, currentLoc, liveLargeVectors);
+    // SaveDef position must be at the same location as Def position of call node.
+    buildUpperVectorRestoreRefPositions(tree, defLocation, liveLargeVectors);
 #endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE
 
     bool isContainedNode = !noAdd && consume == 0 && produce == 0 &&
@@ -7279,23 +7280,39 @@ void LinearScan::allocateRegisters()
             // then find a register to spill
             if (assignedRegister == REG_NA)
             {
-#ifdef FEATURE_SIMD
+#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE
                 if (refType == RefTypeUpperVectorSaveDef)
                 {
                     // TODO-CQ: Determine whether copying to two integer callee-save registers would be profitable.
-                    currentRefPosition->registerAssignment = (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH);
-                    assignedRegister                       = tryAllocateFreeReg(currentInterval, currentRefPosition);
+
+                    // SaveDef position occurs after the Use of args and at the same location as Kill/Def
+                    // positions of a call node.  But SaveDef position cannot use any of the arg regs as
+                    // they are needed for call node.
+                    currentRefPosition->registerAssignment =
+                        (allRegs(TYP_FLOAT) & RBM_FLT_CALLEE_TRASH & ~RBM_FLTARG_REGS);
+                    assignedRegister = tryAllocateFreeReg(currentInterval, currentRefPosition);
+
                     // There MUST be caller-save registers available, because they have all just been killed.
+                    // Amd64 Windows: xmm4-xmm5 are guaranteed to be available as xmm0-xmm3 are used for passing args.
+                    // Amd64 Unix: xmm8-xmm15 are guaranteed to be avilable as xmm0-xmm7 are used for passing args.
+                    // X86 RyuJIT Windows: xmm4-xmm7 are guanrateed to be available.
                     assert(assignedRegister != REG_NA);
+
                     // Now, spill it.
-                    // (These will look a bit backward in the dump, but it's a pain to dump the alloc before the spill).
+                    // Note:
+                    //   i) The reason we have to spill is that SaveDef position is allocated after the Kill positions
+                    //      of the call node are processed.  Since callee-trash registers are killed by call node
+                    //      we explicity spill and unassign the register.
+                    //  ii) These will look a bit backward in the dump, but it's a pain to dump the alloc before the
+                    //  spill).
                     unassignPhysReg(getRegisterRecord(assignedRegister), currentRefPosition);
                     INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_ALLOC_REG, currentInterval, assignedRegister));
+
                     // Now set assignedRegister to REG_NA again so that we don't re-activate it.
                     assignedRegister = REG_NA;
                 }
                 else
-#endif // FEATURE_SIMD
+#endif // FEATURE_PARTIAL_SIMD_CALLEE_SAVE
                     if (currentRefPosition->RequiresRegister() || currentRefPosition->AllocateIfProfitable())
                 {
                     if (allocateReg)