diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index e55073378cddd9..f3f87ed8110da7 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -3337,6 +3337,7 @@ struct GenTreeIntConCommon : public GenTree inline ssize_t IconValue() const; inline void SetIconValue(ssize_t val); inline INT64 IntegralValue() const; + inline UINT64 UnsignedIntegralValue() const; inline void SetIntegralValue(int64_t value); template @@ -3540,6 +3541,13 @@ inline INT64 GenTreeIntConCommon::IntegralValue() const #endif // TARGET_64BIT } +inline UINT64 GenTreeIntConCommon::UnsignedIntegralValue() const +{ + INT64 signExtended = IntegralValue(); + UINT64 zeroExtended = TypeIs(TYP_LONG) ? signExtended : (uint32_t)signExtended; + return zeroExtended; +} + inline void GenTreeIntConCommon::SetIntegralValue(int64_t value) { #ifdef TARGET_64BIT diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 7caba07734be6d..bcec7a85d7c9ff 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -7768,6 +7768,17 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA case GT_EQ: case GT_NE: + // Change "CNS relop op2" to "op2 relop* CNS" + if (op1->IsIntegralConst() && tree->OperIsCompare() && gtCanSwapOrder(op1, op2)) + { + std::swap(tree->AsOp()->gtOp1, tree->AsOp()->gtOp2); + tree->gtOper = GenTree::SwapRelop(tree->OperGet()); + + oper = tree->OperGet(); + op1 = tree->gtGetOp1(); + op2 = tree->gtGetOp2(); + } + if (op2->IsIntegralConst()) { tree = fgOptimizeEqualityComparisonWithConst(tree->AsOp()); @@ -8748,6 +8759,20 @@ GenTree* Compiler::fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp) GenTree* op1 = cmp->gtGetOp1(); GenTreeIntConCommon* op2 = cmp->gtGetOp2()->AsIntConCommon(); + // Canonicalize + // '(A & pow2) == pow2' -> '(A & pow2) != 0' + // '(A & pow2) != pow2' -> '(A & pow2) == 0' + if (op1->OperIs(GT_AND) && op1->gtGetOp2()->IsIntegralConst()) + { + if (BitOperations::PopCount(op2->UnsignedIntegralValue()) == 1 && + (op1->gtGetOp2()->AsIntConCommon()->IntegralValue() == op2->IntegralValue())) + { + cmp->SetOper(cmp->OperIs(GT_EQ) ? GT_NE : GT_EQ, GenTree::PRESERVE_VN); + op2->SetIntegralValue(0); + fgUpdateConstTreeValueNumber(op2); + } + } + // Fold: (-(x)) == 0 -> x == 0 (avoid neg on compare-to-zero) if (op1->OperIs(GT_NEG) && !op1->gtOverflowEx()) {