Skip to content

Commit

Permalink
Generalized both sides to intervals (dotnet#70145)
Browse files Browse the repository at this point in the history
  • Loading branch information
SkiFoD committed Jun 11, 2022
1 parent 2da383c commit 01d7d48
Showing 1 changed file with 41 additions and 71 deletions.
112 changes: 41 additions & 71 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11410,7 +11410,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
{
if (op2->IsIntegralConst() || op1->IsIntegralConst())
{
if (tree->OperIs(GT_GT, GT_LT))
if (tree->OperIs(GT_GT, GT_LT, GT_LE, GT_GE))
{
tree = fgOptimizeRelationalComparisonWithFullRangeConst(tree->AsOp());
if (tree->OperIs(GT_CNS_INT, GT_COMMA))
Expand Down Expand Up @@ -12664,92 +12664,62 @@ GenTree* Compiler::fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp)
//
GenTree* Compiler::fgOptimizeRelationalComparisonWithFullRangeConst(GenTreeOp* cmp)
{
assert(cmp->OperIs(GT_LT, GT_GT));
assert(cmp->gtGetOp2()->IsIntegralConst() || cmp->gtGetOp1()->IsIntegralConst());

GenTree* conNode = cmp->gtGetOp2()->IsIntegralConst() ? cmp->gtGetOp2() : cmp->gtGetOp1();
GenTree* varNode = cmp->gtGetOp2()->IsIntegralConst() ? cmp->gtGetOp1() : cmp->gtGetOp2();

IntegralRange valRange = IntegralRange::ForNode(varNode, this);

#if defined(HOST_X86) || defined(HOST_ARM)
ssize_t valMin = (int32_t)IntegralRange::SymbolicToRealValue(valRange.GetLowerBound());
ssize_t valMax = (int32_t)IntegralRange::SymbolicToRealValue(valRange.GetUpperBound());
#else
ssize_t valMin = IntegralRange::SymbolicToRealValue(valRange.GetLowerBound());
ssize_t valMax = IntegralRange::SymbolicToRealValue(valRange.GetUpperBound());
#endif
int64_t lhsMin;
int64_t lhsMax;
if (cmp->gtGetOp1()->IsIntegralConst())
{
lhsMin = cmp->gtGetOp1()->AsIntConCommon()->IntegralValue();
lhsMax = lhsMin;
}
else
{
IntegralRange lhsRange = IntegralRange::ForNode(cmp->gtGetOp1(), this);
lhsMin = IntegralRange::SymbolicToRealValue(lhsRange.GetLowerBound());
lhsMax = IntegralRange::SymbolicToRealValue(lhsRange.GetUpperBound());
}

bool fold = false;
// Folds
// 1. byte x <= 0 => false
// 2. short x <= short.MinValue => false
// 3. ushort x <= ushort.MinValue => false
// 4. int x <= int.MinValue => false
// 5. uint x <= uint.MinValue => false
// 6. long x <= long.MinValue => false
// 7. ulong x <= ulong.MinValue => false
//
// 8. byte x >= byte.MaxValue => false
// 9. short x <= short.MinValue => false
// 10. ushort x <= ushort.MinValue => false
// 11. int x >= int.MaxValue => false
// 12. int x >= int.MaxValue => false
// 13. long x >= long.MaxValue => false
// 14. long x >= long.MaxValue => false
//
// when const is RHS:
int64_t rhsMin;
int64_t rhsMax;
if (cmp->gtGetOp2()->IsIntegralConst())
{
if ((cmp->OperIs(GT_GT) && conNode->IsIntegralConst(valMax)) ||
(cmp->OperIs(GT_LT) && conNode->IsIntegralConst(valMin)))
{
fold = true;
}

// when const is RHS and cmp is unsigned
if (cmp->IsUnsigned())
{
if (cmp->OperIs(GT_GT) && conNode->IsIntegralConst(-1))
{
fold = true;
}
}
rhsMin = cmp->gtGetOp2()->AsIntConCommon()->IntegralValue();
rhsMax = rhsMin;
}
// when const is LHS:
else if (cmp->gtGetOp1()->IsIntegralConst())
else
{
if ((cmp->OperIs(GT_GT) && conNode->IsIntegralConst(valMin)) ||
(cmp->OperIs(GT_LT) && conNode->IsIntegralConst(valMax)))
{
fold = true;
}

// when const is LHS and cmp is unsigned
if (cmp->IsUnsigned())
{
if (cmp->OperIs(GT_LT) && conNode->IsIntegralConst(-1))
{
fold = true;
}
}
IntegralRange rhsRange = IntegralRange::ForNode(cmp->gtGetOp2(), this);
rhsMin = IntegralRange::SymbolicToRealValue(rhsRange.GetLowerBound());
rhsMax = IntegralRange::SymbolicToRealValue(rhsRange.GetUpperBound());
}

if (fold)
genTreeOps op = cmp->gtOper;
if ((op != GT_LT) && (op != GT_LE))
{
GenTree* ret = gtNewZeroConNode(TYP_INT);
op = GenTree::SwapRelop(op);
std::swap(lhsMin, rhsMin);
std::swap(lhsMax, rhsMax);
}

ret->SetVNsFromNode(cmp);
int64_t lefOpValue = lhsMin;
int64_t rightOpValue = rhsMax;

GenTree* cmpSideEffects = nullptr;
if (cmp->IsUnsigned() && lefOpValue == -1 && lhsMax == -1)
{
rightOpValue = -1;
}

gtExtractSideEffList(cmp, &cmpSideEffects);
if ((op == GT_LT && lefOpValue == rightOpValue) || (op == GT_LE && lefOpValue > rightOpValue))
{
GenTree* ret = gtNewZeroConNode(TYP_INT);

if (cmpSideEffects != nullptr)
if (gtTreeHasSideEffects(cmp, GTF_SIDE_EFFECT))
{
ret = gtNewOperNode(GT_COMMA, TYP_INT, cmpSideEffects, ret);
return cmp;
}

ret->SetVNsFromNode(cmp);

DEBUG_DESTROY_NODE(cmp);

INDEBUG(ret->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
Expand Down

0 comments on commit 01d7d48

Please sign in to comment.