@@ -742,6 +742,10 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
742742 {
743743 printf (" ArrBnds " );
744744 }
745+ else if (curAssertion->op1 .kind == O1K_VN)
746+ {
747+ printf (" Vn " );
748+ }
745749 else if (curAssertion->op1 .kind == O1K_SUBTYPE)
746750 {
747751 printf (" Subtype " );
@@ -787,6 +791,10 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
787791 vnStore->vnDump (this , curAssertion->op1 .bnd .vnLen );
788792 printf (" ]" );
789793 }
794+ else if (curAssertion->op1 .kind == O1K_VN)
795+ {
796+ printf (" [" FMT_VN " ]" , curAssertion->op1 .vn );
797+ }
790798 else if (curAssertion->op1 .kind == O1K_BOUND_OPER_BND)
791799 {
792800 printf (" Oper_Bnd" );
@@ -1534,6 +1542,31 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
15341542 }
15351543 }
15361544 }
1545+ else
1546+ {
1547+ // Currently, O1K_VN serves as a backup for O1K_LCLVAR (where it's not a local),
1548+ // but long term we should keep O1K_LCLVAR for local assertions only.
1549+ if (!optLocalAssertionProp)
1550+ {
1551+ ValueNum op1VN = optConservativeNormalVN (op1);
1552+ ValueNum op2VN = optConservativeNormalVN (op2);
1553+
1554+ // For TP reasons, limited to 32-bit constants on the op2 side.
1555+ if ((op1VN != ValueNumStore::NoVN) && (op2VN != ValueNumStore::NoVN) && vnStore->IsVNInt32Constant (op2VN) &&
1556+ !vnStore->IsVNHandle (op2VN))
1557+ {
1558+ assert (assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL);
1559+ assertion.assertionKind = assertionKind;
1560+ assertion.op1 .vn = op1VN;
1561+ assertion.op1 .kind = O1K_VN;
1562+ assertion.op2 .vn = op2VN;
1563+ assertion.op2 .kind = O2K_CONST_INT;
1564+ assertion.op2 .u1 .iconVal = vnStore->ConstantValue <int >(op2VN);
1565+ assertion.op2 .SetIconFlag (GTF_EMPTY);
1566+ return optAddAssertion (&assertion);
1567+ }
1568+ }
1569+ }
15371570
15381571DONE_ASSERTION:
15391572 return optFinalizeCreatingAssertion (&assertion);
@@ -1831,7 +1864,10 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion)
18311864 break ;
18321865 case O1K_ARR_BND:
18331866 // It would be good to check that bnd.vnIdx and bnd.vnLen are valid value numbers.
1867+ assert (!optLocalAssertionProp);
1868+ assert (assertion->assertionKind == OAK_NO_THROW);
18341869 break ;
1870+ case O1K_VN:
18351871 case O1K_BOUND_OPER_BND:
18361872 case O1K_BOUND_LOOP_BND:
18371873 case O1K_CONSTANT_LOOP_BND:
@@ -2249,45 +2285,7 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
22492285 if (vnStore->IsVNCheckedBound (op1VN) && vnStore->IsVNInt32Constant (op2VN))
22502286 {
22512287 assert (relop->OperIs (GT_EQ, GT_NE));
2252-
2253- int con = vnStore->ConstantValue <int >(op2VN);
2254- if (con >= 0 )
2255- {
2256- AssertionDsc dsc;
2257-
2258- // For arr.Length != 0, we know that 0 is a valid index
2259- // For arr.Length == con, we know that con - 1 is the greatest valid index
2260- if (con == 0 )
2261- {
2262- dsc.assertionKind = OAK_NOT_EQUAL;
2263- dsc.op1 .bnd .vnIdx = vnStore->VNForIntCon (0 );
2264- }
2265- else
2266- {
2267- dsc.assertionKind = OAK_EQUAL;
2268- dsc.op1 .bnd .vnIdx = vnStore->VNForIntCon (con - 1 );
2269- }
2270-
2271- dsc.op1 .vn = op1VN;
2272- dsc.op1 .kind = O1K_ARR_BND;
2273- dsc.op1 .bnd .vnLen = op1VN;
2274- dsc.op2 .vn = vnStore->VNConservativeNormalValue (op2->gtVNPair );
2275- dsc.op2 .kind = O2K_CONST_INT;
2276- dsc.op2 .u1 .iconVal = 0 ;
2277- dsc.op2 .SetIconFlag (GTF_EMPTY);
2278-
2279- // when con is not zero, create an assertion on the arr.Length == con edge
2280- // when con is zero, create an assertion on the arr.Length != 0 edge
2281- AssertionIndex index = optAddAssertion (&dsc);
2282- if (relop->OperIs (GT_NE) != (con == 0 ))
2283- {
2284- return AssertionInfo::ForNextEdge (index);
2285- }
2286- else
2287- {
2288- return index;
2289- }
2290- }
2288+ return optCreateJtrueAssertions (op1, op2, assertionKind);
22912289 }
22922290 }
22932291
@@ -4061,8 +4059,7 @@ void Compiler::optAssertionProp_RangeProperties(ASSERT_VALARG_TP assertions,
40614059 }
40624060
40634061 // First, analyze possible X ==/!= CNS assertions.
4064- if (curAssertion->IsConstantInt32Assertion () && (curAssertion->op1 .kind == O1K_LCLVAR) &&
4065- (curAssertion->op1 .vn == treeVN))
4062+ if (curAssertion->IsConstantInt32Assertion () && (curAssertion->op1 .vn == treeVN))
40664063 {
40674064 if ((curAssertion->assertionKind == OAK_NOT_EQUAL) && (curAssertion->op2 .u1 .iconVal == 0 ))
40684065 {
0 commit comments