diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 6472e1771ec73..68d1fd892402c 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -1054,6 +1054,50 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, return SplitBlockImpl(Old, SplitPt, DTU, /*DT=*/nullptr, LI, MSSAU, BBName); } +BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, BasicBlock::iterator SplitPt, + DomTreeUpdater *DTU, LoopInfo *LI, + MemorySSAUpdater *MSSAU, + const Twine &BBName) { + + BasicBlock::iterator SplitIt = SplitPt; + while (isa(SplitIt) || SplitIt->isEHPad()) + ++SplitIt; + std::string Name = BBName.str(); + BasicBlock *New = Old->splitBasicBlockBefore( + SplitIt, Name.empty() ? Old->getName() + ".split" : Name); + + // The new block lives in whichever loop the old one did. This preserves + // LCSSA as well, because we force the split point to be after any PHI nodes. + if (LI) + if (Loop *L = LI->getLoopFor(Old)) + L->addBasicBlockToLoop(New, *LI); + + if (DTU) { + SmallVector DTUpdates; + // New dominates Old. The predecessor nodes of the Old node dominate + // New node. + SmallPtrSet UniquePredecessorsOfOld; + DTUpdates.push_back({DominatorTree::Insert, New, Old}); + DTUpdates.reserve(DTUpdates.size() + 2 * pred_size(New)); + for (BasicBlock *PredecessorOfOld : predecessors(New)) + if (UniquePredecessorsOfOld.insert(PredecessorOfOld).second) { + DTUpdates.push_back({DominatorTree::Insert, PredecessorOfOld, New}); + DTUpdates.push_back({DominatorTree::Delete, PredecessorOfOld, Old}); + } + + DTU->applyUpdates(DTUpdates); + + // Move MemoryAccesses still tracked in Old, but part of New now. + // Update accesses in successor blocks accordingly. + if (MSSAU) { + MSSAU->applyUpdates(DTUpdates, DTU->getDomTree()); + if (VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + } + } + return New; +} + /// Update DominatorTree, LoopInfo, and LCCSA analysis information. /// Invalidates DFS Numbering when DTU or DT is provided. static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB, @@ -1168,25 +1212,6 @@ static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB, } } -BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, - BasicBlock::iterator SplitPt, - DomTreeUpdater *DTU, LoopInfo *LI, - MemorySSAUpdater *MSSAU, - const Twine &BBName) { - BasicBlock::iterator SplitIt = SplitPt; - while (isa(SplitIt) || SplitIt->isEHPad()) - ++SplitIt; - SmallVector Preds(predecessors(Old)); - BasicBlock *New = Old->splitBasicBlockBefore( - SplitIt, BBName.isTriviallyEmpty() ? Old->getName() + ".split" : BBName); - - bool HasLoopExit = false; - UpdateAnalysisInformation(Old, New, Preds, DTU, nullptr, LI, MSSAU, false, - HasLoopExit); - - return New; -} - /// Update the PHI nodes in OrigBB to include the values coming from NewBB. /// This also updates AliasAnalysis, if available. static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB, diff --git a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp index d5b4f6b6d6593..00d9e9ff81e05 100644 --- a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp @@ -378,31 +378,6 @@ define i32 @no_unreachable(i1 %cond) { EXPECT_TRUE(DT.verify()); } -TEST(BasicBlockUtils, splitBlockBefore) { - LLVMContext C; - std::unique_ptr M = parseIR(C, R"IR( -define i32 @basic_func(i1 %cond) { -entry: - br i1 %cond, label %bb0, label %bb1 -bb0: - br label %bb1 -bb1: - %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ] - ret i32 %phi -} -)IR"); - Function *F = M->getFunction("basic_func"); - DominatorTree DT(*F); - DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); - BasicBlock *EntryBB = &F->getEntryBlock(); - Instruction *TI = EntryBB->getTerminator(); - - // Make sure the dominator tree is properly updated if calling this on the - // entry block. - splitBlockBefore(EntryBB, TI, &DTU, nullptr, nullptr); - EXPECT_TRUE(DTU.getDomTree().verify()); -} - TEST(BasicBlockUtils, SplitBlockPredecessors) { LLVMContext C; std::unique_ptr M = parseIR(C, R"IR(