summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrits van Bommel <fvbommel@gmail.com>2011-05-22 16:24:18 +0000
committerFrits van Bommel <fvbommel@gmail.com>2011-05-22 16:24:18 +0000
commit5649ba70fb39f2fda4791d255ae8bb373071874f (patch)
tree304070a251ebb6a6f0d5369ca76818a110e3265f
parent8480aba5ec7438570cd090abcf3f6f52dd15352e (diff)
downloadllvm-5649ba70fb39f2fda4791d255ae8bb373071874f.tar.gz
llvm-5649ba70fb39f2fda4791d255ae8bb373071874f.tar.bz2
llvm-5649ba70fb39f2fda4791d255ae8bb373071874f.tar.xz
Add a parameter to ConstantFoldTerminator() that callers can use to ask it to also clean up the condition of any conditional terminator it folds to be unconditional, if that turns the condition into dead code. This just means it calls RecursivelyDeleteTriviallyDeadInstructions() in strategic spots. It defaults to the old behavior.
I also changed -simplifycfg, -jump-threading and -codegenprepare to use this to produce slightly better code without any extra cleanup passes (AFAICT this was the only place in -simplifycfg where now-dead conditions of replaced terminators weren't being cleaned up). The only other user of this function is -sccp, but I didn't read that thoroughly enough to figure out whether it might be holding pointers to instructions that could be deleted by this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131855 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Transforms/Utils/Local.h6
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp2
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp2
-rw-r--r--lib/Transforms/Scalar/SimplifyCFGPass.cpp2
-rw-r--r--lib/Transforms/Utils/Local.cpp24
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp2
-rw-r--r--test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll52
7 files changed, 78 insertions, 12 deletions
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index e61dcb347c..c9d2916821 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -43,8 +43,10 @@ template<typename T> class SmallVectorImpl;
/// constant value, convert it into an unconditional branch to the constant
/// destination. This is a nontrivial operation because the successors of this
/// basic block must have their PHI nodes updated.
-///
-bool ConstantFoldTerminator(BasicBlock *BB);
+/// Also calls RecursivelyDeleteTriviallyDeadInstructions() on any branch/switch
+/// conditions and indirectbr addresses this might make dead if
+/// DeleteDeadConditions is true.
+bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false);
//===----------------------------------------------------------------------===//
// Local dead code elimination.
diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp
index 0184390185..483bfe3655 100644
--- a/lib/Transforms/Scalar/CodeGenPrepare.cpp
+++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp
@@ -147,7 +147,7 @@ bool CodeGenPrepare::runOnFunction(Function &F) {
if (!DisableBranchOpts) {
MadeChange = false;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- MadeChange |= ConstantFoldTerminator(BB);
+ MadeChange |= ConstantFoldTerminator(BB, true);
if (MadeChange)
ModifiedDT = true;
diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp
index 5a8f4ca192..cf18ff040b 100644
--- a/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/lib/Transforms/Scalar/JumpThreading.cpp
@@ -706,7 +706,7 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) {
DEBUG(dbgs() << " In block '" << BB->getName()
<< "' folding terminator: " << *BB->getTerminator() << '\n');
++NumFolds;
- ConstantFoldTerminator(BB);
+ ConstantFoldTerminator(BB, true);
return true;
}
diff --git a/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/lib/Transforms/Scalar/SimplifyCFGPass.cpp
index 1137c2b23f..eccafea3aa 100644
--- a/lib/Transforms/Scalar/SimplifyCFGPass.cpp
+++ b/lib/Transforms/Scalar/SimplifyCFGPass.cpp
@@ -163,7 +163,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
Changed = true;
}
- Changed |= ConstantFoldTerminator(BB);
+ Changed |= ConstantFoldTerminator(BB, true);
for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
Worklist.push_back(*SI);
} while (!Worklist.empty());
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 12e15b07c7..f5a8adacd5 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -44,11 +44,14 @@ using namespace llvm;
// Local constant propagation.
//
-// ConstantFoldTerminator - If a terminator instruction is predicated on a
-// constant value, convert it into an unconditional branch to the constant
-// destination.
-//
-bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
+/// ConstantFoldTerminator - If a terminator instruction is predicated on a
+/// constant value, convert it into an unconditional branch to the constant
+/// destination. This is a nontrivial operation because the successors of this
+/// basic block must have their PHI nodes updated.
+/// Also calls RecursivelyDeleteTriviallyDeadInstructions() on any branch/switch
+/// conditions and indirectbr addresses this might make dead if
+/// DeleteDeadConditions is true.
+bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions) {
TerminatorInst *T = BB->getTerminator();
IRBuilder<> Builder(T);
@@ -89,7 +92,10 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
// Replace the conditional branch with an unconditional one.
Builder.CreateBr(Dest1);
+ Value *Cond = BI->getCondition();
BI->eraseFromParent();
+ if (DeleteDeadConditions)
+ RecursivelyDeleteTriviallyDeadInstructions(Cond);
return true;
}
return false;
@@ -152,7 +158,10 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
}
// Delete the old switch.
- BB->getInstList().erase(SI);
+ Value *Cond = SI->getCondition();
+ SI->eraseFromParent();
+ if (DeleteDeadConditions)
+ RecursivelyDeleteTriviallyDeadInstructions(Cond);
return true;
}
@@ -186,7 +195,10 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
else
IBI->getDestination(i)->removePredecessor(IBI->getParent());
}
+ Value *Address = IBI->getAddress();
IBI->eraseFromParent();
+ if (DeleteDeadConditions)
+ RecursivelyDeleteTriviallyDeadInstructions(Address);
// If we didn't find our destination in the IBI successor list, then we
// have undefined behavior. Replace the unconditional branch with an
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index 2c032d5d12..5ab9a2877c 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2651,7 +2651,7 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
// Check to see if we can constant propagate this terminator instruction
// away...
- Changed |= ConstantFoldTerminator(BB);
+ Changed |= ConstantFoldTerminator(BB, true);
// Check for and eliminate duplicate PHI nodes in this block.
Changed |= EliminateDuplicatePHINodes(BB);
diff --git a/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll b/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll
new file mode 100644
index 0000000000..3996efd82b
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/dce-cond-after-folding-terminator.ll
@@ -0,0 +1,52 @@
+; RUN: opt -S <%s -simplifycfg | FileCheck %s
+
+define void @test_br(i32 %x) {
+entry:
+; CHECK: @test_br
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void
+ %cmp = icmp eq i32 %x, 10
+ br i1 %cmp, label %if.then, label %if.then
+
+if.then: ; preds = %entry
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ ret void
+}
+
+define void @test_switch(i32 %x) nounwind {
+entry:
+; CHECK: @test_switch
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void
+ %rem = srem i32 %x, 3
+ switch i32 %rem, label %sw.bb [
+ i32 1, label %sw.bb
+ i32 10, label %sw.bb
+ ]
+
+sw.bb: ; preds = %sw.default, %entry, %entry
+ br label %sw.epilog
+
+sw.epilog: ; preds = %sw.bb
+ ret void
+}
+
+define void @test_indirectbr(i32 %x) {
+entry:
+; CHECK: @test_indirectbr
+; CHECK-NEXT: entry:
+; Ideally this should now check:
+; CHK-NEXT: ret void
+; But that doesn't happen yet. Instead:
+; CHECK-NEXT: br label %L1
+
+ %label = bitcast i8* blockaddress(@test_indirectbr, %L1) to i8*
+ indirectbr i8* %label, [label %L1, label %L2]
+
+L1: ; preds = %entry
+ ret void
+L2: ; preds = %entry
+ ret void
+}