Treat EDI as killed by MaskMove
authorCarol Eidt <carol.eidt@microsoft.com>
Thu, 19 Apr 2018 17:14:23 +0000 (10:14 -0700)
committerCarol Eidt <carol.eidt@microsoft.com>
Fri, 20 Apr 2018 23:18:39 +0000 (16:18 -0700)
It should really only be a fixed reference, not a kill, but if the reference is changed by `LinearScan::resolveConflictingDefAndUse()` it can fail to cause the value in EDI to be killed.

Fix #17634

src/jit/lsra.h
src/jit/lsrabuild.cpp

index 6710782..316942b 100644 (file)
@@ -1112,8 +1112,11 @@ private:
 
     static Compiler::fgWalkResult markAddrModeOperandsHelperMD(GenTree* tree, void* p);
 
-    // Helper for getKillSetForNode().
+    // Helpers for getKillSetForNode().
     regMaskTP getKillSetForStoreInd(GenTreeStoreInd* tree);
+#ifdef FEATURE_HW_INTRINSICS
+    regMaskTP getKillSetForHWIntrinsic(GenTreeHWIntrinsic* node);
+#endif // FEATURE_HW_INTRINSICS
 
     // Return the registers killed by the given tree node.
     regMaskTP getKillSetForNode(GenTree* tree);
index 988728d..ffa28d1 100644 (file)
@@ -680,6 +680,44 @@ regMaskTP LinearScan::getKillSetForStoreInd(GenTreeStoreInd* tree)
     return killMask;
 }
 
+#ifdef FEATURE_HW_INTRINSICS
+//------------------------------------------------------------------------
+// getKillSetForHWIntrinsic: Determine the liveness kill set for a GT_STOREIND node.
+// If the GT_STOREIND will generate a write barrier, determine the specific kill
+// set required by the case-specific, platform-specific write barrier. If no
+// write barrier is required, the kill set will be RBM_NONE.
+//
+// Arguments:
+//    tree - the GT_STOREIND node
+//
+// Return Value:    a register mask of the registers killed
+//
+regMaskTP LinearScan::getKillSetForHWIntrinsic(GenTreeHWIntrinsic* node)
+{
+    regMaskTP killMask = RBM_NONE;
+#ifdef _TARGET_XARCH_
+    switch (node->gtHWIntrinsicId)
+    {
+        case NI_SSE2_MaskMove:
+            // maskmovdqu uses edi as the implicit address register.
+            // Although it is set as the srcCandidate on the address, if there is also a fixed
+            // assignment for the definition of the address, resolveConflictingDefAndUse() may
+            // change the register assignment on the def or use of a tree temp (SDSU) when there
+            // is a conflict, and the FixedRef on edi won't be sufficient to ensure that another
+            // Interval will not be allocated there.
+            // Issue #17674 tracks this.
+            killMask = RBM_EDI;
+            break;
+
+        default:
+            // Leave killMask as RBM_NONE
+            break;
+    }
+#endif // _TARGET_XARCH_
+    return killMask;
+}
+#endif // FEATURE_HW_INTRINSICS
+
 //------------------------------------------------------------------------
 // getKillSetForNode:   Return the registers killed by the given tree node.
 //
@@ -853,6 +891,12 @@ regMaskTP LinearScan::getKillSetForNode(GenTree* tree)
             break;
 #endif // PROFILING_SUPPORTED
 
+#ifdef FEATURE_HW_INTRINSICS
+        case GT_HWIntrinsic:
+            killMask = getKillSetForHWIntrinsic(tree->AsHWIntrinsic());
+            break;
+#endif // FEATURE_HW_INTRINSICS
+
         default:
             // for all other 'tree->OperGet()' kinds, leave 'killMask' = RBM_NONE
             break;