Allow uncontained GT_LONG nodes
authorMike Danes <onemihaid@hotmail.com>
Fri, 1 Jul 2016 19:54:04 +0000 (22:54 +0300)
committerMike Danes <onemihaid@hotmail.com>
Sat, 2 Jul 2016 05:07:00 +0000 (08:07 +0300)
When the result of a TYP_LONG operation is not used the GT_LONG node inserted during decomposition remains in the tree and unlike other GT_LONG nodes is not contained and needs special handling.

This usually happens with arithmetic operations that require overflow checks,  the result of the operation may be ignored but the operation itself cannot be eliminated because it has a side-effect.

Commit migrated from https://github.com/dotnet/coreclr/commit/6f8f2154825b1cf17fbbba8ccb365069e2d7d15f

src/coreclr/src/jit/codegenxarch.cpp
src/coreclr/src/jit/gentree.cpp
src/coreclr/src/jit/lowerxarch.cpp

index ca5dc61..1ec491e 100755 (executable)
@@ -2728,6 +2728,13 @@ CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
         genProduceReg(treeNode);
         break;
 
+#if !defined(_TARGET_64BIT_)
+    case GT_LONG:
+        assert(!treeNode->isContained());
+        genConsumeRegs(treeNode);
+        break;
+#endif
+
     default:
         {
 #ifdef  DEBUG
index 092e63d..6dbba94 100644 (file)
@@ -13235,6 +13235,14 @@ bool GenTree::isContained() const
 #endif
         return false;
 
+#if !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_)
+    case GT_LONG:
+        // GT_LONG nodes are normally contained. The only exception is when the result
+        // of a TYP_LONG operation is not used and this can only happen if the GT_LONG
+        // is the last node in the statement (in linear order).
+        return gtNext != nullptr;
+#endif
+
     case GT_CALL:
         // Note: if you hit this assert you are probably calling isContained() 
         // before the LSRA phase has allocated physical register to the tree nodes
index 6fd09f8..d6e3418 100644 (file)
@@ -247,8 +247,16 @@ void Lowering::TreeNodeInfoInit(GenTree* stmt)
 #if !defined(_TARGET_64BIT_)
 
         case GT_LONG:
-            // Passthrough
-            info->srcCount = 0;
+            if (tree->gtNext == nullptr)
+            {
+                // An uncontained GT_LONG node needs to consume its source operands
+                info->srcCount = 2;
+            }
+            else
+            {
+                // Passthrough
+                info->srcCount = 0;
+            }
             info->dstCount = 0;
             break;