@@ -755,8 +755,8 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
755
755
{
756
756
printf (" Copy " );
757
757
}
758
- else if ((curAssertion->op2 .kind == O2K_CONST_INT) || (curAssertion->op2 .kind == O2K_CONST_LONG ) ||
759
- (curAssertion->op2 .kind == O2K_CONST_DOUBLE) || (curAssertion-> op2 . kind == O2K_ZEROOBJ))
758
+ else if ((curAssertion->op2 .kind == O2K_CONST_INT) || (curAssertion->op2 .kind == O2K_CONST_DOUBLE ) ||
759
+ (curAssertion->op2 .kind == O2K_ZEROOBJ))
760
760
{
761
761
printf (" Constant " );
762
762
}
@@ -950,10 +950,6 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse
950
950
}
951
951
break ;
952
952
953
- case O2K_CONST_LONG:
954
- printf (" 0x%016llx" , curAssertion->op2 .lconVal );
955
- break ;
956
-
957
953
case O2K_CONST_DOUBLE:
958
954
if (FloatingPointUtils::isNegativeZero (curAssertion->op2 .dconVal ))
959
955
{
@@ -1232,10 +1228,6 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser
1232
1228
}
1233
1229
goto CNS_COMMON;
1234
1230
1235
- case GT_CNS_LNG:
1236
- op2Kind = O2K_CONST_LONG;
1237
- goto CNS_COMMON;
1238
-
1239
1231
case GT_CNS_DBL:
1240
1232
op2Kind = O2K_CONST_DOUBLE;
1241
1233
goto CNS_COMMON;
@@ -1258,9 +1250,8 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser
1258
1250
goto DONE_ASSERTION; // Don't make an assertion
1259
1251
}
1260
1252
1261
- assertion.op2 .kind = op2Kind;
1262
- assertion.op2 .lconVal = 0 ;
1263
- assertion.op2 .vn = optConservativeNormalVN (op2);
1253
+ assertion.op2 .kind = op2Kind;
1254
+ assertion.op2 .vn = optConservativeNormalVN (op2);
1264
1255
1265
1256
if (op2->gtOper == GT_CNS_INT)
1266
1257
{
@@ -1276,10 +1267,6 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, GenTree* op2, optAsser
1276
1267
assertion.op2 .u1 .iconVal = iconVal;
1277
1268
assertion.op2 .SetIconFlag (op2->GetIconHandleFlag (), op2->AsIntCon ()->gtFieldSeq );
1278
1269
}
1279
- else if (op2->gtOper == GT_CNS_LNG)
1280
- {
1281
- assertion.op2 .lconVal = op2->AsLngCon ()->gtLconVal ;
1282
- }
1283
1270
else
1284
1271
{
1285
1272
noway_assert (op2->gtOper == GT_CNS_DBL);
@@ -1444,12 +1431,6 @@ AssertionIndex Compiler::optFinalizeCreatingAssertion(AssertionDsc* assertion)
1444
1431
{
1445
1432
return NO_ASSERTION_INDEX;
1446
1433
}
1447
-
1448
- // TODO: only copy assertions rely on valid SSA number so we could generate more assertions here
1449
- if (assertion->op1 .lcl .ssaNum == SsaConfig::RESERVED_SSA_NUM)
1450
- {
1451
- return NO_ASSERTION_INDEX;
1452
- }
1453
1434
}
1454
1435
1455
1436
// Now add the assertion to our assertion table
@@ -1731,10 +1712,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion)
1731
1712
1732
1713
switch (assertion->op1 .kind )
1733
1714
{
1734
- case O1K_LCLVAR:
1735
- assert (optLocalAssertionProp ||
1736
- lvaGetDesc (assertion->op1 .lcl .lclNum )->lvPerSsaData .IsValidSsaNum (assertion->op1 .lcl .ssaNum ));
1737
- break ;
1738
1715
case O1K_ARR_BND:
1739
1716
// It would be good to check that bnd.vnIdx and bnd.vnLen are valid value numbers.
1740
1717
assert (!optLocalAssertionProp);
@@ -1772,14 +1749,6 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion)
1772
1749
}
1773
1750
break ;
1774
1751
1775
- case O2K_CONST_LONG:
1776
- {
1777
- // All handles should be represented by O2K_CONST_INT,
1778
- // so no handle bits should be set here.
1779
- assert (!assertion->op2 .HasIconFlag ());
1780
- }
1781
- break ;
1782
-
1783
1752
case O2K_ZEROOBJ:
1784
1753
{
1785
1754
// We only make these assertion for stores (not control flow).
@@ -1852,8 +1821,8 @@ void Compiler::optCreateComplementaryAssertion(AssertionIndex assertionIndex, Ge
1852
1821
if ((candidateAssertion.op1 .kind == O1K_LCLVAR) || (candidateAssertion.op1 .kind == O1K_VN))
1853
1822
{
1854
1823
// "LCLVAR != CNS" is not a useful assertion (unless CNS is 0/1)
1855
- if (((candidateAssertion.op2 .kind == O2K_CONST_INT) || (candidateAssertion.op2 .kind == O2K_CONST_LONG) ) &&
1856
- (candidateAssertion.op2 .u1 .iconVal != 0 ) && (candidateAssertion. op2 . u1 . iconVal != 1 ))
1824
+ if (((candidateAssertion.op2 .kind == O2K_CONST_INT)) && (candidateAssertion.op2 .u1 . iconVal != 0 ) &&
1825
+ (candidateAssertion.op2 .u1 .iconVal != 1 ))
1857
1826
{
1858
1827
return ;
1859
1828
}
@@ -1881,59 +1850,6 @@ void Compiler::optCreateComplementaryAssertion(AssertionIndex assertionIndex, Ge
1881
1850
}
1882
1851
}
1883
1852
1884
- // optAssertionGenCast: Create a tentative subrange assertion for a cast.
1885
- //
1886
- // This function will try to create an assertion that the cast's operand
1887
- // is within the "input" range for the cast, so that this assertion can
1888
- // later be proven via implication and the cast removed. Such assertions
1889
- // are only generated during global propagation, and only for LCL_VARs.
1890
- //
1891
- // Arguments:
1892
- // cast - the cast node for which to create the assertion
1893
- //
1894
- // Return Value:
1895
- // Index of the generated assertion, or NO_ASSERTION_INDEX if it was not
1896
- // legal, profitable, or possible to create one.
1897
- //
1898
- AssertionIndex Compiler::optAssertionGenCast (GenTreeCast* cast)
1899
- {
1900
- if (optLocalAssertionProp || !varTypeIsIntegral (cast) || !varTypeIsIntegral (cast->CastOp ()))
1901
- {
1902
- return NO_ASSERTION_INDEX;
1903
- }
1904
-
1905
- // This condition exists to preserve previous behavior.
1906
- if (!cast->CastOp ()->OperIs (GT_LCL_VAR))
1907
- {
1908
- return NO_ASSERTION_INDEX;
1909
- }
1910
-
1911
- GenTreeLclVar* lclVar = cast->CastOp ()->AsLclVar ();
1912
- LclVarDsc* varDsc = lvaGetDesc (lclVar);
1913
-
1914
- // It is not useful to make assertions about address-exposed variables, they will never be proven.
1915
- if (varDsc->IsAddressExposed ())
1916
- {
1917
- return NO_ASSERTION_INDEX;
1918
- }
1919
-
1920
- // A representation-changing cast cannot be simplified if it is not checked.
1921
- if (!cast->gtOverflow () && (genActualType (cast) != genActualType (lclVar)))
1922
- {
1923
- return NO_ASSERTION_INDEX;
1924
- }
1925
-
1926
- AssertionDsc assertion = {OAK_SUBRANGE};
1927
- assertion.op1 .kind = O1K_LCLVAR;
1928
- assertion.op1 .vn = vnStore->VNConservativeNormalValue (lclVar->gtVNPair );
1929
- assertion.op1 .lcl .lclNum = lclVar->GetLclNum ();
1930
- assertion.op1 .lcl .ssaNum = lclVar->GetSsaNum ();
1931
- assertion.op2 .kind = O2K_SUBRANGE;
1932
- assertion.op2 .u2 = IntegralRange::ForCastInput (cast);
1933
-
1934
- return optFinalizeCreatingAssertion (&assertion);
1935
- }
1936
-
1937
1853
// ------------------------------------------------------------------------
1938
1854
// optCreateJtrueAssertions: Create assertions about a JTRUE's relop operands.
1939
1855
//
@@ -2139,21 +2055,21 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
2139
2055
2140
2056
// See if we have IND(obj) ==/!= TypeHandle
2141
2057
//
2142
- if (!optLocalAssertionProp && op1->OperIs (GT_IND))
2058
+ if (!optLocalAssertionProp && op1->OperIs (GT_IND) && op1-> gtGetOp1 ()-> TypeIs (TYP_REF) )
2143
2059
{
2144
- ssize_t cnsValue = 0 ;
2145
- GenTreeFlags iconFlags = GTF_EMPTY ;
2146
- if (op1-> gtGetOp1 ()-> TypeIs (TYP_REF) &&
2147
- optIsTreeKnownIntValue (!optLocalAssertionProp, op2, &cnsValue, &iconFlags ))
2060
+ ValueNum objVN = optConservativeNormalVN (op1-> gtGetOp1 ()) ;
2061
+ ValueNum typeHndVN = optConservativeNormalVN (op2) ;
2062
+
2063
+ if ((objVN != ValueNumStore::NoVN) && vnStore-> IsVNTypeHandle (typeHndVN ))
2148
2064
{
2149
2065
AssertionDsc assertion;
2150
2066
assertion.assertionKind = OAK_EQUAL;
2151
2067
assertion.op1 .kind = O1K_EXACT_TYPE;
2152
- assertion.op1 .vn = optConservativeNormalVN (op1-> gtGetOp1 ()) ;
2068
+ assertion.op1 .vn = objVN ;
2153
2069
assertion.op2 .kind = O2K_CONST_INT;
2154
- assertion.op2 .u1 .iconVal = cnsValue ;
2155
- assertion.op2 .vn = optConservativeNormalVN (op2) ;
2156
- assertion.op2 .SetIconFlag (iconFlags );
2070
+ assertion.op2 .u1 .iconVal = vnStore-> CoercedConstantValue < ssize_t >(typeHndVN) ;
2071
+ assertion.op2 .vn = typeHndVN ;
2072
+ assertion.op2 .SetIconFlag (GTF_ICON_CLASS_HDL );
2157
2073
AssertionIndex index = optAddAssertion (&assertion);
2158
2074
2159
2075
// We don't need to create a complementary assertion here. We're only interested
@@ -2260,15 +2176,18 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree)
2260
2176
assert (objectNode->TypeIs (TYP_REF, TYP_I_IMPL));
2261
2177
assert (methodTableNode->TypeIs (TYP_I_IMPL));
2262
2178
2263
- if (methodTableNode->OperIs (GT_CNS_INT))
2179
+ ValueNum objVN = optConservativeNormalVN (objectNode);
2180
+ ValueNum typeHndVN = optConservativeNormalVN (methodTableNode);
2181
+
2182
+ if ((objVN != ValueNumStore::NoVN) && vnStore->IsVNTypeHandle (typeHndVN))
2264
2183
{
2265
2184
AssertionDsc assertion;
2266
2185
assertion.op1 .kind = O1K_SUBTYPE;
2267
- assertion.op1 .vn = optConservativeNormalVN (objectNode) ;
2186
+ assertion.op1 .vn = objVN ;
2268
2187
assertion.op2 .kind = O2K_CONST_INT;
2269
- assertion.op2 .u1 .iconVal = methodTableNode-> AsIntCon ()-> IconValue ( );
2270
- assertion.op2 .vn = optConservativeNormalVN (methodTableNode) ;
2271
- assertion.op2 .SetIconFlag (op2-> GetIconHandleFlag () );
2188
+ assertion.op2 .u1 .iconVal = vnStore-> CoercedConstantValue < ssize_t >(typeHndVN );
2189
+ assertion.op2 .vn = typeHndVN ;
2190
+ assertion.op2 .SetIconFlag (GTF_ICON_CLASS_HDL );
2272
2191
assertion.assertionKind = OAK_EQUAL;
2273
2192
AssertionIndex index = optAddAssertion (&assertion);
2274
2193
@@ -2310,9 +2229,6 @@ void Compiler::optAssertionGen(GenTree* tree)
2310
2229
optAssertionPropCurrentTree = tree;
2311
2230
#endif
2312
2231
2313
- // For most of the assertions that we create below
2314
- // the assertion is true after the tree is processed
2315
- bool assertionProven = true ;
2316
2232
AssertionInfo assertionInfo;
2317
2233
switch (tree->OperGet ())
2318
2234
{
@@ -2379,14 +2295,6 @@ void Compiler::optAssertionGen(GenTree* tree)
2379
2295
}
2380
2296
break ;
2381
2297
2382
- case GT_CAST:
2383
- // This represets an assertion that we would like to prove to be true.
2384
- // If we can prove this assertion true then we can eliminate this cast.
2385
- // We only create this assertion for global assertion propagation.
2386
- assertionInfo = optAssertionGenCast (tree->AsCast ());
2387
- assertionProven = false ;
2388
- break ;
2389
-
2390
2298
case GT_JTRUE:
2391
2299
assertionInfo = optAssertionGenJtrue (tree);
2392
2300
break ;
@@ -2396,7 +2304,7 @@ void Compiler::optAssertionGen(GenTree* tree)
2396
2304
break ;
2397
2305
}
2398
2306
2399
- if (assertionInfo.HasAssertion () && assertionProven )
2307
+ if (assertionInfo.HasAssertion ())
2400
2308
{
2401
2309
tree->SetAssertionInfo (assertionInfo);
2402
2310
}
@@ -3326,17 +3234,6 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion,
3326
3234
newTree->BashToConst (curAssertion->op2 .dconVal , tree->TypeGet ());
3327
3235
break ;
3328
3236
3329
- case O2K_CONST_LONG:
3330
- if (newTree->TypeIs (TYP_LONG))
3331
- {
3332
- newTree->BashToConst (curAssertion->op2 .lconVal );
3333
- }
3334
- else
3335
- {
3336
- newTree->BashToConst (static_cast <int32_t >(curAssertion->op2 .lconVal ));
3337
- }
3338
- break ;
3339
-
3340
3237
case O2K_CONST_INT:
3341
3238
3342
3239
// Don't propagate handles if we need to report relocs.
@@ -3731,30 +3628,26 @@ GenTree* Compiler::optAssertionProp_LclVar(ASSERT_VALARG_TP assertions, GenTreeL
3731
3628
continue ;
3732
3629
}
3733
3630
3734
- // Constant prop.
3735
- //
3736
- // The case where the tree type could be different than the LclVar type is caused by
3737
- // gtFoldExpr, specifically the case of a cast, where the fold operation changes the type of the LclVar
3738
- // node. In such a case is not safe to perform the substitution since later on the JIT will assert mismatching
3739
- // types between trees.
3740
- //
3741
- if (curAssertion->op1 .lcl .lclNum == lclNum)
3631
+ // Verify types match
3632
+ if (tree->TypeGet () != lvaGetRealType (lclNum))
3742
3633
{
3743
- LclVarDsc* const lclDsc = lvaGetDesc (lclNum);
3744
- // Verify types match
3745
- if (tree->TypeGet () == lclDsc->lvType )
3746
- {
3747
- // If local assertion prop, just perform constant prop.
3748
- if (optLocalAssertionProp)
3749
- {
3750
- return optConstantAssertionProp (curAssertion, tree, stmt DEBUGARG (assertionIndex));
3751
- }
3634
+ continue ;
3635
+ }
3752
3636
3753
- // If global assertion, perform constant propagation only if the VN's match.
3754
- if (curAssertion->op1 .vn == vnStore->VNConservativeNormalValue (tree->gtVNPair ))
3755
- {
3756
- return optConstantAssertionProp (curAssertion, tree, stmt DEBUGARG (assertionIndex));
3757
- }
3637
+ if (optLocalAssertionProp)
3638
+ {
3639
+ // Check lclNum in Local Assertion Prop
3640
+ if (curAssertion->op1 .lcl .lclNum == lclNum)
3641
+ {
3642
+ return optConstantAssertionProp (curAssertion, tree, stmt DEBUGARG (assertionIndex));
3643
+ }
3644
+ }
3645
+ else
3646
+ {
3647
+ // Check VN in Global Assertion Prop
3648
+ if (curAssertion->op1 .vn == vnStore->VNConservativeNormalValue (tree->gtVNPair ))
3649
+ {
3650
+ return optConstantAssertionProp (curAssertion, tree, stmt DEBUGARG (assertionIndex));
3758
3651
}
3759
3652
}
3760
3653
}
@@ -6034,10 +5927,6 @@ void Compiler::optImpliedByCopyAssertion(AssertionDsc* copyAssertion, AssertionD
6034
5927
usable = op1MatchesCopy && impAssertion->op2 .u2 .Contains (depAssertion->op2 .u2 );
6035
5928
break ;
6036
5929
6037
- case O2K_CONST_LONG:
6038
- usable = op1MatchesCopy && (impAssertion->op2 .lconVal == depAssertion->op2 .lconVal );
6039
- break ;
6040
-
6041
5930
case O2K_CONST_DOUBLE:
6042
5931
// Exact memory match because of positive and negative zero
6043
5932
usable = op1MatchesCopy &&
0 commit comments