Skip to content

Commit e4d4736

Browse files
authored
Merge return true/false blocks
1 parent b1f403b commit e4d4736

1 file changed

Lines changed: 101 additions & 69 deletions

File tree

src/coreclr/jit/fgopt.cpp

Lines changed: 101 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -6729,69 +6729,7 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
67296729
// If return value is true, retry.
67306730
// May also add to retryBlocks.
67316731
//
6732-
auto tailMerge = [&](BasicBlock* block) -> bool {
6733-
6734-
if (block->countOfInEdges() < 2)
6735-
{
6736-
// Nothing to merge here
6737-
return false;
6738-
}
6739-
6740-
predInfo.Reset();
6741-
6742-
// Find the subset of preds that reach along non-critical edges
6743-
// and populate predInfo.
6744-
//
6745-
for (BasicBlock* const predBlock : block->PredBlocks())
6746-
{
6747-
if (predBlock->GetUniqueSucc() != block)
6748-
{
6749-
continue;
6750-
}
6751-
6752-
if (!BasicBlock::sameEHRegion(block, predBlock))
6753-
{
6754-
continue;
6755-
}
6756-
6757-
Statement* lastStmt = predBlock->lastStmt();
6758-
6759-
// Block might be empty.
6760-
//
6761-
if (lastStmt == nullptr)
6762-
{
6763-
continue;
6764-
}
6765-
6766-
// Walk back past any GT_NOPs.
6767-
//
6768-
Statement* const firstStmt = predBlock->firstStmt();
6769-
while (lastStmt->GetRootNode()->OperIs(GT_NOP))
6770-
{
6771-
if (lastStmt == firstStmt)
6772-
{
6773-
// predBlock is evidently all GT_NOP.
6774-
//
6775-
lastStmt = nullptr;
6776-
break;
6777-
}
6778-
6779-
lastStmt = lastStmt->GetPrevStmt();
6780-
}
6781-
6782-
// Block might be effectively empty.
6783-
//
6784-
if (lastStmt == nullptr)
6785-
{
6786-
continue;
6787-
}
6788-
6789-
// We don't expect to see PHIs but watch for them anyways.
6790-
//
6791-
assert(!lastStmt->IsPhiDefnStmt());
6792-
predInfo.Emplace(predBlock, lastStmt);
6793-
}
6794-
6732+
auto tailMergePreds = [&](BasicBlock* commSucc) -> bool {
67956733
// Are there enough preds to make it interesting?
67966734
//
67976735
if (predInfo.Height() < 2)
@@ -6842,9 +6780,9 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
68426780
// We have some number of preds that have identical last statements.
68436781
// If all preds of block have a matching last stmt, move that statement to the start of block.
68446782
//
6845-
if (matchedPredInfo.Height() == (int)block->countOfInEdges())
6783+
if ((commSucc != nullptr) && (matchedPredInfo.Height() == (int)commSucc->countOfInEdges()))
68466784
{
6847-
JITDUMP("All preds of " FMT_BB " end with the same tree, moving\n", block->bbNum);
6785+
JITDUMP("All preds of " FMT_BB " end with the same tree, moving\n", commSucc->bbNum);
68486786
JITDUMPEXEC(gtDispStmt(matchedPredInfo.TopRef(0).m_stmt));
68496787

68506788
for (int j = 0; j < matchedPredInfo.Height(); j++)
@@ -6860,8 +6798,8 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
68606798
//
68616799
if (j == 0)
68626800
{
6863-
fgInsertStmtAtBeg(block, stmt);
6864-
block->bbFlags |= predBlock->bbFlags & BBF_COPY_PROPAGATE;
6801+
fgInsertStmtAtBeg(commSucc, stmt);
6802+
commSucc->bbFlags |= predBlock->bbFlags & BBF_COPY_PROPAGATE;
68656803
}
68666804

68676805
madeChanges = true;
@@ -6876,7 +6814,16 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
68766814
// Pick one block as the victim -- preferably a block with just one
68776815
// statement or one that falls through to block (or both).
68786816
//
6879-
JITDUMP("A set of %d preds of " FMT_BB " end with the same tree\n", matchedPredInfo.Height(), block->bbNum);
6817+
if (commSucc != nullptr)
6818+
{
6819+
JITDUMP("A set of %d preds of " FMT_BB " end with the same tree\n", matchedPredInfo.Height(),
6820+
commSucc->bbNum);
6821+
}
6822+
else
6823+
{
6824+
JITDUMP("A set of %d return blocks end with the same tree\n", matchedPredInfo.Height());
6825+
}
6826+
68806827
JITDUMPEXEC(gtDispStmt(matchedPredInfo.TopRef(0).m_stmt));
68816828

68826829
BasicBlock* crossJumpVictim = nullptr;
@@ -6977,7 +6924,10 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
69776924
//
69786925
predBlock->SetJumpKindAndTarget(BBJ_ALWAYS, crossJumpTarget DEBUG_ARG(this));
69796926

6980-
fgRemoveRefPred(block, predBlock);
6927+
if (commSucc != nullptr)
6928+
{
6929+
fgRemoveRefPred(commSucc, predBlock);
6930+
}
69816931
fgAddRefPred(crossJumpTarget, predBlock);
69826932
}
69836933

@@ -7001,6 +6951,71 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
70016951
return false;
70026952
};
70036953

6954+
auto tailMerge = [&](BasicBlock* block) -> bool {
6955+
if (block->countOfInEdges() < 2)
6956+
{
6957+
// Nothing to merge here
6958+
return false;
6959+
}
6960+
6961+
predInfo.Reset();
6962+
6963+
// Find the subset of preds that reach along non-critical edges
6964+
// and populate predInfo.
6965+
//
6966+
for (BasicBlock* const predBlock : block->PredBlocks())
6967+
{
6968+
if (predBlock->GetUniqueSucc() != block)
6969+
{
6970+
continue;
6971+
}
6972+
6973+
if (!BasicBlock::sameEHRegion(block, predBlock))
6974+
{
6975+
continue;
6976+
}
6977+
6978+
Statement* lastStmt = predBlock->lastStmt();
6979+
6980+
// Block might be empty.
6981+
//
6982+
if (lastStmt == nullptr)
6983+
{
6984+
continue;
6985+
}
6986+
6987+
// Walk back past any GT_NOPs.
6988+
//
6989+
Statement* const firstStmt = predBlock->firstStmt();
6990+
while (lastStmt->GetRootNode()->OperIs(GT_NOP))
6991+
{
6992+
if (lastStmt == firstStmt)
6993+
{
6994+
// predBlock is evidently all GT_NOP.
6995+
//
6996+
lastStmt = nullptr;
6997+
break;
6998+
}
6999+
7000+
lastStmt = lastStmt->GetPrevStmt();
7001+
}
7002+
7003+
// Block might be effectively empty.
7004+
//
7005+
if (lastStmt == nullptr)
7006+
{
7007+
continue;
7008+
}
7009+
7010+
// We don't expect to see PHIs but watch for them anyways.
7011+
//
7012+
assert(!lastStmt->IsPhiDefnStmt());
7013+
predInfo.Emplace(predBlock, lastStmt);
7014+
}
7015+
7016+
return tailMergePreds(block);
7017+
};
7018+
70047019
auto iterateTailMerge = [&](BasicBlock* block) -> void {
70057020

70067021
int numOpts = 0;
@@ -7016,13 +7031,30 @@ PhaseStatus Compiler::fgHeadTailMerge(bool early)
70167031
}
70177032
};
70187033

7034+
ArrayStack<BasicBlock*> retBlocks(getAllocator(CMK_ArrayStack));
7035+
70197036
// Visit each block
70207037
//
70217038
for (BasicBlock* const block : Blocks())
70227039
{
70237040
iterateTailMerge(block);
7041+
7042+
// TODO: consider removing hasSingleStmt(), it should find more opportunities
7043+
// (with size and TP regressions)
7044+
if (block->KindIs(BBJ_RETURN) && block->hasSingleStmt() && (block != genReturnBB))
7045+
{
7046+
retBlocks.Push(block);
7047+
}
70247048
}
70257049

7050+
predInfo.Reset();
7051+
for (int i = 0; i < retBlocks.Height(); i++)
7052+
{
7053+
predInfo.Push(PredInfo(retBlocks.Bottom(i), retBlocks.Bottom(i)->lastStmt()));
7054+
}
7055+
7056+
tailMergePreds(nullptr);
7057+
70267058
// Work through any retries
70277059
//
70287060
while (retryBlocks.Height() > 0)

0 commit comments

Comments
 (0)