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
This commit is contained in:
Chris Lattner 2008-04-22 20:46:09 +00:00
parent d2368dc344
commit ae65b3c791
2 changed files with 55 additions and 14 deletions

View File

@ -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()

View File

@ -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
}