From 9e47a3d42081944940210616c4adc2347ee3755f Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Sun, 24 May 2026 05:17:54 +0200 Subject: [PATCH 1/5] * '(A & pow2) == pow2' -> '(A & pow2) != 0' * '(A & pow2) != pow2' -> '(A & pow2) == 0' --- src/coreclr/jit/morph.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index f5dd9fe9bef06a..7f06ed18db981f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8783,6 +8783,20 @@ GenTree* Compiler::fgOptimizeRelationalComparison(GenTreeOp* cmp) { assert(cmp->OperIsCmpCompare()); + // Canonicalize + // '(A & pow2) == pow2' -> '(A & pow2) != 0' + // '(A & pow2) != pow2' -> '(A & pow2) == 0' + if (cmp->OperIs(GT_EQ, GT_NE) && cmp->gtGetOp1()->OperIs(GT_AND) && + cmp->gtGetOp1()->gtGetOp2()->IsIntegralConst() && cmp->gtGetOp2()->IsIntegralConstUnsignedPow2()) + { + if (GenTree::Compare(cmp->gtGetOp1()->gtGetOp2(), cmp->gtGetOp2())) + { + cmp->SetOper(GenTree::ReverseRelop(cmp->OperGet()), GenTree::PRESERVE_VN); + cmp->gtGetOp2()->BashToZeroConst(cmp->gtGetOp2()->TypeGet()); + fgUpdateConstTreeValueNumber(cmp->gtGetOp2()); + } + } + GenTree* tree = cmp; // TODO-CQ: Should be called for all comparisons From bc71b6f4f860679d29cdfc5277d3dc188e7de88a Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Mon, 25 May 2026 01:04:30 +0200 Subject: [PATCH 2/5] * feedback --- src/coreclr/jit/morph.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 7f06ed18db981f..e689d277140244 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8786,8 +8786,7 @@ GenTree* Compiler::fgOptimizeRelationalComparison(GenTreeOp* cmp) // Canonicalize // '(A & pow2) == pow2' -> '(A & pow2) != 0' // '(A & pow2) != pow2' -> '(A & pow2) == 0' - if (cmp->OperIs(GT_EQ, GT_NE) && cmp->gtGetOp1()->OperIs(GT_AND) && - cmp->gtGetOp1()->gtGetOp2()->IsIntegralConst() && cmp->gtGetOp2()->IsIntegralConstUnsignedPow2()) + if (cmp->OperIs(GT_EQ, GT_NE) && cmp->gtGetOp1()->OperIs(GT_AND) && cmp->gtGetOp2()->IsIntegralConstUnsignedPow2()) { if (GenTree::Compare(cmp->gtGetOp1()->gtGetOp2(), cmp->gtGetOp2())) { From 71ad99d0f6b102160517f08902ecb0a7ddf0e818 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Tue, 2 Jun 2026 22:21:34 +0200 Subject: [PATCH 3/5] * feedback --- src/coreclr/jit/morph.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index f691a1363b1b94..f8f3efa7ad277c 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8807,8 +8807,7 @@ GenTree* Compiler::fgOptimizeRelationalComparison(GenTreeOp* cmp) if (GenTree::Compare(cmp->gtGetOp1()->gtGetOp2(), cmp->gtGetOp2())) { cmp->SetOper(GenTree::ReverseRelop(cmp->OperGet()), GenTree::PRESERVE_VN); - cmp->gtGetOp2()->BashToZeroConst(cmp->gtGetOp2()->TypeGet()); - fgUpdateConstTreeValueNumber(cmp->gtGetOp2()); + cmp->gtOp2 = gtNewIconNodeWithVN(this, 0, cmp->gtGetOp2()->TypeGet()); } } From 6b7f24330b5ac5d310052c59ad5c5741b9be83f1 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Wed, 3 Jun 2026 01:01:23 +0200 Subject: [PATCH 4/5] * add missing fgMorphTreeDone for gtNewIconNodeWithVN --- src/coreclr/jit/morph.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index f8f3efa7ad277c..c2103c1b37de1f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8808,6 +8808,11 @@ GenTree* Compiler::fgOptimizeRelationalComparison(GenTreeOp* cmp) { cmp->SetOper(GenTree::ReverseRelop(cmp->OperGet()), GenTree::PRESERVE_VN); cmp->gtOp2 = gtNewIconNodeWithVN(this, 0, cmp->gtGetOp2()->TypeGet()); + + if (fgGlobalMorph) + { + fgMorphTreeDone(cmp->gtOp2); + } } } From 70b794bcfb744eceb0cd69e723ba8e91ca428d84 Mon Sep 17 00:00:00 2001 From: BoyBaykiller Date: Wed, 3 Jun 2026 15:26:48 +0200 Subject: [PATCH 5/5] * switch to gtNewZeroConNode + fgUpdateConstTreeValueNumber + fgMorphTreeDone --- src/coreclr/jit/morph.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c2103c1b37de1f..b3dfa5bfecddda 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8807,7 +8807,8 @@ GenTree* Compiler::fgOptimizeRelationalComparison(GenTreeOp* cmp) if (GenTree::Compare(cmp->gtGetOp1()->gtGetOp2(), cmp->gtGetOp2())) { cmp->SetOper(GenTree::ReverseRelop(cmp->OperGet()), GenTree::PRESERVE_VN); - cmp->gtOp2 = gtNewIconNodeWithVN(this, 0, cmp->gtGetOp2()->TypeGet()); + cmp->gtOp2 = gtNewZeroConNode(cmp->gtGetOp2()->TypeGet()); + fgUpdateConstTreeValueNumber(cmp->gtGetOp2()); if (fgGlobalMorph) {