Index: include/llvm/Transforms/Scalar/JumpThreading.h =================================================================== --- include/llvm/Transforms/Scalar/JumpThreading.h +++ include/llvm/Transforms/Scalar/JumpThreading.h @@ -109,8 +109,8 @@ bool ProcessBlock(BasicBlock *BB); bool ThreadEdge(BasicBlock *BB, const SmallVectorImpl &PredBBs, BasicBlock *SuccBB); - bool DuplicateCondBranchOnPHIIntoPred( - BasicBlock *BB, const SmallVectorImpl &PredBBs); + bool DuplicateBBIntoPreds(BasicBlock *BB, + const SmallVectorImpl &PredBBs); bool ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB, Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -882,6 +882,37 @@ if (ProcessImpliedCondition(BB)) return true; + // If this is an otherwise-unthreadable conditional branch on a compare, + // duplicate this into its predecessor under the following condition: the + // branch condition in a *successor to BB* can be inferred as a constant + // after the duplication. + if (CmpInst *Cmp = dyn_cast(CondInst)) { + if (Cmp->getParent() != BB || !isa(BB->getTerminator())) + return false; + for (auto *Succ : successors(BB)) { + if (Succ->getSinglePredecessor() != BB) + continue; + if (!isa(Succ->getTerminator())) + continue; + BranchInst *SuccBranch = cast(Succ->getTerminator()); + if (!SuccBranch->isConditional()) + continue; + Value *SuccCond = SuccBranch->getCondition(); + if (!isa(SuccCond) || + cast(SuccCond)->getParent() == Succ || + cast(SuccCond)->getParent() == BB) + continue; + for (auto *Pred : predecessors(BB)) { + BranchInst *PredBr; + if ((PredBr = dyn_cast(Pred->getTerminator())) && + PredBr->isUnconditional() && + LVI->getConstantOnEdge(SuccCond, Pred, BB) && + DuplicateBBIntoPreds(BB, SmallVector({Pred}))) + return true; + } + } + } + return false; } @@ -1305,7 +1336,7 @@ if (PredBr->isUnconditional()) { PredBBs[0] = PredBB; // Try to duplicate BB into PredBB. - if (DuplicateCondBranchOnPHIIntoPred(BB, PredBBs)) + if (DuplicateBBIntoPreds(BB, PredBBs)) return true; } } @@ -1414,7 +1445,7 @@ } // Try to duplicate BB into PredBB. - return DuplicateCondBranchOnPHIIntoPred(BB, BlocksToFoldInto); + return DuplicateBBIntoPreds(BB, BlocksToFoldInto); } @@ -1682,12 +1713,10 @@ } } -/// DuplicateCondBranchOnPHIIntoPred - PredBB contains an unconditional branch -/// to BB which contains an i1 PHI node and a conditional branch on that PHI. -/// If we can duplicate the contents of BB up into PredBB do so now, this -/// improves the odds that the branch will be on an analyzable instruction like -/// a compare. -bool JumpThreadingPass::DuplicateCondBranchOnPHIIntoPred( +/// DuplicateBBIntoPreds - PredBBs is a list of blocks that contain an +/// unconditional branch to BB. Duplicate the contents of BB into Preds if the +/// duplication cost is within the threshold. +bool JumpThreadingPass::DuplicateBBIntoPreds( BasicBlock *BB, const SmallVectorImpl &PredBBs) { assert(!PredBBs.empty() && "Can't handle an empty set"); @@ -1721,8 +1750,8 @@ // Okay, we decided to do this! Clone all the instructions in BB onto the end // of PredBB. DEBUG(dbgs() << " Duplicating block '" << BB->getName() << "' into end of '" - << PredBB->getName() << "' to eliminate branch on phi. Cost: " - << DuplicationCost << " block is:" << *BB << "\n"); + << PredBB->getName() << "'. Cost: " << DuplicationCost + << " block is:" << *BB << "\n"); // Unless PredBB ends with an unconditional branch, split the edge so that we // can just clone the bits from BB into the end of the new PredBB. Index: test/Transforms/JumpThreading/basic.ll =================================================================== --- test/Transforms/JumpThreading/basic.ll +++ test/Transforms/JumpThreading/basic.ll @@ -3,6 +3,7 @@ declare i32 @f1() declare i32 @f2() declare void @f3() +declare void @f4() define i32 @test1(i1 %cond) { ; CHECK-LABEL: @test1( @@ -176,6 +177,44 @@ } +;; Clone a block if any of its successor ends with a conditional branch whose +;; condition is known at a predecessor. + + +define i32 @test6a(i32 %A, i32 %B) { +; CHECK-LABEL: @test6a( + %tmp455 = icmp eq i32 %A, 42 + br i1 %tmp455, label %BB5, label %BB2 + +BB2: + call i32 @f1() + br label %BB11 + +BB5: +; One of BB11's successor is BB1 which ends with a conditional branch. The +; condition used is %tmp455 whose value is known here. So BB11 is cloned here. +; CHECK: call void @f4() +; CHECK-NEXT: icmp eq i32 %B + call void @f4() + br label %BB11 + +BB11: + %tmp5 = icmp eq i32 %B, 42 + br i1 %tmp5, label %BB1, label %BB3 + +BB1: + call i32 @f2() + br i1 %tmp455, label %BB3, label %BB4 + +BB3: + ret i32 3 + +BB4: + call void @f3() + ret i32 4 +} + + ;; This tests that the branch in 'merge' can be cloned up into T1. ;; rdar://7367025 define i32 @test7(i1 %cond, i1 %cond2) {