From b938c26548a3e3f08b9459aef74efa614545ecc3 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sat, 2 May 2026 15:54:48 -0700 Subject: [PATCH 1/2] Ensure we preserve vn and produce a canonical tree --- src/coreclr/jit/morph.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index e713a94e0e095f..6021befcea02ae 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -7484,7 +7484,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA JITDUMP("\nTransforming:\n"); DISPTREE(tree); - otherNode->SetOper(GT_AND); // Change % => & + otherNode->SetOper(GT_AND, GenTree::PRESERVE_VN); // Change % => & otherNode->gtFlags &= ~(GTF_DIV_MOD_NO_OVERFLOW | GTF_DIV_MOD_NO_BY_ZERO); divisor->AsIntConCommon()->SetIconValue(modValue - 1); // Change c => c - 1 @@ -7906,7 +7906,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA goto CM_ADD_OP; } - /* Check for "cns1 - op2" , we change it to "(cns1 + (-op2))" */ + /* Check for "cns1 - op2" , we change it to "((-op2) + cns1)" */ noway_assert(op1); if (op1->IsCnsIntOrI()) @@ -7929,9 +7929,13 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA return tree; } - tree->AsOp()->gtOp2 = op2 = gtNewOperNode(GT_NEG, genActualType(op2->TypeGet()), op2); + op2 = gtNewOperNode(GT_NEG, genActualType(op2->TypeGet()), op2); fgMorphTreeDone(op2); + std::swap(op2, op1); + tree->AsOp()->gtOp1 = op1; + tree->AsOp()->gtOp2 = op2; + oper = GT_ADD; tree->ChangeOper(oper); goto CM_ADD_OP; From a2a38d195228ccf460f064ab97f38d65fce208ec Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Sun, 3 May 2026 13:25:39 -0700 Subject: [PATCH 2/2] PRESERVE_VN in a few more places --- src/coreclr/jit/morph.cpp | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 6021befcea02ae..8ffff718ad2af3 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -6736,6 +6736,7 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) tree->SetOper(GT_CNS_INT); tree->AsIntConCommon()->SetIconValue(ssize_t(addrInfo.handle)); tree->gtFlags |= GTF_ICON_FTN_ADDR; + fgUpdateConstTreeValueNumber(tree); INDEBUG(tree->AsIntCon()->gtTargetHandle = reinterpret_cast(funcHandle)); break; @@ -7902,7 +7903,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA fgUpdateConstTreeValueNumber(op2); oper = GT_ADD; - tree->ChangeOper(oper); + tree->ChangeOper(oper, GenTree::PRESERVE_VN); goto CM_ADD_OP; } @@ -7919,7 +7920,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // GT_CAST(GT_SUB(0, s_1.ubyte)) if (op1->IsIntegralConst(0)) { - tree->ChangeOper(GT_NEG); + tree->ChangeOper(GT_NEG, GenTree::PRESERVE_VN); tree->gtType = genActualType(op2->TypeGet()); tree->AsOp()->gtOp1 = op2; @@ -7937,7 +7938,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA tree->AsOp()->gtOp2 = op2; oper = GT_ADD; - tree->ChangeOper(oper); + tree->ChangeOper(oper, GenTree::PRESERVE_VN); goto CM_ADD_OP; } } @@ -8065,8 +8066,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA if (transform) { - tree->ChangeOper(GT_MUL); + tree->ChangeOper(GT_MUL, GenTree::PRESERVE_VN); op2->AsDblCon()->SetDconValue(divisor); + fgUpdateConstTreeValueNumber(op2); oper = GT_MUL; goto CM_OVF_OP; @@ -8929,6 +8931,7 @@ GenTree* Compiler::fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp) { goto SKIP; // Unsupported type or invalid shift amount. } + fgUpdateConstTreeValueNumber(andMask); andOp->gtOp1 = rshiftOp->gtGetOp1(); DEBUG_DESTROY_NODE(rshiftOp->gtGetOp2()); @@ -8961,6 +8964,7 @@ GenTree* Compiler::fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp) { gtReverseCond(cmp); op2->SetIntegralValue(0); + fgUpdateConstTreeValueNumber(op2); } } } @@ -10113,6 +10117,7 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node) { ExtractEffectiveOp(GT_NOT, node, /* destroyNodes */ true); cmpOp3->AsIntConCommon()->SetIntegralValue(static_cast(mode)); + fgUpdateConstTreeValueNumber(cmpOp3); return fgMorphHWIntrinsicRequired(op1Intrin); } break; @@ -10667,7 +10672,7 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul) } else { - mul->ChangeOper(GT_NEG); + mul->ChangeOper(GT_NEG, GenTree::PRESERVE_VN); mul->AsOp()->gtOp2 = nullptr; return mul; } @@ -10999,7 +11004,7 @@ GenTree* Compiler::fgOptimizeBitwiseXor(GenTreeOp* xorOp) else if (op2->IsIntegralConst(-1)) { /* "x ^ -1" is "~x" */ - xorOp->ChangeOper(GT_NOT); + xorOp->ChangeOper(GT_NOT, GenTree::PRESERVE_VN); xorOp->gtOp2 = nullptr; DEBUG_DESTROY_NODE(op2); @@ -11018,7 +11023,7 @@ GenTree* Compiler::fgOptimizeBitwiseXor(GenTreeOp* xorOp) { // "x ^ -0.0" is "-x" - xorOp->ChangeOper(GT_NEG); + xorOp->ChangeOper(GT_NEG, GenTree::PRESERVE_VN); xorOp->gtOp2 = nullptr; DEBUG_DESTROY_NODE(op2); @@ -11327,13 +11332,16 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree, bool* optAssertionPropD /* Change '(val + iadd) * imul' -> '(val * imul) + (iadd * imul)' */ oper = GT_ADD; - tree->ChangeOper(oper); + tree->ChangeOper(oper, GenTree::PRESERVE_VN); op2->AsIntCon()->SetValueTruncating(iadd * imul); + fgUpdateConstTreeValueNumber(op2); + // changing from (val + iadd) to (val * imul), so don't preserve VN op1->ChangeOper(GT_MUL); add->AsIntCon()->SetIconValue(imul); + fgValueNumberTreeConst(add); } } @@ -11372,13 +11380,17 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree, bool* optAssertionPropD /* Change "(val + iadd) << ishf" into "(val<ChangeOper(GT_ADD); + tree->ChangeOper(GT_ADD, GenTree::PRESERVE_VN); // we are reusing the shift amount node here, but the type we want is that of the shift result op2->gtType = op1->gtType; op2->AsIntConCommon()->SetValueTruncating(iadd << ishf); + fgUpdateConstTreeValueNumber(op2); + + // changing from (val + iadd) to (val << ishf), so don't preserve VN op1->ChangeOper(GT_LSH); cns->AsIntConCommon()->SetIconValue(ishf); + fgUpdateConstTreeValueNumber(cns); } } @@ -12400,7 +12412,7 @@ GenTree* Compiler::fgRecognizeAndMorphBitwiseRotation(GenTree* tree) { tree->AsOp()->gtOp1 = rotatedValue; tree->AsOp()->gtOp2 = rotateIndex; - tree->ChangeOper(rotateOp); + tree->ChangeOper(rotateOp, GenTree::PRESERVE_VN); unsigned childFlags = 0; for (GenTree* op : tree->Operands())