@@ -4903,6 +4903,7 @@ static void SetIndirectStoreEvalOrder(Compiler* comp, GenTreeIndir* store, bool*
4903
4903
* 1. GetCostEx() to the execution complexity estimate
4904
4904
* 2. GetCostSz() to the code size estimate
4905
4905
* 3. Sometimes sets GTF_ADDRMODE_NO_CSE on nodes in the tree.
4906
+ * 4. DEBUG-only: clears GTF_DEBUG_NODE_MORPHED.
4906
4907
*/
4907
4908
4908
4909
#ifdef _PREFAST_
@@ -14387,7 +14388,10 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14387
14388
// Helper function that creates a new IntCon node and morphs it, if required
14388
14389
auto NewMorphedIntConNode = [&](int value) -> GenTreeIntCon* {
14389
14390
GenTreeIntCon* icon = gtNewIconNode(value);
14390
- icon->SetMorphed(this);
14391
+ if (fgGlobalMorph)
14392
+ {
14393
+ INDEBUG(icon->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
14394
+ }
14391
14395
return icon;
14392
14396
};
14393
14397
@@ -14398,14 +14402,18 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14398
14402
assert(varTypeIsUnsigned(castToType));
14399
14403
14400
14404
GenTreeCast* cast = gtNewCastNode(TYP_INT, op1, false, castToType);
14401
- cast->SetMorphed(this);
14402
- fgMorphTreeDone(cast);
14405
+ if (fgGlobalMorph)
14406
+ {
14407
+ fgMorphTreeDone(cast);
14408
+ }
14403
14409
14404
14410
if (type == TYP_LONG)
14405
14411
{
14406
14412
cast = gtNewCastNode(TYP_LONG, cast, true, TYP_LONG);
14407
- cast->SetMorphed(this);
14408
- fgMorphTreeDone(cast);
14413
+ if (fgGlobalMorph)
14414
+ {
14415
+ fgMorphTreeDone(cast);
14416
+ }
14409
14417
}
14410
14418
14411
14419
return cast;
@@ -14672,7 +14680,14 @@ GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
14672
14680
DISPTREE(tree);
14673
14681
JITDUMP("Transformed into:\n");
14674
14682
DISPTREE(op);
14675
- op->SetMorphed(this);
14683
+
14684
+ if (fgGlobalMorph)
14685
+ {
14686
+ // We can sometimes produce a comma over the constant if the original op
14687
+ // had a side effect, so just ensure we set the flag (which will be already
14688
+ // set for the operands otherwise).
14689
+ INDEBUG(op->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
14690
+ }
14676
14691
return op;
14677
14692
}
14678
14693
@@ -14727,9 +14742,10 @@ GenTree* Compiler::gtFoldExprSpecialFloating(GenTree* tree)
14727
14742
// Helper function that creates a new IntCon node and morphs it, if required
14728
14743
auto NewMorphedIntConNode = [&](int value) -> GenTreeIntCon* {
14729
14744
GenTreeIntCon* icon = gtNewIconNode(value);
14730
-
14731
- icon->SetMorphed(this);
14732
-
14745
+ if (fgGlobalMorph)
14746
+ {
14747
+ INDEBUG(icon->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
14748
+ }
14733
14749
return icon;
14734
14750
};
14735
14751
@@ -14891,8 +14907,14 @@ GenTree* Compiler::gtFoldExprSpecialFloating(GenTree* tree)
14891
14907
DISPTREE(tree);
14892
14908
JITDUMP("Transformed into:\n");
14893
14909
DISPTREE(op);
14894
- op->SetMorphed(this);
14895
14910
14911
+ if (fgGlobalMorph)
14912
+ {
14913
+ // We can sometimes produce a comma over the constant if the original op
14914
+ // had a side effect, so just ensure we set the flag (which will be already
14915
+ // set for the operands otherwise).
14916
+ INDEBUG(op->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
14917
+ }
14896
14918
return op;
14897
14919
}
14898
14920
@@ -15413,11 +15435,6 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
15413
15435
Statement* thisStoreStmt = thisOp->AsBox()->gtCopyStmtWhenInlinedBoxValue;
15414
15436
thisStoreStmt->SetRootNode(thisStore);
15415
15437
thisValOpt = gtNewLclvNode(thisTmp, type);
15416
-
15417
- // If this is invoked during global morph we are adding code to a remote tree
15418
- // Despite this being a store, we can't meaningfully add assertions
15419
- //
15420
- thisStore->SetMorphed(this);
15421
15438
}
15422
15439
15423
15440
if (flagVal->IsIntegralConst())
@@ -15435,11 +15452,6 @@ GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
15435
15452
flagStoreStmt->SetRootNode(flagStore);
15436
15453
flagValOpt = gtNewLclvNode(flagTmp, type);
15437
15454
flagValOptCopy = gtNewLclvNode(flagTmp, type);
15438
-
15439
- // If this is invoked during global morph we are adding code to a remote tree
15440
- // Despite this being a store, we can't meaningfully add assertions
15441
- //
15442
- flagStore->SetMorphed(this);
15443
15455
}
15444
15456
15445
15457
// Turn the call into (thisValTmp & flagTmp) == flagTmp.
@@ -17424,7 +17436,16 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
17424
17436
}
17425
17437
17426
17438
GenTree* comma = m_compiler->gtNewOperNode(GT_COMMA, TYP_VOID, m_result, node);
17427
- comma->SetMorphed(m_compiler);
17439
+
17440
+ #ifdef DEBUG
17441
+ if (m_compiler->fgGlobalMorph)
17442
+ {
17443
+ // Either both should be morphed or neither should be.
17444
+ assert((m_result->gtDebugFlags & GTF_DEBUG_NODE_MORPHED) ==
17445
+ (node->gtDebugFlags & GTF_DEBUG_NODE_MORPHED));
17446
+ comma->gtDebugFlags |= node->gtDebugFlags & GTF_DEBUG_NODE_MORPHED;
17447
+ }
17448
+ #endif
17428
17449
17429
17450
// Both should have valuenumbers defined for both or for neither
17430
17451
// one (unless we are remorphing, in which case a prior transform
@@ -30741,7 +30762,12 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
30741
30762
}
30742
30763
30743
30764
vecCon->gtSimdVal = simdVal;
30744
- vecCon->SetMorphed(this);
30765
+
30766
+ if (fgGlobalMorph)
30767
+ {
30768
+ INDEBUG(vecCon->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
30769
+ }
30770
+
30745
30771
fgUpdateConstTreeValueNumber(vecCon);
30746
30772
return vecCon;
30747
30773
}
@@ -30803,7 +30829,11 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
30803
30829
#endif // !TARGET_XARCH && !TARGET_ARM64
30804
30830
30805
30831
DEBUG_DESTROY_NODE(op, tree);
30806
- vectorNode->SetMorphed(this);
30832
+
30833
+ if (fgGlobalMorph)
30834
+ {
30835
+ INDEBUG(vectorNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
30836
+ }
30807
30837
return vectorNode;
30808
30838
}
30809
30839
}
@@ -31988,10 +32018,17 @@ GenTree* Compiler::gtFoldExprHWIntrinsic(GenTreeHWIntrinsic* tree)
31988
32018
31989
32019
if (resultNode != tree)
31990
32020
{
31991
- resultNode->SetMorphed(this);
31992
- if (resultNode->OperIs(GT_COMMA))
32021
+ if (fgGlobalMorph)
31993
32022
{
31994
- resultNode->AsOp()->gtGetOp2()->SetMorphed(this);
32023
+ // We can sometimes produce a comma over the constant if the original op
32024
+ // had a side effect or even a new constant node, so just ensure we set
32025
+ // the flag (which will be already set for the operands otherwise).
32026
+ INDEBUG(resultNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
32027
+
32028
+ if (resultNode->OperIs(GT_COMMA))
32029
+ {
32030
+ INDEBUG(resultNode->AsOp()->gtGetOp2()->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
32031
+ }
31995
32032
}
31996
32033
31997
32034
if (resultNode->OperIsConst())
@@ -32118,65 +32155,3 @@ bool Compiler::gtCanSkipCovariantStoreCheck(GenTree* value, GenTree* array)
32118
32155
32119
32156
return false;
32120
32157
}
32121
-
32122
- #if defined(DEBUG)
32123
- //------------------------------------------------------------------------
32124
- // SetMorphed: mark a node as having been morphed
32125
- //
32126
- // Arguments:
32127
- // compiler - compiler instance
32128
- // doChildren - recursive mark child nodes
32129
- //
32130
- // Notes:
32131
- // Does nothing outside of global morph.
32132
- //
32133
- // Useful for morph post-order expansions / optimizations.
32134
- //
32135
- // Use care when invoking this on an assignment (or when doChildren is true,
32136
- // on trees containing assignments) as those usually will also require
32137
- // local assertion updates.
32138
- //
32139
- void GenTree::SetMorphed(Compiler* compiler, bool doChildren /* = false */)
32140
- {
32141
- if (!compiler->fgGlobalMorph)
32142
- {
32143
- return;
32144
- }
32145
-
32146
- struct Visitor : GenTreeVisitor<Visitor>
32147
- {
32148
- enum
32149
- {
32150
- DoPostOrder = true,
32151
- };
32152
-
32153
- Visitor(Compiler* comp)
32154
- : GenTreeVisitor(comp)
32155
- {
32156
- }
32157
-
32158
- fgWalkResult PostOrderVisit(GenTree** use, GenTree* user)
32159
- {
32160
- GenTree* const node = *use;
32161
- if (!node->WasMorphed())
32162
- {
32163
- node->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
32164
- node->gtMorphCount++;
32165
- }
32166
- return Compiler::WALK_CONTINUE;
32167
- }
32168
- };
32169
-
32170
- if (doChildren)
32171
- {
32172
- Visitor v(compiler);
32173
- GenTree* node = this;
32174
- v.WalkTree(&node, nullptr);
32175
- }
32176
- else if (!WasMorphed())
32177
- {
32178
- gtDebugFlags |= GTF_DEBUG_NODE_MORPHED;
32179
- gtMorphCount++;
32180
- }
32181
- }
32182
- #endif
0 commit comments