From ae65b3c7912138ec636b3bde5ff528d948161651 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 22 Apr 2008 20:46:09 +0000 Subject: [PATCH] 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 --- lib/Transforms/Scalar/JumpThreading.cpp | 36 +++++++++++-------- test/Transforms/JumpThreading/and-and-cond.ll | 33 +++++++++++++++++ 2 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 test/Transforms/JumpThreading/and-and-cond.ll diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 653a83563d2..72c4acbaa5f 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 X("jump-threading", "Jump Threading"); @@ -193,16 +193,10 @@ bool JumpThreading::ThreadBlock(BasicBlock *BB) { if (BinaryOperator *CondI = dyn_cast(Condition)) { if ((CondI->getOpcode() == Instruction::And || CondI->getOpcode() == Instruction::Or) && - isa(BB->getTerminator())) { - if (PHINode *PN = dyn_cast(CondI->getOperand(0))) - if (PN->getParent() == BB && - ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() == Instruction::And)) - return true; - if (PHINode *PN = dyn_cast(CondI->getOperand(1))) - if (PN->getParent() == BB && - ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() == Instruction::And)) - return true; - } + isa(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(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(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 00000000000..de4435c5079 --- /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 +}