summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-02-10 19:08:15 +0000
committerChris Lattner <sabre@nondot.org>2006-02-10 19:08:15 +0000
commitec6b40a093a11a06db045ff5bb5b2cce7f0dbc90 (patch)
tree2a8dc93c90719a67b00fa20a48098ae5b23122bd /llvm/lib/Transforms
parentfcb8a3aa76f8073193e69918e8bbd4a6c5a2f5fb (diff)
downloadbcm5719-llvm-ec6b40a093a11a06db045ff5bb5b2cce7f0dbc90.tar.gz
bcm5719-llvm-ec6b40a093a11a06db045ff5bb5b2cce7f0dbc90.zip
Fix a case where UnswitchTrivialCondition broke critical edges with
phi's in the successors llvm-svn: 26108
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/LoopUnswitch.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
index 600061de354..09f4976f100 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
@@ -34,6 +34,7 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/CommandLine.h"
@@ -255,6 +256,8 @@ bool LoopUnswitch::visitLoop(Loop *L) {
// loop.
for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
I != E; ++I) {
+ for (BasicBlock::iterator BBI = (*I)->begin(), E = (*I)->end();
+ BBI != E; ++BBI)
TerminatorInst *TI = (*I)->getTerminator();
// FIXME: Handle invariant select instructions.
@@ -415,7 +418,27 @@ void LoopUnswitch::UnswitchTrivialCondition(Loop *L, Value *Cond,
// Split this block now, so that the loop maintains its exit block.
assert(!L->contains(ExitBlock) && "Exit block is in the loop?");
- BasicBlock *NewExit = SplitBlock(ExitBlock, true);
+ BasicBlock *NewExit;
+ if (BasicBlock *SinglePred = ExitBlock->getSinglePredecessor()) {
+ assert(SinglePred == L->getLoopLatch() && "Unexpected case");
+ NewExit = SplitBlock(ExitBlock, true);
+ } else {
+ // Otherwise, this is a critical edge. Split block would split the wrong
+ // edge here, so we use SplitCriticalEdge, which allows us to specify the
+ // edge to split, not just the block.
+ TerminatorInst *LatchTerm = L->getLoopLatch()->getTerminator();
+ unsigned SuccNum = 0;
+ for (unsigned i = 0, e = LatchTerm->getNumSuccessors(); ; ++i) {
+ assert(i != e && "Didn't find edge?");
+ if (LatchTerm->getSuccessor(i) == ExitBlock) {
+ SuccNum = i;
+ break;
+ }
+ }
+ SplitCriticalEdge(LatchTerm, SuccNum, this);
+ NewExit = LatchTerm->getSuccessor(SuccNum);
+ assert(NewExit != ExitBlock && "Edge not split!");
+ }
// Okay, now we have a position to branch from and a position to branch to,
// insert the new conditional branch.
OpenPOWER on IntegriCloud