[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