diff options
| author | Nadav Rotem <nrotem@apple.com> | 2012-08-14 05:19:07 +0000 | 
|---|---|---|
| committer | Nadav Rotem <nrotem@apple.com> | 2012-08-14 05:19:07 +0000 | 
| commit | 70409991bc92beaced7a9abb7c5f2f1e30cc3721 (patch) | |
| tree | def3a79a70ea6635a6c9cab07672ba229a85783a /llvm/lib/Transforms/Scalar | |
| parent | 160522c25acd8508903feea0f7fbb45b324ffcdf (diff) | |
| download | bcm5719-llvm-70409991bc92beaced7a9abb7c5f2f1e30cc3721.tar.gz bcm5719-llvm-70409991bc92beaced7a9abb7c5f2f1e30cc3721.zip | |
During the CodeGenPrepare we often lower intrinsics (such as objsize)
and allow some optimizations to turn conditional branches into unconditional.
This commit adds a simple control-flow optimization which merges two consecutive
basic blocks which are connected by a single edge. This allows the codegen to
operate on larger basic blocks.
rdar://11973998
llvm-svn: 161852
Diffstat (limited to 'llvm/lib/Transforms/Scalar')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp | 39 | 
1 files changed, 39 insertions, 0 deletions
| diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 4b4a8c598fc..bc87106b3d2 100644 --- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -116,6 +116,7 @@ namespace {      }    private: +    bool EliminateFallThrough(Function &F);      bool EliminateMostlyEmptyBlocks(Function &F);      bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const;      void EliminateMostlyEmptyBlock(BasicBlock *BB); @@ -192,6 +193,11 @@ bool CodeGenPrepare::runOnFunction(Function &F) {               I = WorkList.begin(), E = WorkList.end(); I != E; ++I)          DeleteDeadBlock(*I); +    // Merge pairs of basic blocks with unconditional branches, connected by +    // a single edge. +    if (EverMadeChange || MadeChange) +      MadeChange |= EliminateFallThrough(F); +      if (MadeChange)        ModifiedDT = true;      EverMadeChange |= MadeChange; @@ -203,6 +209,39 @@ bool CodeGenPrepare::runOnFunction(Function &F) {    return EverMadeChange;  } +/// EliminateFallThrough - Merge basic blocks which are connected +/// by a single edge, where one of the basic blocks has a single successor +/// pointing to the other basic block, which has a single predecessor. +bool CodeGenPrepare::EliminateFallThrough(Function &F) { +  bool Changed = false; +  // Scan all of the blocks in the function, except for the entry block. +  for (Function::iterator I = ++F.begin(), E = F.end(); I != E; ) { +    BasicBlock *BB = I++; +    // If the destination block has a single pred, then this is a trivial +    // edge, just collapse it. +    BasicBlock *SinglePred = BB->getSinglePredecessor(); + +    if (!SinglePred || SinglePred == BB) continue; + +    BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator()); +    if (Term && !Term->isConditional()) { +      Changed = true; +      // Remember if SinglePred was the entry block of the function. +      // If so, we will need to move BB back to the entry position. +      bool isEntry = SinglePred == &SinglePred->getParent()->getEntryBlock(); +      MergeBasicBlockIntoOnlyPred(BB, this); + +      if (isEntry && BB != &BB->getParent()->getEntryBlock()) +        BB->moveBefore(&BB->getParent()->getEntryBlock()); + +      // We have erased a block. Update the iterator. +      I = BB; +      DEBUG(dbgs() << "Merged:\n"<< *SinglePred << "\n\n\n"); +    } +  } +  return Changed; +} +  /// EliminateMostlyEmptyBlocks - eliminate blocks that contain only PHI nodes,  /// debug info directives, and an unconditional branch.  Passes before isel  /// (e.g. LSR/loopsimplify) often split edges in ways that are non-optimal for | 

