Skip to content

Commit

Permalink
Sign to zero extend cast
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedn committed Mar 8, 2019
1 parent 42bacd6 commit e0a6e91
Showing 1 changed file with 69 additions and 11 deletions.
80 changes: 69 additions & 11 deletions src/jit/rangecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,51 @@ bool RangeCheck::BetweenBounds(Range& range, int lower, GenTree* upper)

void RangeCheck::OptimizeRangeCheck(BasicBlock* block, GenTree* stmt, GenTree* treeParent)
{
if (treeParent->OperIs(GT_CAST))
{
GenTreeCast* cast = treeParent->AsCast();

if ((cast->CastToType() != TYP_LONG) || (cast->CastFromType() != TYP_INT) || cast->IsUnsigned())
{
return;
}

m_pCurBndsChk = nullptr;

GetRangeMap()->RemoveAll();
GetOverflowMap()->RemoveAll();
m_pSearchPath = new (m_alloc) SearchPath(m_alloc);

Range range = GetRange(block, cast->gtGetOp1(), false DEBUGARG(0));

if (range.UpperLimit().IsUnknown() || range.LowerLimit().IsUnknown())
{
return;
}

if (DoesOverflow(block, cast->gtGetOp1()))
{
JITDUMP("Value determined to overflow.\n");
return;
}

JITDUMP("Range value %s\n", range.ToString(m_pCompiler->getAllocatorDebugOnly()));
m_pSearchPath->RemoveAll();
Widen(block, cast->gtGetOp1(), &range);

if (range.UpperLimit().IsUnknown() || range.LowerLimit().IsUnknown())
{
return;
}

if (range.lLimit.IsConstant() && (range.lLimit.GetConstant() >= 0) && range.uLimit.IsBinOpArray())
{
cast->gtFlags |= GTF_UNSIGNED;
}

return;
}

// Check if we are dealing with a bounds check node.
if (treeParent->OperGet() != GT_COMMA)
{
Expand Down Expand Up @@ -626,15 +671,23 @@ void RangeCheck::MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP
}
#endif

ValueNum arrLenVN = m_pCompiler->vnStore->VNConservativeNormalValue(m_pCurBndsChk->gtArrLen->gtVNPair);

if (m_pCompiler->vnStore->IsVNConstant(arrLenVN))
{
// Set arrLenVN to NoVN; this will make it match the "vn" recorded on
// constant limits (where we explicitly track the constant and don't
// redundantly store its VN in the "vn" field).
arrLenVN = ValueNumStore::NoVN;
}
ValueNum arrLenVN;

if (m_pCurBndsChk == nullptr)
{
arrLenVN = ValueNumStore::NoVN;
}
else
{
arrLenVN = m_pCompiler->vnStore->VNConservativeNormalValue(m_pCurBndsChk->gtArrLen->gtVNPair);
if (m_pCompiler->vnStore->IsVNConstant(arrLenVN))
{
// Set arrLenVN to NoVN; this will make it match the "vn" recorded on
// constant limits (where we explicitly track the constant and don't
// redundantly store its VN in the "vn" field).
arrLenVN = ValueNumStore::NoVN;
}
}

// During assertion prop we add assertions of the form:
//
Expand Down Expand Up @@ -669,13 +722,13 @@ void RangeCheck::MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP
}

// Doesn't tighten the current bound. So skip.
if (pRange->uLimit.IsConstant() && limit.vn != arrLenVN)
if (pRange->uLimit.IsConstant() && (limit.vn != arrLenVN && m_pCurBndsChk != nullptr))
{
continue;
}

// Check if the incoming limit from assertions tightens the existing upper limit.
if (pRange->uLimit.IsBinOpArray() && (pRange->uLimit.vn == arrLenVN))
if (pRange->uLimit.IsBinOpArray() && (pRange->uLimit.vn == arrLenVN && m_pCurBndsChk != nullptr))
{
// We have checked the current range's (pRange's) upper limit is either of the form:
// length + cns
Expand Down Expand Up @@ -747,6 +800,11 @@ void RangeCheck::MergeAssertion(BasicBlock* block, GenTree* op, Range* pRange DE
Compiler::dspTreeID(op), m_pCompiler->vnStore->VNConservativeNormalValue(op->gtVNPair));
ASSERT_TP assertions = BitVecOps::UninitVal();

if (m_pCompiler->GetAssertionCount() == 0)
{
return;
}

// If we have a phi arg, we can get to the block from it and use its assertion out.
if (op->gtOper == GT_PHI_ARG)
{
Expand Down

0 comments on commit e0a6e91

Please sign in to comment.