assert(BB && BB->getParent() && "Block not embedded in function!");
assert(BB->getTerminator() && "Degenerate basic block encountered!");
- assert(&BB->getParent()->getEntryBlock() != BB &&
- "Can't Simplify entry block!");
- // Remove basic blocks that have no predecessors... or that just have themself
- // as a predecessor. These are unreachable.
- if (pred_begin(BB) == pred_end(BB) || BB->getSinglePredecessor() == BB) {
+ // Remove basic blocks that have no predecessors (except the entry block)...
+ // or that just have themself as a predecessor. These are unreachable.
+ if ((pred_begin(BB) == pred_end(BB) &&
+ &BB->getParent()->getEntryBlock() != BB) ||
+ BB->getSinglePredecessor() == BB) {
DEBUG(dbgs() << "Removing BB: \n" << *BB);
DeleteDeadBlock(BB);
return true;
while (isa<DbgInfoIntrinsic>(BBI))
++BBI;
if (BBI->isTerminator()) // Terminator is the only non-phi instruction!
- if (TryToSimplifyUncondBranchFromEmptyBlock(BB))
- return true;
+ if (BB != &BB->getParent()->getEntryBlock())
+ if (TryToSimplifyUncondBranchFromEmptyBlock(BB))
+ return true;
} else { // Conditional branch
if (isValueEqualityComparison(BI)) {
}
// If this block is now dead, remove it.
- if (pred_begin(BB) == pred_end(BB)) {
+ if (pred_begin(BB) == pred_end(BB) &&
+ BB != &BB->getParent()->getEntryBlock()) {
// We know there are no successors, so just nuke the block.
M->getBasicBlockList().erase(BB);
return true;
}
}
+ } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(BB->getTerminator())) {
+ // Eliminate redundant destinations.
+ SmallPtrSet<Value *, 8> Succs;
+ for (unsigned i = 0, e = IBI->getNumDestinations(); i != e; ++i) {
+ BasicBlock *Dest = IBI->getDestination(i);
+ if (!Succs.insert(Dest)) {
+ Dest->removePredecessor(BB);
+ IBI->removeDestination(i);
+ --i; --e;
+ Changed = true;
+ }
+ }
+
+ if (IBI->getNumDestinations() == 0) {
+ // If the indirectbr has no successors, change it to unreachable.
+ new UnreachableInst(IBI->getContext(), IBI);
+ IBI->eraseFromParent();
+ Changed = true;
+ } else if (IBI->getNumDestinations() == 1) {
+ // If the indirectbr has one successor, change it to a direct branch.
+ BranchInst::Create(IBI->getDestination(0), IBI);
+ IBI->eraseFromParent();
+ Changed = true;
+ }
}
// Merge basic blocks into their predecessor if there is only one distinct
// is a conditional branch, see if we can hoist any code from this block up
// into our predecessor.
pred_iterator PI(pred_begin(BB)), PE(pred_end(BB));
- BasicBlock *OnlyPred = *PI++;
- for (; PI != PE; ++PI) // Search all predecessors, see if they are all same
- if (*PI != OnlyPred) {
+ BasicBlock *OnlyPred = 0;
+ for (; PI != PE; ++PI) { // Search all predecessors, see if they are all same
+ if (!OnlyPred)
+ OnlyPred = *PI;
+ else if (*PI != OnlyPred) {
OnlyPred = 0; // There are multiple different predecessors...
break;
}
+ }
if (OnlyPred)
if (BranchInst *BI = dyn_cast<BranchInst>(OnlyPred->getTerminator()))
/// eliminates unreachable basic blocks, and does other "peephole" optimization
/// of the CFG. It returns true if a modification was made.
///
-/// WARNING: The entry node of a function may not be simplified.
-///
bool llvm::SimplifyCFG(BasicBlock *BB, const TargetData *TD) {
return SimplifyCFGOpt(TD).run(BB);
}
--- /dev/null
+; RUN: opt -S -simplifycfg < %s | FileCheck %s
+
+; SimplifyCFG should eliminate redundant indirectbr edges.
+
+; CHECK: indbrtest0
+; CHECK: indirectbr i8* %t, [label %BB0, label %BB1, label %BB2]
+; CHECK: %x = phi i32 [ 0, %BB0 ], [ 1, %entry ]
+
+declare void @foo()
+declare void @A()
+declare void @B(i32)
+declare void @C()
+
+define void @indbrtest0(i8** %P, i8** %Q) {
+entry:
+ store i8* blockaddress(@indbrtest0, %BB0), i8** %P
+ store i8* blockaddress(@indbrtest0, %BB1), i8** %P
+ store i8* blockaddress(@indbrtest0, %BB2), i8** %P
+ call void @foo()
+ %t = load i8** %Q
+ indirectbr i8* %t, [label %BB0, label %BB1, label %BB2, label %BB0, label %BB1, label %BB2]
+BB0:
+ call void @A()
+ br label %BB1
+BB1:
+ %x = phi i32 [ 0, %BB0 ], [ 1, %entry ], [ 1, %entry ]
+ call void @B(i32 %x)
+ ret void
+BB2:
+ call void @C()
+ ret void
+}
+
+; SimplifyCFG should convert the indirectbr into a directbr. It would be even
+; better if it removed the branch altogether, but simplifycfdg currently misses
+; that because the predecessor is the entry block.
+
+; CHECK: indbrtest1
+; CHECK: br label %BB0
+
+define void @indbrtest1(i8** %P, i8** %Q) {
+entry:
+ store i8* blockaddress(@indbrtest1, %BB0), i8** %P
+ call void @foo()
+ %t = load i8** %Q
+ indirectbr i8* %t, [label %BB0, label %BB0]
+BB0:
+ call void @A()
+ ret void
+}
+