Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
68 changes: 34 additions & 34 deletions src/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,12 +627,12 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
vnStore->vnDump(this, curAssertion->op1.bnd.vnLen);
printf("]");
}
else if (curAssertion->op1.kind == O1K_ARRLEN_OPER_BND)
else if (curAssertion->op1.kind == O1K_BOUND_OPER_BND)
{
printf("Oper_Bnd");
vnStore->vnDump(this, curAssertion->op1.vn);
}
else if (curAssertion->op1.kind == O1K_ARRLEN_LOOP_BND)
else if (curAssertion->op1.kind == O1K_BOUND_LOOP_BND)
{
printf("Loop_Bnd");
vnStore->vnDump(this, curAssertion->op1.vn);
Expand Down Expand Up @@ -711,12 +711,12 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
printf("MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal));
assert(curAssertion->op2.u1.iconFlags != 0);
}
else if (curAssertion->op1.kind == O1K_ARRLEN_OPER_BND)
else if (curAssertion->op1.kind == O1K_BOUND_OPER_BND)
{
assert(!optLocalAssertionProp);
vnStore->vnDump(this, curAssertion->op2.vn);
}
else if (curAssertion->op1.kind == O1K_ARRLEN_LOOP_BND)
else if (curAssertion->op1.kind == O1K_BOUND_LOOP_BND)
{
assert(!optLocalAssertionProp);
vnStore->vnDump(this, curAssertion->op2.vn);
Expand Down Expand Up @@ -1625,8 +1625,8 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion)
case O1K_ARR_BND:
// It would be good to check that bnd.vnIdx and bnd.vnLen are valid value numbers.
break;
case O1K_ARRLEN_OPER_BND:
case O1K_ARRLEN_LOOP_BND:
case O1K_BOUND_OPER_BND:
case O1K_BOUND_LOOP_BND:
case O1K_CONSTANT_LOOP_BND:
case O1K_VALUE_NUMBER:
assert(!optLocalAssertionProp);
Expand Down Expand Up @@ -1702,7 +1702,7 @@ void Compiler::optCreateComplementaryAssertion(AssertionIndex assertionIndex, Ge
}

AssertionDsc& candidateAssertion = *optGetAssertion(assertionIndex);
if (candidateAssertion.op1.kind == O1K_ARRLEN_OPER_BND || candidateAssertion.op1.kind == O1K_ARRLEN_LOOP_BND ||
if (candidateAssertion.op1.kind == O1K_BOUND_OPER_BND || candidateAssertion.op1.kind == O1K_BOUND_LOOP_BND ||
candidateAssertion.op1.kind == O1K_CONSTANT_LOOP_BND)
{
AssertionDsc dsc = candidateAssertion;
Expand Down Expand Up @@ -1768,17 +1768,17 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTreePtr tree)

ValueNum vn = op1->gtVNPair.GetConservative();

ValueNumStore::ArrLenUnsignedBoundInfo arrLenUnsignedBnd;
// Cases where op1 holds the condition with array arithmetic and op2 is 0.
// Loop condition like: "i < a.len +/-k == 0"
// Assertion: "i < a.len +/- k == 0"
if (vnStore->IsVNArrLenArithBound(vn) &&
ValueNumStore::UnsignedCompareCheckedBoundInfo unsignedCompareBnd;
// Cases where op1 holds the upper bound arithmetic and op2 is 0.
// Loop condition like: "i < bnd +/-k == 0"
// Assertion: "i < bnd +/- k == 0"
if (vnStore->IsVNCompareCheckedBoundArith(vn) &&
op2->gtVNPair.GetConservative() == vnStore->VNZeroForType(op2->TypeGet()) &&
(relop->gtOper == GT_EQ || relop->gtOper == GT_NE))
{
AssertionDsc dsc;
dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL;
dsc.op1.kind = O1K_ARRLEN_OPER_BND;
dsc.op1.kind = O1K_BOUND_OPER_BND;
dsc.op1.vn = vn;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet());
Expand All @@ -1788,16 +1788,16 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTreePtr tree)
optCreateComplementaryAssertion(index, nullptr, nullptr);
return index;
}
// Cases where op1 holds the condition array length and op2 is 0.
// Loop condition like: "i < a.len == 0"
// Assertion: "i < a.len == false"
else if (vnStore->IsVNArrLenBound(vn) &&
// Cases where op1 holds the upper bound and op2 is 0.
// Loop condition like: "i < bnd == 0"
// Assertion: "i < bnd == false"
else if (vnStore->IsVNCompareCheckedBound(vn) &&
(op2->gtVNPair.GetConservative() == vnStore->VNZeroForType(op2->TypeGet())) &&
(relop->gtOper == GT_EQ || relop->gtOper == GT_NE))
{
AssertionDsc dsc;
dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL;
dsc.op1.kind = O1K_ARRLEN_LOOP_BND;
dsc.op1.kind = O1K_BOUND_LOOP_BND;
dsc.op1.vn = vn;
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet());
Expand All @@ -1807,14 +1807,14 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTreePtr tree)
optCreateComplementaryAssertion(index, nullptr, nullptr);
return index;
}
// Cases where op1 holds the lhs of the condition op2 holds rhs.
// Loop condition like "i < a.len"
// Assertion: "i < a.len != 0"
else if (vnStore->IsVNArrLenBound(relop->gtVNPair.GetConservative()))
// Cases where op1 holds the lhs of the condition op2 holds the bound.
// Loop condition like "i < bnd"
// Assertion: "i < bnd != 0"
else if (vnStore->IsVNCompareCheckedBound(relop->gtVNPair.GetConservative()))
{
AssertionDsc dsc;
dsc.assertionKind = OAK_NOT_EQUAL;
dsc.op1.kind = O1K_ARRLEN_LOOP_BND;
dsc.op1.kind = O1K_BOUND_LOOP_BND;
dsc.op1.vn = relop->gtVNPair.GetConservative();
dsc.op2.kind = O2K_CONST_INT;
dsc.op2.vn = vnStore->VNZeroForType(TYP_INT);
Expand All @@ -1824,28 +1824,28 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTreePtr tree)
optCreateComplementaryAssertion(index, nullptr, nullptr);
return index;
}
// Loop condition like "(uint)i < (uint)a.len" or equivalent
// Assertion: "no throw" since this condition guarantees that i is both >= 0 and < a.len (on the appropiate edge)
else if (vnStore->IsVNArrLenUnsignedBound(relop->gtVNPair.GetConservative(), &arrLenUnsignedBnd))
// Loop condition like "(uint)i < (uint)bnd" or equivalent
// Assertion: "no throw" since this condition guarantees that i is both >= 0 and < bnd (on the appropiate edge)
else if (vnStore->IsVNUnsignedCompareCheckedBound(relop->gtVNPair.GetConservative(), &unsignedCompareBnd))
{
assert(arrLenUnsignedBnd.vnIdx != ValueNumStore::NoVN);
assert((arrLenUnsignedBnd.cmpOper == VNF_LT_UN) || (arrLenUnsignedBnd.cmpOper == VNF_GE_UN));
assert(vnStore->IsVNArrLen(arrLenUnsignedBnd.vnLen));
assert(unsignedCompareBnd.vnIdx != ValueNumStore::NoVN);
assert((unsignedCompareBnd.cmpOper == VNF_LT_UN) || (unsignedCompareBnd.cmpOper == VNF_GE_UN));
assert(vnStore->IsVNCheckedBound(unsignedCompareBnd.vnBound));

AssertionDsc dsc;
dsc.assertionKind = OAK_NO_THROW;
dsc.op1.kind = O1K_ARR_BND;
dsc.op1.vn = relop->gtVNPair.GetConservative();
dsc.op1.bnd.vnIdx = arrLenUnsignedBnd.vnIdx;
dsc.op1.bnd.vnLen = arrLenUnsignedBnd.vnLen;
dsc.op1.bnd.vnIdx = unsignedCompareBnd.vnIdx;
dsc.op1.bnd.vnLen = unsignedCompareBnd.vnBound;
dsc.op2.kind = O2K_INVALID;
dsc.op2.vn = ValueNumStore::NoVN;

AssertionIndex index = optAddAssertion(&dsc);
if (arrLenUnsignedBnd.cmpOper == VNF_GE_UN)
if (unsignedCompareBnd.cmpOper == VNF_GE_UN)
{
// By default JTRUE generated assertions hold on the "jump" edge. We have i >= a.len but we're really
// after i < a.len so we need to change the assertion edge to "next".
// By default JTRUE generated assertions hold on the "jump" edge. We have i >= bnd but we're really
// after i < bnd so we need to change the assertion edge to "next".
return AssertionInfo::ForNextEdge(index);
}
return index;
Expand Down
20 changes: 10 additions & 10 deletions src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5493,11 +5493,11 @@ class Compiler

typedef SimplerHashTable<GenTreePtr, PtrKeyFuncs<GenTree>, GenTreePtr, JitSimplerHashBehavior> NodeToNodeMap;

NodeToNodeMap* optCseArrLenMap; // Maps array length nodes to ancestor compares that should be
// re-numbered with the array length to improve range check elimination
NodeToNodeMap* optCseCheckedBoundMap; // Maps bound nodes to ancestor compares that should be
// re-numbered with the bound to improve range check elimination

// Given a compare, look for a cse candidate arrlen feeding it and add a map entry if found.
void optCseUpdateArrLenMap(GenTreePtr compare);
// Given a compare, look for a cse candidate checked bound feeding it and add a map entry if found.
void optCseUpdateCheckedBoundMap(GenTreePtr compare);

void optCSEstop();

Expand Down Expand Up @@ -5726,8 +5726,8 @@ class Compiler
O1K_INVALID,
O1K_LCLVAR,
O1K_ARR_BND,
O1K_ARRLEN_OPER_BND,
O1K_ARRLEN_LOOP_BND,
O1K_BOUND_OPER_BND,
O1K_BOUND_LOOP_BND,
O1K_CONSTANT_LOOP_BND,
O1K_EXACT_TYPE,
O1K_SUBTYPE,
Expand Down Expand Up @@ -5792,13 +5792,13 @@ class Compiler
};
} op2;

bool IsArrLenArithBound()
bool IsCheckedBoundArithBound()
{
return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_ARRLEN_OPER_BND);
return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_OPER_BND);
}
bool IsArrLenBound()
bool IsCheckedBoundBound()
{
return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_ARRLEN_LOOP_BND);
return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_LOOP_BND);
}
bool IsConstantBound()
{
Expand Down
7 changes: 7 additions & 0 deletions src/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4104,6 +4104,13 @@ inline void* Compiler::compGetMem(size_t sz, CompMemKind cmk)

#endif

// Wrapper for Compiler::compGetMem that can be forward-declared for use in template
// types which Compiler depends on but which need to allocate heap memory.
inline void* compGetMem(Compiler* comp, size_t sz)
{
return comp->compGetMem(sz);
}

/*****************************************************************************
*
* A common memory allocation for arrays of structures involves the
Expand Down
Loading