Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f5bc205
tmp
EgorBo Dec 2, 2021
2757d64
Merge branch 'main' of https://github.com/dotnet/runtime into span-bo…
EgorBo Dec 14, 2021
1556eb8
Handle bound checks for ((uint)index cmp CNS) pattern
EgorBo Dec 15, 2021
be074e4
Fix typo
EgorBo Dec 15, 2021
1b14746
Fix build error
EgorBo Dec 15, 2021
31ab6d5
Fix 32bit platforms
EgorBo Dec 16, 2021
1b06196
Fix 32bit again
EgorBo Dec 16, 2021
81b5232
Update morph.cpp
EgorBo Dec 16, 2021
b13b852
Update morph.cpp
EgorBo Dec 16, 2021
fc5ceb2
Clean up
EgorBo Dec 17, 2021
1e14f8e
Clean up
EgorBo Dec 17, 2021
53a6405
Move to fgOptimizeRelationalComparisonWithCasts
EgorBo Dec 17, 2021
747339c
fix 32bit again
EgorBo Dec 17, 2021
f4b1ffa
fix SetUnsigned
EgorBo Dec 17, 2021
58f4f68
Clean up
EgorBo Dec 18, 2021
b9e68b0
Update morph.cpp
EgorBo Dec 18, 2021
929e53b
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Dec 19, 2021
f4e82ce
test
EgorBo Dec 19, 2021
abc7d54
Introduce O1K_CONSTANT_LOOP_BND_UN
EgorBo Dec 19, 2021
3bf8534
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Dec 19, 2021
aecf6a4
Update assertionprop.cpp
EgorBo Dec 20, 2021
96376f6
Merge branch 'bound-checks-constant-len' of https://github.com/EgorBo…
EgorBo Jan 15, 2022
1c9f406
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Jan 27, 2022
ff58212
resolve conflicts
EgorBo Jan 27, 2022
61b1fa1
fix newline
EgorBo Jan 27, 2022
8ba164d
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Jan 27, 2022
e4fff61
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Feb 15, 2022
f2aa51a
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Feb 18, 2022
58cec64
Address feedback
EgorBo Feb 18, 2022
10d9a0d
Apply suggestions from code review
EgorBo Feb 24, 2022
20505fd
Merge branch 'main' of https://github.com/dotnet/runtime into bound-c…
EgorBo Feb 24, 2022
a643eb6
Apply suggestions
EgorBo Feb 24, 2022
ffadcd7
use bashtoconst
EgorBo Feb 24, 2022
d2518c2
use bashtoconst
EgorBo Feb 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Handle bound checks for ((uint)index cmp CNS) pattern
  • Loading branch information
EgorBo committed Dec 15, 2021
commit 1556eb8faaa29ab202884535837a67a5b2751d8e
14 changes: 3 additions & 11 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,17 +1081,9 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
printf("MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal));
assert(curAssertion->op2.u1.iconFlags != GTF_EMPTY);
}
else if (curAssertion->op1.kind == O1K_BOUND_OPER_BND)
{
assert(!optLocalAssertionProp);
vnStore->vnDump(this, curAssertion->op2.vn);
}
else if (curAssertion->op1.kind == O1K_BOUND_LOOP_BND)
{
assert(!optLocalAssertionProp);
vnStore->vnDump(this, curAssertion->op2.vn);
}
else if ((curAssertion->op1.kind == O1K_CONSTANT_LOOP_BND) ||
else if ((curAssertion->op1.kind == O1K_BOUND_OPER_BND) ||
(curAssertion->op1.kind == O1K_BOUND_LOOP_BND) ||
(curAssertion->op1.kind == O1K_CONSTANT_LOOP_BND) ||
(curAssertion->op1.kind == O1K_CONSTANT_LOOP_BND_UN))
{
assert(!optLocalAssertionProp);
Expand Down
32 changes: 29 additions & 3 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12093,9 +12093,8 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
{
tree = fgOptimizeRelationalComparisonWithConst(tree->AsOp());
oper = tree->OperGet();

assert(op1 == tree->AsOp()->gtGetOp1());
assert(op2 == tree->AsOp()->gtGetOp2());
op1 = tree->AsOp()->gtGetOp1();
op2 = tree->AsOp()->gtGetOp2();
}

COMPARE:
Expand Down Expand Up @@ -13710,6 +13709,33 @@ GenTree* Compiler::fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp)
}
}
}
else if (fgGlobalMorph && !cmp->IsUnsigned() && (op2Value >= 0) && cmp->OperIs(GT_LE, GT_LT, GT_GE, GT_GE) &&
op1->OperIs(GT_CAST) && varTypeIsLong(op1->CastToType()) && op1->gtGetOp1()->TypeIs(TYP_INT) &&
op1->IsUnsigned() && ((size_t)op2Value <= UINT_MAX))
{
// Transform
//
// * GE int
// +--* CAST long <- ulong <- uint
// | \--* X int
// \--* CNS_INT long
//
// to
//
// * GE_un int
// +--* X int
// \--* CNS_INT int
//
// TODO: handle small type casts. Also we can fold the whole condition
// if op2Value doesn't fit into CastToType.
//
cmp->gtOp1 = op1->gtGetOp1();
cmp->gtFlags |= GTF_UNSIGNED;
assert(op1->TypeIs(TYP_LONG) && op2->TypeIs(TYP_LONG));
op2->ChangeType(TYP_INT);
DEBUG_DESTROY_NODE(op1);
op1 = cmp->gtGetOp1();
}

