Skip to content

Commit ad42b51

Browse files
committed
JIT: cross-block local assertion prop in morph
During global morph, allow assertions to propagate to a block from the block's predecessors. Handle special cases where we can't allow this to happen: * block has preds that have not yet been morphed * block has no preds * block is specially flagged as one that might gain new preds during morph * block is an EH handler entry Contributes to dotnet#93246.
1 parent 76a995a commit ad42b51

File tree

3 files changed

+81
-6
lines changed

3 files changed

+81
-6
lines changed

src/coreclr/jit/assertionprop.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -4379,12 +4379,11 @@ AssertionIndex Compiler::optAssertionIsNonNullInternal(GenTree* op,
43794379
// Find live assertions related to lclNum
43804380
//
43814381
unsigned const lclNum = op->AsLclVarCommon()->GetLclNum();
4382-
ASSERT_TP apDependent = GetAssertionDep(lclNum);
4383-
BitVecOps::IntersectionD(apTraits, apDependent, apLocal);
4382+
ASSERT_TP apDependent = BitVecOps::Intersection(apTraits, GetAssertionDep(lclNum), assertions);
43844383

43854384
// Scan those looking for a suitable assertion
43864385
//
4387-
BitVecOps::Iter iter(apTraits, assertions);
4386+
BitVecOps::Iter iter(apTraits, apDependent);
43884387
unsigned index = 0;
43894388
while (iter.NextElem(&index))
43904389
{

src/coreclr/jit/jitconfigvalues.h

+3
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,9 @@ CONFIG_INTEGER(JitNoRngChks, W("JitNoRngChks"), 0) // If 1, don't generate range
445445

446446
#if defined(OPT_CONFIG)
447447
CONFIG_INTEGER(JitDoAssertionProp, W("JitDoAssertionProp"), 1) // Perform assertion propagation optimization
448+
CONFIG_INTEGER(JitDoCrossBlockLocalAssertionProp, W("JitDoCrossBlockLocalAssertionProp"), 1) // Perform local assertion
449+
// propagation optimization
450+
// cross-block
448451
CONFIG_INTEGER(JitDoCopyProp, W("JitDoCopyProp"), 1) // Perform copy propagation on variables that appear redundant
449452
CONFIG_INTEGER(JitDoEarlyProp, W("JitDoEarlyProp"), 1) // Perform Early Value Propagation
450453
CONFIG_INTEGER(JitDoLoopHoisting, W("JitDoLoopHoisting"), 1) // Perform loop hoisting on loop invariant values

src/coreclr/jit/morph.cpp

+76-3
Original file line numberDiff line numberDiff line change
@@ -13780,10 +13780,78 @@ void Compiler::fgMorphBlock(BasicBlock* block)
1378013780

1378113781
if (optLocalAssertionProp)
1378213782
{
13783-
// For now, each block starts with an empty table, and no available assertions
13783+
// Determine if this block can leverage assertions from its pred blocks.
1378413784
//
13785-
optAssertionReset(0);
13786-
apLocal = BitVecOps::MakeEmpty(apTraits);
13785+
// Some blocks are ineligible.
13786+
//
13787+
bool canUsePredAssertions = ((block->bbFlags & BBF_CAN_ADD_PRED) == 0) && !bbIsHandlerBeg(block);
13788+
13789+
#ifdef DEBUG
13790+
// Optionally suppress via config
13791+
//
13792+
if (JitConfig.JitDoCrossBlockLocalAssertionProp() == 0)
13793+
{
13794+
canUsePredAssertions = false;
13795+
}
13796+
#endif
13797+
13798+
// Validate all preds have valid info
13799+
//
13800+
if (canUsePredAssertions)
13801+
{
13802+
bool hasPred = false;
13803+
13804+
for (BasicBlock* const pred : block->PredBlocks())
13805+
{
13806+
// A higher postorder number means the block appears earlier in
13807+
// the postorder. Use this to detect if a pred's assertion info is available.
13808+
//
13809+
if (pred->bbPostorderNum > block->bbPostorderNum)
13810+
{
13811+
// Yes, available. If this is the first pred, copy.
13812+
// If this is a subsequent pred, intersect.
13813+
//
13814+
if (!hasPred)
13815+
{
13816+
apLocal = BitVecOps::MakeCopy(apTraits, pred->bbAssertionOut);
13817+
hasPred = true;
13818+
}
13819+
else
13820+
{
13821+
BitVecOps::IntersectionD(apTraits, apLocal, pred->bbAssertionOut);
13822+
}
13823+
13824+
continue;
13825+
}
13826+
13827+
// No, not available.
13828+
//
13829+
JITDUMP(FMT_BB " pred " FMT_BB " not processed; clearing assertions in\n", block->bbNum, pred->bbNum);
13830+
canUsePredAssertions = false;
13831+
}
13832+
13833+
// If there were no preds, there are no asserions in.
13834+
//
13835+
if (!hasPred)
13836+
{
13837+
JITDUMP(FMT_BB " has no preds, so no assertions in\n", block->bbNum);
13838+
canUsePredAssertions = false;
13839+
}
13840+
13841+
if (canUsePredAssertions)
13842+
{
13843+
JITDUMPEXEC(optDumpAssertionIndices("Assertions in: ", apLocal));
13844+
}
13845+
}
13846+
else
13847+
{
13848+
JITDUMP(FMT_BB " ineligible for cross-block; clearing assertions in\n", block->bbNum);
13849+
}
13850+
13851+
if (!canUsePredAssertions)
13852+
{
13853+
apLocal = BitVecOps::MakeEmpty(apTraits);
13854+
}
1378713855
}
1378813856

1378913857
// Make the current basic block address available globally.
@@ -13801,6 +13869,11 @@ void Compiler::fgMorphBlock(BasicBlock* block)
1380113869
}
1380213870
}
1380313871

13872+
if (optLocalAssertionProp && (block->NumSucc() > 0))
13873+
{
13874+
block->bbAssertionOut = BitVecOps::MakeCopy(apTraits, apLocal);
13875+
}
13876+
1380413877
compCurBB = nullptr;
1380513878
}
1380613879

0 commit comments

Comments
 (0)