From a1c62a8b28038c8b3576719e3ad6bcb56677915a Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Wed, 8 Mar 2017 21:51:47 -0800 Subject: [PATCH] Fix extend lifetimes stress. --- src/jit/lsra.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/jit/lsra.cpp b/src/jit/lsra.cpp index fe7b599..cf817ca 100644 --- a/src/jit/lsra.cpp +++ b/src/jit/lsra.cpp @@ -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) { -- 2.7.4