if (!cmp->OperIs(oper))
{
Expand Down
48 changes: 9 additions & 39 deletions src/coreclr/jit/rangecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,9 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree*
// Get the range for this index.
Range range = GetRange(block, treeIndex, false DEBUGARG(0));

Limit lowerLimit = range.LowerLimit();
Limit upperLimit = range.UpperLimit();

// If upper or lower limit is found to be unknown (top), or it was found to
// be unknown because of over budget or a deep search, then return early.
if (lowerLimit.IsUnknown() || upperLimit.IsUnknown())
if (range.LowerLimit().IsUnknown() || range.UpperLimit().IsUnknown())
{
// Note: If we had stack depth too deep in the GetRange call, we'd be
// too deep even in the DoesOverflow call. So return early.
Expand All @@ -287,18 +284,8 @@ void RangeCheck::OptimizeRangeCheck(BasicBlock* block, Statement* stmt, GenTree*

if (DoesOverflow(block, treeIndex))
{
// Actually, we don't overflow if both upper and lower limits are known
// to be constants
if (lowerLimit.IsConstant() && upperLimit.IsConstant() && (lowerLimit.cns <= upperLimit.cns) &&
(lowerLimit.cns > 0))
{
JITDUMP("Upper and lower limits are constants => we don't overflow.\n");
}
else
{
JITDUMP("Method determined to overflow.\n");
return;
}
JITDUMP("Method determined to overflow.\n");
return;
}

JITDUMP("Range value %s\n", range.ToString(m_pCompiler->getAllocatorDebugOnly()));
Expand Down Expand Up @@ -679,7 +666,7 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
}
}
// Current assertion is of the form (i < 100) != 0
else if (curAssertion->IsConstantBound())
else if (curAssertion->IsConstantBound() || curAssertion->IsConstantBoundUnsigned())
{
ValueNumStore::ConstantBoundInfo info;

Expand All @@ -692,27 +679,9 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
continue;
}

limit = Limit(Limit::keConstant, info.constVal);
cmpOper = (genTreeOps)info.cmpOper;
}
// Current assertion is of the form (i < 100) != 0
else if (curAssertion->IsConstantBoundUnsigned())
{
ValueNumStore::ConstantBoundInfo info;

//// Get the info as "i", "<" and "100"
m_pCompiler->vnStore->GetConstantBoundInfo(curAssertion->op1.vn, &info);

// If we don't have the same variable we are comparing against, bail.
if (normalLclVN != info.cmpOpVN)
{
continue;
}

limit = Limit(Limit::keConstant, info.constVal);
assert(info.cmpOper == VNF_GE_UN);
cmpOper = GT_GE;
isUnsigned = true;
limit = Limit(Limit::keConstant, info.constVal);
cmpOper = (genTreeOps)info.cmpOper;
isUnsigned = info.isUnsigned;
}
// Current assertion is of the form i == 100
else if (curAssertion->IsConstantInt32Assertion())
Expand Down Expand Up @@ -870,13 +839,14 @@ void RangeCheck::MergeEdgeAssertions(ValueNum normalLclVN, ASSERT_VALARG_TP asse
pRange->uLimit = limit;
if (isUnsigned)
{
pRange->lLimit = Limit(Limit::keConstant, 1);
pRange->lLimit = Limit(Limit::keConstant, 0);
}
break;

case GT_GT:
case GT_GE:
pRange->lLimit = limit;
assert(!isUnsigned);
break;

case GT_EQ:
Expand Down
36 changes: 23 additions & 13 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4795,7 +4795,7 @@ bool ValueNumStore::IsVNConstantBound(ValueNum vn)

bool ValueNumStore::IsVNConstantBoundUnsigned(ValueNum vn)
{
// Do we have "var < 100"?
// Do we have "(unsigned type)var < 100"? which is an equivalent for "var >= 0 && var < 100"
if (vn == NoVN)
{
return false;
Expand All @@ -4806,7 +4806,7 @@ bool ValueNumStore::IsVNConstantBoundUnsigned(ValueNum vn)
{
return false;
}
if (funcAttr.m_func != VNF_GE_UN)
if ((funcAttr.m_func != VNF_GE_UN) && (funcAttr.m_func != VNF_GT_UN))
{
return false;
}
Expand All @@ -4817,7 +4817,8 @@ bool ValueNumStore::IsVNConstantBoundUnsigned(ValueNum vn)

void ValueNumStore::GetConstantBoundInfo(ValueNum vn, ConstantBoundInfo* info)
{
//assert(IsVNConstantBound(vn));
bool isUnsignedCnsBnd = IsVNConstantBoundUnsigned(vn);
assert(IsVNConstantBound(vn) || isUnsignedCnsBnd);
assert(info);

// Do we have var < 100?
Expand All @@ -4826,27 +4827,36 @@ void ValueNumStore::GetConstantBoundInfo(ValueNum vn, ConstantBoundInfo* info)

bool isOp1Const = IsVNInt32Constant(funcAttr.m_args[1]);

genTreeOps op;
if (funcAttr.m_func == VNF_GT_UN)
{
assert(isUnsignedCnsBnd);
op = GT_GT;
}
else if (funcAttr.m_func == VNF_GE_UN)
{
assert(isUnsignedCnsBnd);
op = GT_GE;
}
else
{
assert(!isUnsignedCnsBnd);
op = (genTreeOps)funcAttr.m_func;
}

if (isOp1Const)
{
info->cmpOper = funcAttr.m_func;
info->cmpOper = op;
info->cmpOpVN = funcAttr.m_args[0];
info->constVal = GetConstantInt32(funcAttr.m_args[1]);
}
else
{
genTreeOps op = (genTreeOps)funcAttr.m_func;
if (funcAttr.m_func == VNF_GT_UN)
{
op = GT_GT;
}
else if (funcAttr.m_func == VNF_GE_UN)
{
op = GT_GE;
}
info->cmpOper = GenTree::SwapRelop(op);
info->cmpOpVN = funcAttr.m_args[1];
info->constVal = GetConstantInt32(funcAttr.m_args[0]);
}
info->isUnsigned = isUnsignedCnsBnd;
}

//------------------------------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/jit/valuenum.h
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,9 @@ class ValueNumStore
int constVal;
unsigned cmpOper;
ValueNum cmpOpVN;
bool isUnsigned;

ConstantBoundInfo() : constVal(0), cmpOper(GT_NONE), cmpOpVN(NoVN)
ConstantBoundInfo() : constVal(0), cmpOper(GT_NONE), cmpOpVN(NoVN), isUnsigned(false)
{
}

Expand Down Expand Up @@ -799,7 +800,8 @@ class ValueNumStore
// Return true with any Relop except for == and != and one operand has to be a 32-bit integer constant.
bool IsVNConstantBound(ValueNum vn);

// Return true with any Relop except for == and != and one operand has to be a 32-bit integer constant.
// Return true with any Relop except for == and != and one operand has to be a 32-bit integer constant
// with (uint) cast for the other operand
bool IsVNConstantBoundUnsigned(ValueNum vn);

// If "vn" is constant bound, then populate the "info" fields for constVal, cmpOp, cmpOper.
Expand Down