aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-04-22 20:46:09 +0000
committerChris Lattner <sabre@nondot.org>2008-04-22 20:46:09 +0000
commitae65b3c7912138ec636b3bde5ff528d948161651 (patch)
tree20440be339629adae7e03390c4c3d7ec7acb8e78
parentd2368dc344bf46e2f5df3de1bff74ab0228d99a9 (diff)
downloadexternal_llvm-ae65b3c7912138ec636b3bde5ff528d948161651.zip
external_llvm-ae65b3c7912138ec636b3bde5ff528d948161651.tar.gz
external_llvm-ae65b3c7912138ec636b3bde5ff528d948161651.tar.bz2
Dig through multiple levels of AND to thread jumps if needed.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50106 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp36
-rw-r--r--test/Transforms/JumpThreading/and-and-cond.ll33
2 files changed, 55 insertions, 14 deletions
diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp
index 653a835..72c4acb 100644
--- a/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/lib/Transforms/Scalar/JumpThreading.cpp
@@ -60,7 +60,7 @@ namespace {
BasicBlock *FactorCommonPHIPreds(PHINode *PN, Constant *CstVal);
bool ProcessJumpOnPHI(PHINode *PN);
- bool ProcessJumpOnLogicalPHI(PHINode *PN, bool isAnd);
+ bool ProcessBranchOnLogical(Value *V, BasicBlock *BB, bool isAnd);
};
char JumpThreading::ID = 0;
RegisterPass<JumpThreading> X("jump-threading", "Jump Threading");
@@ -193,16 +193,10 @@ bool JumpThreading::ThreadBlock(BasicBlock *BB) {
if (BinaryOperator *CondI = dyn_cast<BinaryOperator>(Condition)) {
if ((CondI->getOpcode() == Instruction::And ||
CondI->getOpcode() == Instruction::Or) &&
- isa<BranchInst>(BB->getTerminator())) {
- if (PHINode *PN = dyn_cast<PHINode>(CondI->getOperand(0)))
- if (PN->getParent() == BB &&
- ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() == Instruction::And))
- return true;
- if (PHINode *PN = dyn_cast<PHINode>(CondI->getOperand(1)))
- if (PN->getParent() == BB &&
- ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() == Instruction::And))
- return true;
- }
+ isa<BranchInst>(BB->getTerminator()) &&
+ ProcessBranchOnLogical(CondI, BB,
+ CondI->getOpcode() == Instruction::And))
+ return true;
}
return false;
@@ -270,8 +264,23 @@ bool JumpThreading::ProcessJumpOnPHI(PHINode *PN) {
/// the predecessor corresponding to the 'false' will always jump to the false
/// destination of the branch.
///
-bool JumpThreading::ProcessJumpOnLogicalPHI(PHINode *PN, bool isAnd) {
-
+bool JumpThreading::ProcessBranchOnLogical(Value *V, BasicBlock *BB,
+ bool isAnd) {
+ // If this is a binary operator tree of the same AND/OR opcode, check the
+ // LHS/RHS.
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V))
+ if (isAnd && BO->getOpcode() == Instruction::And ||
+ !isAnd && BO->getOpcode() == Instruction::Or) {
+ if (ProcessBranchOnLogical(BO->getOperand(0), BB, isAnd))
+ return true;
+ if (ProcessBranchOnLogical(BO->getOperand(1), BB, isAnd))
+ return true;
+ }
+
+ // If this isn't a PHI node, we can't handle it.
+ PHINode *PN = dyn_cast<PHINode>(V);
+ if (!PN || PN->getParent() != BB) return false;
+
// We can only do the simplification for phi nodes of 'false' with AND or
// 'true' with OR. See if we have any entries in the phi for this.
unsigned PredNo = ~0U;
@@ -288,7 +297,6 @@ bool JumpThreading::ProcessJumpOnLogicalPHI(PHINode *PN, bool isAnd) {
return false;
// See if the cost of duplicating this block is low enough.
- BasicBlock *BB = PN->getParent();
unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB);
if (JumpThreadCost > Threshold) {
DOUT << " Not threading BB '" << BB->getNameStart()
diff --git a/test/Transforms/JumpThreading/and-and-cond.ll b/test/Transforms/JumpThreading/and-and-cond.ll
new file mode 100644
index 0000000..de4435c
--- /dev/null
+++ b/test/Transforms/JumpThreading/and-and-cond.ll
@@ -0,0 +1,33 @@
+; RUN: llvm-as < %s | opt -jump-threading -mem2reg -instcombine -simplifycfg | llvm-dis | grep {ret i32 %v1}
+; There should be no uncond branches left.
+; RUN: llvm-as < %s | opt -jump-threading -mem2reg -instcombine -simplifycfg | llvm-dis | not grep {br label}
+
+declare i32 @f1()
+declare i32 @f2()
+declare void @f3()
+
+define i32 @test(i1 %cond, i1 %cond2, i1 %cond3) {
+ br i1 %cond, label %T1, label %F1
+
+T1:
+ %v1 = call i32 @f1()
+ br label %Merge
+
+F1:
+ %v2 = call i32 @f2()
+ br label %Merge
+
+Merge:
+ %A = phi i1 [true, %T1], [false, %F1]
+ %B = phi i32 [%v1, %T1], [%v2, %F1]
+ %C = and i1 %A, %cond2
+ %D = and i1 %C, %cond3
+ br i1 %D, label %T2, label %F2
+
+T2:
+ call void @f3()
+ ret i32 %B
+
+F2:
+ ret i32 %B
+}