[llvm] 2353e1c - [NFC][SimplifyCFG] Extract `performBlockTailMerging()` out of `tailMergeBlocksWithSimilarFunctionTerminators()`
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 5 12:00:00 PST 2022
Author: Roman Lebedev
Date: 2022-01-05T22:59:39+03:00
New Revision: 2353e1c87b09c20e75f0f3ceb05fa4a4261fe3dd
URL: https://github.com/llvm/llvm-project/commit/2353e1c87b09c20e75f0f3ceb05fa4a4261fe3dd
DIFF: https://github.com/llvm/llvm-project/commit/2353e1c87b09c20e75f0f3ceb05fa4a4261fe3dd.diff
LOG: [NFC][SimplifyCFG] Extract `performBlockTailMerging()` out of `tailMergeBlocksWithSimilarFunctionTerminators()`
Added:
Modified:
llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
index 3799d2dd1cf27..b830c07715ae2 100644
--- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
+++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp
@@ -78,6 +78,79 @@ static cl::opt<bool> UserSinkCommonInsts(
STATISTIC(NumSimpl, "Number of blocks simplified");
+static bool
+performBlockTailMerging(Function &F, ArrayRef<BasicBlock *> BBs,
+ std::vector<DominatorTree::UpdateType> *Updates) {
+ SmallVector<PHINode *, 1> NewOps;
+
+ // We don't want to change IR just because we can.
+ // Only do that if there are at least two blocks we'll tail-merge.
+ if (BBs.size() < 2)
+ return false;
+
+ if (Updates)
+ Updates->reserve(Updates->size() + BBs.size());
+
+ BasicBlock *CanonicalBB;
+ Instruction *CanonicalTerm;
+ {
+ auto *Term = BBs[0]->getTerminator();
+
+ // Create a canonical block for this function terminator type now,
+ // placing it *before* the first block that will branch to it.
+ CanonicalBB = BasicBlock::Create(
+ F.getContext(), Twine("common.") + Term->getOpcodeName(), &F, BBs[0]);
+ // We'll also need a PHI node per each operand of the terminator.
+ NewOps.resize(Term->getNumOperands());
+ for (auto I : zip(Term->operands(), NewOps)) {
+ std::get<1>(I) = PHINode::Create(std::get<0>(I)->getType(),
+ /*NumReservedValues=*/BBs.size(),
+ CanonicalBB->getName() + ".op");
+ CanonicalBB->getInstList().push_back(std::get<1>(I));
+ }
+ // Make it so that this canonical block actually has the right
+ // terminator.
+ CanonicalTerm = Term->clone();
+ CanonicalBB->getInstList().push_back(CanonicalTerm);
+ // If the canonical terminator has operands, rewrite it to take PHI's.
+ for (auto I : zip(NewOps, CanonicalTerm->operands()))
+ std::get<1>(I) = std::get<0>(I);
+ }
+
+ // Now, go through each block (with the current terminator type)
+ // we've recorded, and rewrite it to branch to the new common block.
+ const DILocation *CommonDebugLoc = nullptr;
+ for (BasicBlock *BB : BBs) {
+ auto *Term = BB->getTerminator();
+ assert(Term->getOpcode() == CanonicalTerm->getOpcode() &&
+ "All blocks to be tail-merged must be the same "
+ "(function-terminating) terminator type.");
+
+ // Aha, found a new non-canonical function terminator. If it has operands,
+ // forward them to the PHI nodes in the canonical block.
+ for (auto I : zip(Term->operands(), NewOps))
+ std::get<1>(I)->addIncoming(std::get<0>(I), BB);
+
+ // Compute the debug location common to all the original terminators.
+ if (!CommonDebugLoc)
+ CommonDebugLoc = Term->getDebugLoc();
+ else
+ CommonDebugLoc =
+ DILocation::getMergedLocation(CommonDebugLoc, Term->getDebugLoc());
+
+ // And turn BB into a block that just unconditionally branches
+ // to the canonical block.
+ Term->eraseFromParent();
+ BranchInst::Create(CanonicalBB, BB);
+ if (Updates)
+ Updates->push_back({DominatorTree::Insert, BB, CanonicalBB});
+ }
+
+ CanonicalTerm->setDebugLoc(CommonDebugLoc);
+
+ return true;
+}
+
static bool tailMergeBlocksWithSimilarFunctionTerminators(Function &F,
DomTreeUpdater *DTU) {
SmallMapVector<unsigned /*TerminatorOpcode*/, SmallVector<BasicBlock *, 2>, 4>
@@ -133,73 +206,8 @@ static bool tailMergeBlocksWithSimilarFunctionTerminators(Function &F,
std::vector<DominatorTree::UpdateType> Updates;
- for (ArrayRef<BasicBlock *> BBs : make_second_range(Structure)) {
- SmallVector<PHINode *, 1> NewOps;
-
- // We don't want to change IR just because we can.
- // Only do that if there are at least two blocks we'll tail-merge.
- if (BBs.size() < 2)
- continue;
-
- Changed = true;
-
- if (DTU)
- Updates.reserve(Updates.size() + BBs.size());
-
- BasicBlock *CanonicalBB;
- Instruction *CanonicalTerm;
- {
- auto *Term = BBs[0]->getTerminator();
-
- // Create a canonical block for this function terminator type now,
- // placing it *before* the first block that will branch to it.
- CanonicalBB = BasicBlock::Create(
- F.getContext(), Twine("common.") + Term->getOpcodeName(), &F, BBs[0]);
- // We'll also need a PHI node per each operand of the terminator.
- NewOps.resize(Term->getNumOperands());
- for (auto I : zip(Term->operands(), NewOps)) {
- std::get<1>(I) = PHINode::Create(std::get<0>(I)->getType(),
- /*NumReservedValues=*/BBs.size(),
- CanonicalBB->getName() + ".op");
- CanonicalBB->getInstList().push_back(std::get<1>(I));
- }
- // Make it so that this canonical block actually has the right
- // terminator.
- CanonicalTerm = Term->clone();
- CanonicalBB->getInstList().push_back(CanonicalTerm);
- // If the canonical terminator has operands, rewrite it to take PHI's.
- for (auto I : zip(NewOps, CanonicalTerm->operands()))
- std::get<1>(I) = std::get<0>(I);
- }
-
- // Now, go through each block (with the current terminator type)
- // we've recorded, and rewrite it to branch to the new common block.
- const DILocation *CommonDebugLoc = nullptr;
- for (BasicBlock *BB : BBs) {
- auto *Term = BB->getTerminator();
-
- // Aha, found a new non-canonical function terminator. If it has operands,
- // forward them to the PHI nodes in the canonical block.
- for (auto I : zip(Term->operands(), NewOps))
- std::get<1>(I)->addIncoming(std::get<0>(I), BB);
-
- // Compute the debug location common to all the original terminators.
- if (!CommonDebugLoc)
- CommonDebugLoc = Term->getDebugLoc();
- else
- CommonDebugLoc =
- DILocation::getMergedLocation(CommonDebugLoc, Term->getDebugLoc());
-
- // And turn BB into a block that just unconditionally branches
- // to the canonical block.
- Term->eraseFromParent();
- BranchInst::Create(CanonicalBB, BB);
- if (DTU)
- Updates.push_back({DominatorTree::Insert, BB, CanonicalBB});
- }
-
- CanonicalTerm->setDebugLoc(CommonDebugLoc);
- }
+ for (ArrayRef<BasicBlock *> BBs : make_second_range(Structure))
+ Changed |= performBlockTailMerging(F, BBs, DTU ? &Updates : nullptr);
if (DTU)
DTU->applyUpdates(Updates);
More information about the llvm-commits
mailing list