Index: lib/Transforms/Scalar/CallSiteSplitting.cpp =================================================================== --- lib/Transforms/Scalar/CallSiteSplitting.cpp +++ lib/Transforms/Scalar/CallSiteSplitting.cpp @@ -348,9 +348,30 @@ return true; } +static bool tryToUseConstrainedArgument(CallSite CS, BasicBlock *SinglePred) { + SmallVector, 2> Cmps; + recordConditions(CS, SinglePred, Cmps); + if (Instruction *NewCI = addConditions(CS, Cmps)) { + Instruction *Instr = CS.getInstruction(); + NewCI->insertBefore(Instr); + Instr->replaceAllUsesWith(NewCI); + Instr->eraseFromParent(); + return true; + } + return false; +} + static bool tryToSplitCallSite(CallSite CS) { - if (!CS.arg_size() || !canSplitCallSite(CS)) + if (!CS.arg_size()) return false; + + if (BasicBlock *SinglePred = + CS.getInstruction()->getParent()->getSinglePredecessor()) + return tryToUseConstrainedArgument(CS, SinglePred); + + if (!canSplitCallSite(CS)) + return false; + return tryToSplitOnPredicatedArgument(CS) || tryToSplitOnPHIPredicatedArgument(CS); } Index: test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll =================================================================== --- test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll +++ test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll @@ -134,6 +134,51 @@ ret i32 %v } +; CHECK-LABEL: @test_single_pred +; CHECK-LABEL: Tail: +; CHECK: %[[CALL:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p) +; CHECK: ret i32 %[[CALL]] +define i32 @test_single_pred(i1 %c, i32* %a, i32 %v, i32 %p) { +Header: + br i1 %c, label %TBB, label %End + +TBB: + %cmp = icmp ne i32* %a, null + br i1 %cmp, label %Tail, label %End + +Tail: + %r = call i32 @callee(i32* %a, i32 %v, i32 %p) + ret i32 %r + +End: + ret i32 %v +} + +; CHECK-LABEL: @test_single_pred_pred +; CHECK-LABEL: Tail: +; CHECK: %[[CALL:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 %p) +; CHECK: ret i32 %[[CALL]] +define i32 @test_single_pred_pred(i1 %c, i32* %a, i32 %v, i32 %p) { +Header: + br i1 %c, label %TBB, label %End + +TBB: + %cmp = icmp ne i32* %a, null + br i1 %cmp, label %TBB2, label %End + +TBB2: + %cmp2 = icmp eq i32 %v, 1 + br i1 %cmp2, label %Tail, label %End + +Tail: + %r = call i32 @callee(i32* %a, i32 %v, i32 %p) + ret i32 %r + +End: + ret i32 %v +} + + define i32 @callee(i32* %a, i32 %v, i32 %p) { ret i32 10 }