Fix extend lifetimes stress.
authorPat Gavlin <pagavlin@microsoft.com>
Thu, 9 Mar 2017 05:51:47 +0000 (21:51 -0800)
committerPat Gavlin <pagavlin@microsoft.com>
Thu, 9 Mar 2017 05:51:47 +0000 (21:51 -0800)
src/jit/lsra.cpp

index fe7b599..cf817ca 100644 (file)
@@ -732,7 +732,7 @@ void LinearScan::associateRefPosWithInterval(RefPosition* rp)
                 }
 
                 rp->lastUse = (rp->refType != RefTypeExpUse) && (rp->refType != RefTypeParamDef) &&
-                              (rp->refType != RefTypeZeroInit);
+                              (rp->refType != RefTypeZeroInit) && !extendLifetimes();
             }
             else if (RefTypeIsUse(rp->refType))
             {
@@ -2545,7 +2545,20 @@ void LinearScan::checkLastUses(BasicBlock* block)
             if (!VarSetOps::IsMember(compiler, temp, varIndex) && varNum != keepAliveVarNum)
             {
                 // There was no exposed use, so this is a "last use" (and we mark it thus even if it's a def)
-                if (!currentRefPosition->lastUse)
+
+                if (extendLifetimes())
+                {
+                    // NOTE: this is a bit of a hack. When extending lifetimes, the "last use" bit will be clear.
+                    // This bit, however, would normally be used during resolveLocalRef to set the value of
+                    // GTF_VAR_DEATH on the node for a ref position. If this bit is not set correctly even when
+                    // extending lifetimes, the code generator will assert as it expects to have accurate last
+                    // use information. To avoid these asserts, set the GTF_VAR_DEATH bit here.
+                    if (tree != nullptr)
+                    {
+                        tree->gtFlags |= GTF_VAR_DEATH;
+                    }
+                }
+                else if (!currentRefPosition->lastUse)
                 {
                     JITDUMP("missing expected last use of V%02u @%u\n", compiler->lvaTrackedToVarNum[varIndex], loc);
                     foundDiff = true;
@@ -2557,6 +2570,11 @@ void LinearScan::checkLastUses(BasicBlock* block)
                 JITDUMP("unexpected last use of V%02u @%u\n", compiler->lvaTrackedToVarNum[varIndex], loc);
                 foundDiff = true;
             }
+            else if (extendLifetimes() && tree != nullptr)
+            {
+                // NOTE: see the comment above re: the extendLifetimes hack.
+                tree->gtFlags &= ~GTF_VAR_DEATH;
+            }
 
             if (currentRefPosition->refType == RefTypeDef || currentRefPosition->refType == RefTypeDummyDef)
             {
@@ -7675,7 +7693,11 @@ void LinearScan::resolveLocalRef(BasicBlock* block, GenTreePtr treeNode, RefPosi
     interval->recentRefPosition = currentRefPosition;
     LclVarDsc* varDsc           = interval->getLocalVar(compiler);
 
-    if ((treeNode != nullptr))
+    // NOTE: we set the GTF_VAR_DEATH flag here unless we are extending lifetimes, in which case we write
+    // this bit in checkLastUses. This is a bit of a hack, but is necessary because codegen requires
+    // accurate last use info that is not reflected in the lastUse bit on ref positions when we are extending
+    // lifetimes. See also the comments in checkLastUses.
+    if ((treeNode != nullptr) && !extendLifetimes())
     {
         if (currentRefPosition->lastUse)
         {