@@ -754,12 +754,13 @@ Compiler::AssertionDsc * Compiler::optGetAssertion(AssertionIndex assertIndex)
754
754
{
755
755
assert (NO_ASSERTION_INDEX == 0 );
756
756
noway_assert (assertIndex != NO_ASSERTION_INDEX);
757
+ noway_assert (assertIndex <= optAssertionCount);
758
+ AssertionDsc* assertion = &optAssertionTabPrivate[assertIndex - 1 ];
759
+ #ifdef DEBUG
760
+ optDebugCheckAssertion (assertion);
761
+ #endif
757
762
758
- if (assertIndex > optMaxAssertionCount)
759
- {
760
- return nullptr ;
761
- }
762
- return &optAssertionTabPrivate[assertIndex - 1 ];
763
+ return assertion;
763
764
}
764
765
765
766
/* ****************************************************************************
@@ -1488,6 +1489,63 @@ Compiler::AssertionIndex Compiler::optAddAssertion(AssertionDsc* newAssertion)
1488
1489
}
1489
1490
1490
1491
#ifdef DEBUG
1492
+ void Compiler::optDebugCheckAssertion (AssertionDsc* assertion)
1493
+ {
1494
+ assert (assertion->assertionKind < OAK_COUNT);
1495
+ assert (assertion->op1 .kind < O1K_COUNT);
1496
+ assert (assertion->op2 .kind < O2K_COUNT);
1497
+ // It would be good to check that op1.vn and op2.vn are valid value numbers.
1498
+
1499
+ switch (assertion->op1 .kind )
1500
+ {
1501
+ case O1K_LCLVAR:
1502
+ case O1K_EXACT_TYPE:
1503
+ case O1K_SUBTYPE:
1504
+ assert (assertion->op1 .lcl .lclNum < lvaCount);
1505
+ assert (optLocalAssertionProp ||
1506
+ ((assertion->op1 .lcl .ssaNum - SsaConfig::UNINIT_SSA_NUM) < lvaTable[assertion->op1 .lcl .lclNum ].lvNumSsaNames ));
1507
+ break ;
1508
+ case O1K_ARR_BND:
1509
+ // It would be good to check that bnd.vnIdx and bnd.vnLen are valid value numbers.
1510
+ break ;
1511
+ case O1K_ARRLEN_OPER_BND:
1512
+ case O1K_ARRLEN_LOOP_BND:
1513
+ case O1K_CONSTANT_LOOP_BND:
1514
+ assert (!optLocalAssertionProp);
1515
+ break ;
1516
+ default :
1517
+ break ;
1518
+ }
1519
+ switch (assertion->op2 .kind )
1520
+ {
1521
+ case O2K_IND_CNS_INT:
1522
+ case O2K_CONST_INT:
1523
+ {
1524
+ // The only flags that can be set are those in the GTF_ICON_HDL_MASK, or bit 0, which is
1525
+ // used to indicate a long constant.
1526
+ assert ((assertion->op2 .u1 .iconFlags & ~(GTF_ICON_HDL_MASK|1 )) == 0 );
1527
+ switch (assertion->op1 .kind )
1528
+ {
1529
+ case O1K_EXACT_TYPE:
1530
+ case O1K_SUBTYPE:
1531
+ assert (assertion->op2 .u1 .iconFlags != 0 );
1532
+ break ;
1533
+ case O1K_LCLVAR:
1534
+ case O1K_ARR_BND:
1535
+ assert (lvaTable[assertion->op1 .lcl .lclNum ].lvType != TYP_REF || assertion->op2 .u1 .iconVal == 0 );
1536
+ break ;
1537
+ default :
1538
+ break ;
1539
+ }
1540
+ }
1541
+ break ;
1542
+
1543
+ default :
1544
+ // for all other 'assertion->op2.kind' values we don't check anything
1545
+ break ;
1546
+ }
1547
+ }
1548
+
1491
1549
/* ****************************************************************************
1492
1550
*
1493
1551
* Verify that assertion prop related assumptions are valid. If "index"
@@ -1502,33 +1560,7 @@ void Compiler::optDebugCheckAssertions(AssertionIndex index)
1502
1560
for (AssertionIndex ind = start; ind <= end; ++ind)
1503
1561
{
1504
1562
AssertionDsc* assertion = optGetAssertion (ind);
1505
- switch (assertion->op2 .kind )
1506
- {
1507
- case O2K_IND_CNS_INT:
1508
- case O2K_CONST_INT:
1509
- {
1510
- switch (assertion->op1 .kind )
1511
- {
1512
- case O1K_EXACT_TYPE:
1513
- case O1K_SUBTYPE:
1514
- assert (assertion->op2 .u1 .iconFlags != 0 );
1515
- break ;
1516
- case O1K_ARRLEN_OPER_BND:
1517
- case O1K_ARRLEN_LOOP_BND:
1518
- case O1K_CONSTANT_LOOP_BND:
1519
- assert (!optLocalAssertionProp);
1520
- break ;
1521
- default :
1522
- assert (lvaTable[assertion->op1 .lcl .lclNum ].lvType != TYP_REF || assertion->op2 .u1 .iconVal == 0 );
1523
- break ;
1524
- }
1525
- }
1526
- break ;
1527
-
1528
- default :
1529
- // for all other 'assertion->op2.kind' values we don't check anything
1530
- break ;
1531
- }
1563
+ optDebugCheckAssertion (assertion);
1532
1564
}
1533
1565
}
1534
1566
#endif
@@ -4282,6 +4314,18 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags()
4282
4314
{
4283
4315
ASSERT_TP* jumpDestOut = fgAllocateTypeForEachBlk<ASSERT_TP>();
4284
4316
4317
+ // The local assertion gen phase may have created unreachable blocks.
4318
+ // They will never be visited in the dataflow propagation phase, so they need to
4319
+ // be initialized correctly. This means that instead of setting their sets to
4320
+ // apFull (i.e. all possible bits set), we need to set the bits only for valid
4321
+ // assertions (note that at this point we are not creating any new assertions).
4322
+ // Also note that assertion indices start from 1.
4323
+ ASSERT_TP apValidFull = optNewEmptyAssertSet ();
4324
+ for (int i = 1 ; i <= optAssertionCount; i++)
4325
+ {
4326
+ BitVecOps::AddElemD (apTraits, apValidFull, i-1 );
4327
+ }
4328
+
4285
4329
// Initially estimate the OUT sets to everything except killed expressions
4286
4330
// Also set the IN sets to 1, so that we can perform the intersection.
4287
4331
// Also, zero-out the flags for handler blocks, as we could be in the
@@ -4290,11 +4334,16 @@ ASSERT_TP* Compiler::optInitAssertionDataflowFlags()
4290
4334
// edges.
4291
4335
for (BasicBlock* block = fgFirstBB; block; block = block->bbNext )
4292
4336
{
4293
- block->bbAssertionIn = bbIsHandlerBeg (block) ? optNewEmptyAssertSet () : optNewFullAssertSet ();
4337
+ block->bbAssertionIn = optNewEmptyAssertSet ();
4338
+ if (!bbIsHandlerBeg (block))
4339
+ {
4340
+ BitVecOps::Assign (apTraits, block->bbAssertionIn , apValidFull);
4341
+ }
4294
4342
block->bbAssertionGen = optNewEmptyAssertSet ();
4295
- block->bbAssertionOut = optNewFullAssertSet ();
4343
+ block->bbAssertionOut = optNewEmptyAssertSet ();
4344
+ BitVecOps::Assign (apTraits, block->bbAssertionOut , apValidFull);
4296
4345
jumpDestOut[block->bbNum ] = optNewEmptyAssertSet ();
4297
- BitVecOps::Assign (apTraits, jumpDestOut[block->bbNum ], apFull );
4346
+ BitVecOps::Assign (apTraits, jumpDestOut[block->bbNum ], apValidFull );
4298
4347
}
4299
4348
// Compute the data flow values for all tracked expressions
4300
4349
// IN and OUT never change for the initial basic block B1
@@ -4817,9 +4866,9 @@ void Compiler::optAssertionPropMain()
4817
4866
// and thus we must morph, set order, re-link
4818
4867
for (GenTreePtr tree = stmt->gtStmt .gtStmtList ; tree; tree = tree->gtNext )
4819
4868
{
4820
- JITDUMP (" Propagating %s assertions for BB%02d, stmt %08X , tree %08X , tree -> %d\n " ,
4821
- BitVecOps::ToString (apTraits, assertions),
4822
- block->bbNum , dspPtr (stmt), dspPtr (tree), tree->GetAssertion ());
4869
+ JITDUMP (" Propagating %s assertions for BB%02d, stmt [%06d] , tree [%06d] , tree -> %d\n " ,
4870
+ BitVecOps::ToString (apTraits, assertions),
4871
+ block->bbNum , dspTreeID (stmt), dspTreeID (tree), tree->GetAssertion ());
4823
4872
4824
4873
GenTreePtr newTree = optAssertionProp (assertions, tree, stmt);
4825
4874
if (newTree)
0 commit comments