@@ -541,36 +541,83 @@ void Compiler::optAssertionTraitsInit(AssertionIndex assertionCount)
541
541
542
542
void Compiler::optAssertionInit (bool isLocalProp)
543
543
{
544
- // Use a function countFunc to determine a proper maximum assertion count for the
545
- // method being compiled. The function is linear to the IL size for small and
546
- // moderate methods. For large methods, considering throughput impact, we track no
547
- // more than 64 assertions.
548
- // Note this tracks at most only 256 assertions.
549
- static const AssertionIndex countFunc[] = {64 , 128 , 256 , 64 };
550
- static const unsigned lowerBound = 0 ;
551
- static const unsigned upperBound = ArrLen (countFunc) - 1 ;
552
- const unsigned codeSize = info.compILCodeSize / 512 ;
553
- optMaxAssertionCount = countFunc[isLocalProp ? lowerBound : min (upperBound, codeSize)];
554
-
555
- optLocalAssertionProp = isLocalProp;
556
- optAssertionTabPrivate = new (this , CMK_AssertionProp) AssertionDsc[optMaxAssertionCount];
557
544
assert (NO_ASSERTION_INDEX == 0 );
545
+ const unsigned maxTrackedLocals = (unsigned )JitConfig.JitMaxLocalsToTrack ();
558
546
559
- if (!isLocalProp)
547
+ // We initialize differently for local prop / global prop
548
+ //
549
+ if (isLocalProp)
560
550
{
551
+ optLocalAssertionProp = true ;
552
+ optCrossBlockLocalAssertionProp = true ;
553
+
554
+ // Disable via config
555
+ //
556
+ if (JitConfig.JitEnableCrossBlockLocalAssertionProp () == 0 )
557
+ {
558
+ JITDUMP (" Disabling cross-block assertion prop by config setting\n " );
559
+ optCrossBlockLocalAssertionProp = false ;
560
+ }
561
+
562
+ // Disable if too many locals
563
+ //
564
+ // The typical number of local assertions is roughly proportional
565
+ // to the number of locals. So when we have huge numbers of locals,
566
+ // just do within-block local assertion prop.
567
+ //
568
+ if (lvaCount > maxTrackedLocals)
569
+ {
570
+ JITDUMP (" Disabling cross-block assertion prop: too many locals\n " );
571
+ optCrossBlockLocalAssertionProp = false ;
572
+ }
573
+
574
+ if (optCrossBlockLocalAssertionProp)
575
+ {
576
+ // We may need a fairly large table.
577
+ // Allow for roughly one assertion per local, up to the tracked limit.
578
+ // (empirical studies show about 0.6 asserions/local)
579
+ //
580
+ optMaxAssertionCount = (AssertionIndex)min (maxTrackedLocals, ((lvaCount / 64 ) + 1 ) * 64 );
581
+ }
582
+ else
583
+ {
584
+ // The assertion table will be reset for each block, so it can be smaller.
585
+ //
586
+ optMaxAssertionCount = 64 ;
587
+ }
588
+
589
+ // Local assertion prop keeps mappings from each local var to the assertions about that var.
590
+ //
591
+ optAssertionDep =
592
+ new (this , CMK_AssertionProp) JitExpandArray<ASSERT_TP>(getAllocator (CMK_AssertionProp), max (1 , lvaCount));
593
+ }
594
+ else
595
+ {
596
+ // General assertion prop.
597
+ //
598
+ optLocalAssertionProp = false ;
599
+
600
+ // Use a function countFunc to determine a proper maximum assertion count for the
601
+ // method being compiled. The function is linear to the IL size for small and
602
+ // moderate methods. For large methods, considering throughput impact, we track no
603
+ // more than 64 assertions.
604
+ // Note this tracks at most only 256 assertions.
605
+ //
606
+ static const AssertionIndex countFunc[] = {64 , 128 , 256 , 64 };
607
+ static const unsigned upperBound = ArrLen (countFunc) - 1 ;
608
+ const unsigned codeSize = info.compILCodeSize / 512 ;
609
+ optMaxAssertionCount = countFunc[min (upperBound, codeSize)];
610
+
561
611
optValueNumToAsserts =
562
612
new (getAllocator (CMK_AssertionProp)) ValueNumToAssertsMap (getAllocator (CMK_AssertionProp));
563
613
optComplementaryAssertionMap = new (this , CMK_AssertionProp)
564
614
AssertionIndex[optMaxAssertionCount + 1 ](); // zero-inited (NO_ASSERTION_INDEX)
565
615
}
566
616
567
- if (optAssertionDep == nullptr )
568
- {
569
- optAssertionDep =
570
- new (this , CMK_AssertionProp) JitExpandArray<ASSERT_TP>(getAllocator (CMK_AssertionProp), max (1 , lvaCount));
571
- }
617
+ optAssertionTabPrivate = new (this , CMK_AssertionProp) AssertionDsc[optMaxAssertionCount];
572
618
573
619
optAssertionTraitsInit (optMaxAssertionCount);
620
+
574
621
optAssertionCount = 0 ;
575
622
optAssertionOverflow = 0 ;
576
623
optAssertionPropagated = false ;
@@ -4457,12 +4504,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op,
4457
4504
// Find live assertions related to lclNum
4458
4505
//
4459
4506
unsigned const lclNum = op->AsLclVarCommon ()->GetLclNum ();
4460
- ASSERT_TP apDependent = GetAssertionDep (lclNum);
4461
- BitVecOps::IntersectionD (apTraits, apDependent, apLocal);
4507
+ ASSERT_TP apDependent = BitVecOps::Intersection (apTraits, GetAssertionDep (lclNum), assertions);
4462
4508
4463
4509
// Scan those looking for a suitable assertion
4464
4510
//
4465
- BitVecOps::Iter iter (apTraits, assertions );
4511
+ BitVecOps::Iter iter (apTraits, apDependent );
4466
4512
unsigned index = 0 ;
4467
4513
while (iter.NextElem (&index ))
4468
4514
{
0 commit comments