aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2011-10-05 14:17:01 +0000
committerDuncan Sands <baldrick@free.fr>2011-10-05 14:17:01 +0000
commit452c58f4c45249b5046f74a165430eedaab5f8f6 (patch)
treecb51cb8940c5f0ec4e951dfdb359842a059db3c6
parent4cbc5a1118507dc22bb8dc5ef7a6a4108e348f6b (diff)
downloadexternal_llvm-452c58f4c45249b5046f74a165430eedaab5f8f6.zip
external_llvm-452c58f4c45249b5046f74a165430eedaab5f8f6.tar.gz
external_llvm-452c58f4c45249b5046f74a165430eedaab5f8f6.tar.bz2
Generalize GVN's conditional propagation logic slightly:
it's OK for the false/true destination to have multiple predecessors as long as the extra ones are dominated by the branch destination. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141176 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/GVN.cpp33
-rw-r--r--test/Transforms/GVN/condprop.ll22
2 files changed, 50 insertions, 5 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index f0f16d8..0ad6a8f 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -1921,14 +1921,39 @@ bool GVN::processInstruction(Instruction *I) {
BasicBlock *TrueSucc = BI->getSuccessor(0);
BasicBlock *FalseSucc = BI->getSuccessor(1);
-
- if (TrueSucc->getSinglePredecessor())
+ BasicBlock *Parent = BI->getParent();
+
+ // If the true and false branches are to the same basic block then the
+ // branch gives no information about the condition. Eliminating this
+ // here simplifies the rest of the logic.
+ if (TrueSucc == FalseSucc)
+ return false;
+
+ // If the true block can be reached without executing the true edge then we
+ // can't say anything about the value of the condition there.
+ for (pred_iterator PI = pred_begin(TrueSucc), PE = pred_end(TrueSucc);
+ PI != PE; ++PI)
+ if (*PI != Parent && !DT->dominates(TrueSucc, *PI)) {
+ TrueSucc = 0;
+ break;
+ }
+
+ // If the false block can be reached without executing the false edge then
+ // we can't say anything about the value of the condition there.
+ for (pred_iterator PI = pred_begin(FalseSucc), PE = pred_end(FalseSucc);
+ PI != PE; ++PI)
+ if (*PI != Parent && !DT->dominates(FalseSucc, *PI)) {
+ FalseSucc = 0;
+ break;
+ }
+
+ if (TrueSucc)
addToLeaderTable(CondVN,
ConstantInt::getTrue(TrueSucc->getContext()),
TrueSucc);
- if (FalseSucc->getSinglePredecessor())
+ if (FalseSucc)
addToLeaderTable(CondVN,
- ConstantInt::getFalse(TrueSucc->getContext()),
+ ConstantInt::getFalse(FalseSucc->getContext()),
FalseSucc);
return false;
diff --git a/test/Transforms/GVN/condprop.ll b/test/Transforms/GVN/condprop.ll
index be6c349..b072856 100644
--- a/test/Transforms/GVN/condprop.ll
+++ b/test/Transforms/GVN/condprop.ll
@@ -52,4 +52,24 @@ bb8: ; preds = %bb7, %bb6, %bb4, %bb2, %bb
return: ; preds = %bb8
ret i32 %.0
-} \ No newline at end of file
+}
+
+declare void @ext(i1)
+
+; CHECK: @bar
+define void @bar(i1 %x, i1 %y) {
+ %z = or i1 %x, %y
+ br i1 %z, label %true, label %false
+true:
+; CHECK: true:
+ %z2 = or i1 %x, %y
+ call void @ext(i1 %z2)
+; CHECK: call void @ext(i1 true)
+ br label %true
+false:
+; CHECK: false:
+ %z3 = or i1 %x, %y
+ call void @ext(i1 %z3)
+; CHECK: call void @ext(i1 false)
+ br label %false
+}