@@ -300,6 +300,10 @@ bool IntegralRange::Contains(int64_t value) const
300300 {
301301 rangeType = TYP_USHORT;
302302 }
303+ else if ((elementCount == 32 ) && varTypeIsLong (rangeType))
304+ {
305+ return {SymbolicIntegerValue::Zero, UpperBoundForType (TYP_UINT)};
306+ }
303307 break ;
304308 }
305309
@@ -4070,17 +4074,20 @@ void Compiler::optAssertionProp_RangeProperties(ASSERT_VALARG_TP assertions,
40704074 }
40714075
40724076 // Let's see if MergeEdgeAssertions can help us:
4073- if (genActualType (tree) == TYP_INT )
4077+ if (varTypeIsIntegral (tree))
40744078 {
4075- Range rng = RangeCheck::GetRangeFromAssertions (this , treeVN, assertions);
4076- assert (rng.IsConstantRange ());
4077- if (rng.LowerLimit ().GetConstant () >= 0 )
4078- {
4079- *isKnownNonNegative = true ;
4080- }
4081- if ((rng.LowerLimit ().GetConstant () > 0 ) || (rng.UpperLimit ().GetConstant () < 0 ))
4079+ Range rng = RangeCheck::GetRangeFromAssertions (this , tree->TypeGet (), treeVN, assertions);
4080+
4081+ if (rng.IsConstantRange ())
40824082 {
4083- *isKnownNonZero = true ;
4083+ if (rng.LowerLimit ().GetConstant () >= 0 )
4084+ {
4085+ *isKnownNonNegative = true ;
4086+ }
4087+ if ((rng.LowerLimit ().GetConstant () > 0 ) || (rng.UpperLimit ().GetConstant () < 0 ))
4088+ {
4089+ *isKnownNonZero = true ;
4090+ }
40844091 }
40854092 }
40864093}
@@ -4101,14 +4108,17 @@ GenTree* Compiler::optAssertionProp_AddMulSub(ASSERT_VALARG_TP assertions, GenTr
41014108{
41024109 assert (tree->OperIs (GT_MUL, GT_ADD, GT_SUB));
41034110
4104- if (!optLocalAssertionProp && tree-> TypeIs (TYP_INT ) && tree->gtOverflow ())
4111+ if (!optLocalAssertionProp && varTypeIsIntegral (tree ) && tree->gtOverflow ())
41054112 {
41064113 GenTree* op1 = tree->gtGetOp1 ();
41074114 GenTree* op2 = tree->gtGetOp2 ();
41084115
4109- Range op1Rng = RangeCheck::GetRangeFromAssertions (this , optConservativeNormalVN (op1), assertions);
4110- Range op2Rng = RangeCheck::GetRangeFromAssertions (this , optConservativeNormalVN (op2), assertions);
4116+ Range op1Rng =
4117+ RangeCheck::GetRangeFromAssertions (this , op1->TypeGet (), optConservativeNormalVN (op1), assertions);
4118+ Range op2Rng =
4119+ RangeCheck::GetRangeFromAssertions (this , op2->TypeGet (), optConservativeNormalVN (op2), assertions);
41114120 Range result = Limit (Limit::keUnknown);
4121+
41124122 if (tree->OperIs (GT_MUL))
41134123 {
41144124 result = RangeOps::Multiply (op1Rng, op2Rng, tree->IsUnsigned ());
@@ -4481,10 +4491,10 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
44814491 }
44824492
44834493 // See if we can fold the relop based on range information.
4484- // We don't need the op1->TypeIs(TYP_INT ) check, but it seems to improve the TP quite a bit.
4485- if (op1-> TypeIs (TYP_INT ))
4494+ // We don't need the varTypeIsIntegral(op1 ) check, but it seems to improve the TP quite a bit.
4495+ if (varTypeIsIntegral (op1 ))
44864496 {
4487- Range relopRange = RangeCheck::GetRangeFromAssertions (this , relopVN, assertions);
4497+ Range relopRange = RangeCheck::GetRangeFromAssertions (this , tree-> TypeGet (), relopVN, assertions);
44884498
44894499 int relopResult;
44904500 if (!relopRange.IsSingleValueConstant (&relopResult))
@@ -4500,8 +4510,8 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
45004510 }
45014511 else
45024512 {
4503- Range op1Range = RangeCheck::GetRangeFromAssertions (this , op1VN, assertions);
4504- Range op2Range = RangeCheck::GetRangeFromAssertions (this , op2VN, assertions);
4513+ Range op1Range = RangeCheck::GetRangeFromAssertions (this , op1-> TypeGet (), op1VN, assertions);
4514+ Range op2Range = RangeCheck::GetRangeFromAssertions (this , op2-> TypeGet (), op2VN, assertions);
45054515 relopRange = RangeOps::EvalRelop (tree->OperGet (), tree->IsUnsigned (), op1Range, op2Range);
45064516 }
45074517 }
@@ -4928,29 +4938,33 @@ GenTree* Compiler::optAssertionProp_Cast(ASSERT_VALARG_TP assertions,
49284938 if (FitsIn<int >(castLo) && FitsIn<int >(castHi))
49294939 {
49304940 Range castToTypeRange = Range (Limit (Limit::keConstant, (int )castLo), Limit (Limit::keConstant, (int )castHi));
4931- if (castToTypeRange.IsConstantRange () && (genActualType (cast->CastOp ()) == TYP_INT))
4932- {
4933- ValueNum castOpVN = optConservativeNormalVN (cast->CastOp ());
4934- Range castOpRng = RangeCheck::GetRangeFromAssertions (this , castOpVN, assertions);
4935- assert (castOpRng.IsConstantRange ());
49364941
4937- int castFromLo = castOpRng.LowerLimit ().GetConstant ();
4938- int castFromHi = castOpRng.UpperLimit ().GetConstant ();
4939- int castToLo = castToTypeRange.LowerLimit ().GetConstant ();
4940- int castToHi = castToTypeRange.UpperLimit ().GetConstant ();
4942+ GenTree* castOp = cast->CastOp ();
4943+ if (castToTypeRange.IsConstantRange () && varTypeIsIntegral (castOp))
4944+ {
4945+ ValueNum castOpVN = optConservativeNormalVN (castOp);
4946+ Range castOpRng = RangeCheck::GetRangeFromAssertions (this , castOp->TypeGet (), castOpVN, assertions);
49414947
4942- if ((castFromLo >= castToLo) && (castFromHi <= castToHi ))
4948+ if (castOpRng. IsConstantRange ( ))
49434949 {
4944- if (canDropCast)
4950+ int castFromLo = castOpRng.LowerLimit ().GetConstant ();
4951+ int castFromHi = castOpRng.UpperLimit ().GetConstant ();
4952+ int castToLo = castToTypeRange.LowerLimit ().GetConstant ();
4953+ int castToHi = castToTypeRange.UpperLimit ().GetConstant ();
4954+
4955+ if ((castFromLo >= castToLo) && (castFromHi <= castToHi))
49454956 {
4946- JITDUMP (" Removing cast %06u as redundant based on VN assertions.\n " , dspTreeID (cast));
4947- return optAssertionProp_Update (cast->CastOp (), cast, stmt);
4948- }
4957+ if (canDropCast)
4958+ {
4959+ JITDUMP (" Removing cast %06u as redundant based on VN assertions.\n " , dspTreeID (cast));
4960+ return optAssertionProp_Update (cast->CastOp (), cast, stmt);
4961+ }
49494962
4950- assert (cast->gtOverflow ());
4951- JITDUMP (" Clearing overflow flag for cast %06u based on VN assertions.\n " , dspTreeID (cast));
4952- cast->ClearOverflow ();
4953- return optAssertionProp_Update (cast, cast, stmt);
4963+ assert (cast->gtOverflow ());
4964+ JITDUMP (" Clearing overflow flag for cast %06u based on VN assertions.\n " , dspTreeID (cast));
4965+ cast->ClearOverflow ();
4966+ return optAssertionProp_Update (cast, cast, stmt);
4967+ }
49544968 }
49554969 }
49564970 }
@@ -5519,9 +5533,11 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
55195533 }
55205534#endif // FEATURE_ENABLE_NO_RANGE_CHECKS
55215535
5522- GenTreeBoundsChk* arrBndsChk = tree->AsBoundsChk ();
5523- ValueNum vnCurIdx = vnStore->VNConservativeNormalValue (arrBndsChk->GetIndex ()->gtVNPair );
5524- ValueNum vnCurLen = vnStore->VNConservativeNormalValue (arrBndsChk->GetArrayLength ()->gtVNPair );
5536+ GenTreeBoundsChk* arrBndsChk = tree->AsBoundsChk ();
5537+ GenTree* arrBndsChkIdx = arrBndsChk->GetIndex ();
5538+ GenTree* arrBndsChkLen = arrBndsChk->GetArrayLength ();
5539+ ValueNum vnCurIdx = vnStore->VNConservativeNormalValue (arrBndsChk->GetIndex ()->gtVNPair );
5540+ ValueNum vnCurLen = vnStore->VNConservativeNormalValue (arrBndsChk->GetArrayLength ()->gtVNPair );
55255541
55265542 auto dropBoundsCheck = [&](INDEBUG (const char * reason)) -> GenTree* {
55275543 JITDUMP (" \n VN based redundant (%s) bounds check assertion prop in " FMT_BB " :\n " , reason, compCurBB->bbNum );
@@ -5549,7 +5565,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
55495565
55505566 if ((add0 == vnCurLen) && vnStore->IsVNInt32Constant (add1))
55515567 {
5552- Range rng = RangeCheck::GetRangeFromAssertions (this , vnCurLen, assertions);
5568+ Range rng = RangeCheck::GetRangeFromAssertions (this , arrBndsChkLen-> TypeGet (), vnCurLen, assertions);
55535569 // Lower known limit of ArrLen:
55545570 const int lenLowerLimit = rng.LowerLimit ().GetConstant ();
55555571
@@ -5582,7 +5598,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
55825598 assert (curAssertion.GetOp2 ().IsVNNeverNegative ());
55835599
55845600 // Do we have a previous range check involving the same 'vnLen' upper bound?
5585- if (curAssertion.GetOp2 ().GetVN () == optConservativeNormalVN (arrBndsChk-> GetArrayLength () ))
5601+ if (curAssertion.GetOp2 ().GetVN () == optConservativeNormalVN (arrBndsChkLen ))
55865602 {
55875603 // Do we have the exact same lower bound 'vnIdx'?
55885604 // a[i] followed by a[i]
@@ -5593,7 +5609,7 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
55935609 // Are we using zero as the index?
55945610 // It can always be considered as redundant with any previous value
55955611 // a[*] followed by a[0]
5596- else if (vnCurIdx == vnStore->VNZeroForType (arrBndsChk-> GetIndex () ->TypeGet ()))
5612+ else if (vnCurIdx == vnStore->VNZeroForType (arrBndsChkIdx ->TypeGet ()))
55975613 {
55985614 return dropBoundsCheck (INDEBUG (" a[*] followed by a[0]" ));
55995615 }
@@ -5645,44 +5661,40 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree
56455661 }
56465662
56475663 // Let's see if we can remove the bounds check based on the ranges.
5648- if ((genActualType (vnStore->TypeOfVN (vnCurIdx)) == TYP_INT) &&
5649- (genActualType (vnStore->TypeOfVN (vnCurLen)) == TYP_INT))
5664+ Range idxRng = RangeCheck::GetRangeFromAssertions (this , arrBndsChkIdx->TypeGet (), vnCurIdx, assertions);
5665+ Range lenRng = RangeCheck::GetRangeFromAssertions (this , arrBndsChkLen->TypeGet (), vnCurLen, assertions);
5666+
5667+ if (idxRng.IsConstantRange () && lenRng.IsConstantRange ())
56505668 {
5651- Range idxRng = RangeCheck::GetRangeFromAssertions (this , vnCurIdx, assertions);
5652- Range lenRng = RangeCheck::GetRangeFromAssertions (this , vnCurLen, assertions);
5653- if (idxRng.IsConstantRange () && lenRng.IsConstantRange ())
5654- {
5655- int idxLo = idxRng.LowerLimit ().GetConstant ();
5656- int idxHi = idxRng.UpperLimit ().GetConstant ();
5657- int lenLo = lenRng.LowerLimit ().GetConstant ();
5669+ int idxLo = idxRng.LowerLimit ().GetConstant ();
5670+ int idxHi = idxRng.UpperLimit ().GetConstant ();
5671+ int lenLo = lenRng.LowerLimit ().GetConstant ();
56585672
5659- // GT_BOUNDS_CHECK node has an implicit contract - the length node must always be non-negative.
5660- // So we additionally tighten the lower bound of lenLo to be ">= 1" when we also have a
5661- // "length != 0" assertion for it.
5662- if ((idxLo == 0 ) && (idxHi == 0 ) && (lenLo <= 0 ))
5673+ // GT_BOUNDS_CHECK node has an implicit contract - the length node must always be non-negative.
5674+ // So we additionally tighten the lower bound of lenLo to be ">= 1" when we also have a
5675+ // "length != 0" assertion for it.
5676+ if ((idxLo == 0 ) && (idxHi == 0 ) && (lenLo <= 0 ))
5677+ {
5678+ BitVecOps::Iter iter (apTraits, assertions);
5679+ unsigned bvIndex = 0 ;
5680+ while (iter.NextElem (&bvIndex))
56635681 {
5664- BitVecOps::Iter iter (apTraits, assertions );
5665- unsigned bvIndex = 0 ;
5666- while (iter. NextElem (&bvIndex ))
5682+ const AssertionDsc& assertion = optGetAssertion ( GetAssertionIndex (bvIndex) );
5683+ if (assertion. IsConstantInt32Assertion () && assertion. KindIs (OAK_NOT_EQUAL) &&
5684+ (assertion. GetOp1 (). GetVN () == vnCurLen) && (assertion. GetOp2 (). GetIntConstant () == 0 ))
56675685 {
5668- const AssertionDsc& assertion = optGetAssertion (GetAssertionIndex (bvIndex));
5669- if (assertion.IsConstantInt32Assertion () && assertion.KindIs (OAK_NOT_EQUAL) &&
5670- (assertion.GetOp1 ().GetVN () == vnCurLen) && (assertion.GetOp2 ().GetIntConstant () == 0 ))
5671- {
5672- lenLo = 1 ;
5673- break ;
5674- }
5686+ lenLo = 1 ;
5687+ break ;
56755688 }
56765689 }
5690+ }
56775691
5678- // index is always within [0..lenLo) --> drop bounds check
5679- if ((idxLo >= 0 ) && (idxHi < lenLo))
5680- {
5681- return dropBoundsCheck (INDEBUG (" upper bound of index is less than lower bound of length" ));
5682- }
5692+ // index is always within [0..lenLo) --> drop bounds check
5693+ if ((idxLo >= 0 ) && (idxHi < lenLo))
5694+ {
5695+ return dropBoundsCheck (INDEBUG (" upper bound of index is less than lower bound of length" ));
56835696 }
56845697 }
5685-
56865698 return nullptr ;
56875699}
56885700
0 commit comments