diff options
author | Bangtian Liu <bangtian@cs.toronto.edu> | 2020-12-17 15:58:45 +0000 |
---|---|---|
committer | Whitney Tsang <whitneyt@ca.ibm.com> | 2020-12-17 16:00:15 +0000 |
commit | d20e0c3444ad9ada550d9d6d1d56fd72948ae444 (patch) | |
tree | 27f549bb991f7d0552abe32d3387cc6388cd2204 /llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | |
parent | 7e13694ac745f6cd4008dd354f2fcfc417b1e1e9 (diff) | |
download | llvm-d20e0c3444ad9ada550d9d6d1d56fd72948ae444.zip llvm-d20e0c3444ad9ada550d9d6d1d56fd72948ae444.tar.gz llvm-d20e0c3444ad9ada550d9d6d1d56fd72948ae444.tar.bz2 |
Ensure SplitEdge to return the new block between the two given blocks
This PR implements the function splitBasicBlockBefore to address an
issue
that occurred during SplitEdge(BB, Succ, ...), inside splitBlockBefore.
The issue occurs in SplitEdge when the Succ has a single predecessor
and the edge between the BB and Succ is not critical. This produces
the result ‘BB->Succ->New’. The new function splitBasicBlockBefore
was added to splitBlockBefore to handle the issue and now produces
the correct result ‘BB->New->Succ’.
Below is an example of splitting the block bb1 at its first instruction.
/// Original IR
bb0:
br bb1
bb1:
%0 = mul i32 1, 2
br bb2
bb2:
/// IR after splitEdge(bb0, bb1) using splitBasicBlock
bb0:
br bb1
bb1:
br bb1.split
bb1.split:
%0 = mul i32 1, 2
br bb2
bb2:
/// IR after splitEdge(bb0, bb1) using splitBasicBlockBefore
bb0:
br bb1.split
bb1.split
br bb1
bb1:
%0 = mul i32 1, 2
br bb2
bb2:
Differential Revision: https://reviews.llvm.org/D92200
Diffstat (limited to 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 85d1be1..14795d4 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -510,7 +510,7 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, DominatorTree *DT, // block. assert(SP == BB && "CFG broken"); SP = nullptr; - return SplitBlock(Succ, &Succ->front(), DT, LI, MSSAU); + return SplitBlock(Succ, &Succ->front(), DT, LI, MSSAU, "", /*Before=*/true); } // Otherwise, if BB has a single successor, split it at the bottom of the @@ -537,7 +537,10 @@ llvm::SplitAllCriticalEdges(Function &F, BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT, LoopInfo *LI, - MemorySSAUpdater *MSSAU, const Twine &BBName) { + MemorySSAUpdater *MSSAU, const Twine &BBName, + bool Before) { + if (Before) + return splitBlockBefore(Old, SplitPt, DT, LI, MSSAU, BBName); BasicBlock::iterator SplitIt = SplitPt->getIterator(); while (isa<PHINode>(SplitIt) || SplitIt->isEHPad()) ++SplitIt; @@ -569,6 +572,51 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, return New; } +BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, Instruction *SplitPt, + DominatorTree *DT, LoopInfo *LI, + MemorySSAUpdater *MSSAU, + const Twine &BBName) { + + BasicBlock::iterator SplitIt = SplitPt->getIterator(); + while (isa<PHINode>(SplitIt) || SplitIt->isEHPad()) + ++SplitIt; + std::string Name = BBName.str(); + BasicBlock *New = Old->splitBasicBlock( + SplitIt, Name.empty() ? Old->getName() + ".split" : Name, + /* Before=*/true); + + // 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 (DT) { + DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); + SmallVector<DominatorTree::UpdateType, 8> DTUpdates; + // New dominates Old. The predecessor nodes of the Old node dominate + // New node. + DTUpdates.push_back({DominatorTree::Insert, New, Old}); + for (BasicBlock *Pred : predecessors(New)) + if (DT->getNode(Pred)) { + DTUpdates.push_back({DominatorTree::Insert, Pred, New}); + DTUpdates.push_back({DominatorTree::Delete, Pred, Old}); + } + + DTU.applyUpdates(DTUpdates); + DTU.flush(); + + // Move MemoryAccesses still tracked in Old, but part of New now. + // Update accesses in successor blocks accordingly. + if (MSSAU) { + MSSAU->applyUpdates(DTUpdates, *DT); + if (VerifyMemorySSA) + MSSAU->getMemorySSA()->verifyMemorySSA(); + } + } + return New; +} + /// Update DominatorTree, LoopInfo, and LCCSA analysis information. static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB, ArrayRef<BasicBlock *> Preds, |