diff --git a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h --- a/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/DomTreeUpdater.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/InstrTypes.h" @@ -96,6 +97,17 @@ MemoryDependenceResults *MemDep = nullptr, bool PredecessorWithTwoSuccessors = false); +/// Merge block(s) sucessors, if possible. Return true if at least two +/// of the blocks were merged together. +/// In order to merge, each block must be terminated by an unconditional +/// branch. If L is provided, then the blocks merged into their predecessors +/// must be in L. In addition, This utility calls on another utility: +/// MergeBlockIntoPredecessor. Blocks are successfully merged when the call to +/// MergeBlockIntoPredecessor returns true. +bool MergeBlockSuccessorsIntoGivenBlocks( + SmallPtrSetImpl &MergeBlocks, Loop *L = nullptr, + DomTreeUpdater *DTU = nullptr, LoopInfo *LI = nullptr); + /// Try to remove redundant dbg.value instructions from given basic block. /// Returns true if at least one instruction was removed. bool RemoveRedundantDbgInstrs(BasicBlock *BB); diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -315,6 +315,31 @@ return true; } +bool llvm::MergeBlockSuccessorsIntoGivenBlocks( + SmallPtrSetImpl &MergeBlocks, Loop *L, DomTreeUpdater *DTU, + LoopInfo *LI) { + assert(!MergeBlocks.empty() && "MergeBlocks should not be empty"); + + bool BlocksHaveBeenMerged = false; + while (!MergeBlocks.empty()) { + BasicBlock *BB = *MergeBlocks.begin(); + BasicBlock *Dest = BB->getSingleSuccessor(); + if (Dest && (!L || L->contains(Dest))) { + BasicBlock *Fold = Dest->getUniquePredecessor(); + (void)Fold; + if (MergeBlockIntoPredecessor(Dest, DTU, LI)) { + assert(Fold == BB && + "Expecting BB to be unique predecessor of the Dest block"); + MergeBlocks.erase(Dest); + BlocksHaveBeenMerged = true; + } else + MergeBlocks.erase(BB); + } else + MergeBlocks.erase(BB); + } + return BlocksHaveBeenMerged; +} + /// Remove redundant instructions within sequences of consecutive dbg.value /// instructions. This is done using a backward scan to keep the last dbg.value /// describing a specific variable/fragment. diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -593,22 +593,9 @@ MergeBlocks.insert(ForeBlocksLast.begin(), ForeBlocksLast.end()); MergeBlocks.insert(SubLoopBlocksLast.begin(), SubLoopBlocksLast.end()); MergeBlocks.insert(AftBlocksLast.begin(), AftBlocksLast.end()); - while (!MergeBlocks.empty()) { - BasicBlock *BB = *MergeBlocks.begin(); - BranchInst *Term = dyn_cast(BB->getTerminator()); - if (Term && Term->isUnconditional() && L->contains(Term->getSuccessor(0))) { - BasicBlock *Dest = Term->getSuccessor(0); - BasicBlock *Fold = Dest->getUniquePredecessor(); - if (MergeBlockIntoPredecessor(Dest, &DTU, LI)) { - // Don't remove BB and add Fold as they are the same BB - assert(Fold == BB); - (void)Fold; - MergeBlocks.erase(Dest); - } else - MergeBlocks.erase(BB); - } else - MergeBlocks.erase(BB); - } + + MergeBlockSuccessorsIntoGivenBlocks(MergeBlocks, L, &DTU, LI); + // Apply updates to the DomTree. DT = &DTU.getDomTree();