[llvm] r325126 - Recommit r325001: [CallSiteSplitting] Support splitting of blocks with instrs before call.

Mikael Holmén via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 19 00:28:21 PST 2018


Hi Florian,

I ran into a failed assertion with this commit:

opt -S -o - foo.ll -callsite-splitting

gives

opt: ../include/llvm/ADT/ilist_iterator.h:140: reference 
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, 
true, false, void>, false, false>::operator*() const [OptionsT = 
llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, 
IsReverse = false, IsConst = false]: Assertion 
`!NodePtr->isKnownSentinel()' failed.
#0 0x0000000001ec20d4 PrintStackTraceSignalHandler(void*) 
(build-all/bin/opt+0x1ec20d4)
#1 0x0000000001ec2846 SignalHandler(int) (build-all/bin/opt+0x1ec2846)
#2 0x00007fb6628a8810 __restore_rt (/lib64/libpthread.so.0+0xf810)
#3 0x00007fb661a53875 __GI_raise (/lib64/libc.so.6+0x32875)
#4 0x00007fb661a54e51 __GI_abort (/lib64/libc.so.6+0x33e51)
#5 0x00007fb661a4c740 __GI___assert_fail (/lib64/libc.so.6+0x2b740)
#6 0x0000000001eee3ba 
llvm::DuplicateInstructionsInSplitBetween(llvm::BasicBlock*, 
llvm::BasicBlock*, llvm::Instruction*, llvm::ValueMap<llvm::Value 
const*, llvm::WeakTrackingVH, llvm::ValueMapConfig<llvm::Value const*, 
llvm::sys::SmartMutex<false> > >&) (build-all/bin/opt+0x1eee3ba)
#7 0x0000000001c5f31d splitCallSite(llvm::CallSite, 
llvm::SmallVectorImpl<std::pair<llvm::BasicBlock*, 
llvm::SmallVector<std::pair<llvm::ICmpInst*, unsigned int>, 2u> > > 
const&) (build-all/bin/opt+0x1c5f31d)
#8 0x0000000001c5e993 doCallSiteSplitting(llvm::Function&, 
llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&) 
(build-all/bin/opt+0x1c5e993)
#9 0x0000000001c6068f (anonymous 
namespace)::CallSiteSplittingLegacyPass::runOnFunction(llvm::Function&) 
(build-all/bin/opt+0x1c6068f)
#10 0x000000000197e648 
llvm::FPPassManager::runOnFunction(llvm::Function&) 
(build-all/bin/opt+0x197e648)
#11 0x000000000197e888 llvm::FPPassManager::runOnModule(llvm::Module&) 
(build-all/bin/opt+0x197e888)
#12 0x000000000197ed68 llvm::legacy::PassManagerImpl::run(llvm::Module&) 
(build-all/bin/opt+0x197ed68)
#13 0x000000000072a7f3 main (build-all/bin/opt+0x72a7f3)
#14 0x00007fb661a3fc36 __libc_start_main (/lib64/libc.so.6+0x1ec36)
#15 0x00000000007150dd _start 
/usr/src/packages/BUILD/glibc-2.11.3/csu/../sysdeps/x86_64/elf/start.S:116:0
Stack dump:
0.      Program arguments: build-all/bin/opt -S -o - foo.ll 
-callsite-splitting
1.      Running pass 'Function Pass Manager' on module 'foo.ll'.
2.      Running pass 'Call-site splitting' on function '@main'
Abort

Regards,
Mikael

On 02/14/2018 02:59 PM, Florian Hahn via llvm-commits wrote:
> Author: fhahn
> Date: Wed Feb 14 05:59:12 2018
> New Revision: 325126
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=325126&view=rev
> Log:
> Recommit r325001: [CallSiteSplitting] Support splitting of blocks with instrs before call.
> 
> For basic blocks with instructions between the beginning of the block
> and a call we have to duplicate the instructions before the call in all
> split blocks and add PHI nodes for uses of the duplicated instructions
> after the call.
> 
> Currently, the threshold for the number of instructions before a call
> is quite low, to keep the impact on binary size low.
> 
> Reviewers: junbuml, mcrosier, davidxl, davide
> 
> Reviewed By: junbuml
> 
> Differential Revision: https://reviews.llvm.org/D41860
> 
> Added:
>      llvm/trunk/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
> Modified:
>      llvm/trunk/lib/Transforms/Scalar/CallSiteSplitting.cpp
>      llvm/trunk/test/Other/new-pm-lto-defaults.ll
>      llvm/trunk/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll
>      llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
>      llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll
>      llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split.ll
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/CallSiteSplitting.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CallSiteSplitting.cpp?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/CallSiteSplitting.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/CallSiteSplitting.cpp Wed Feb 14 05:59:12 2018
> @@ -59,11 +59,13 @@
>   #include "llvm/Transforms/Scalar/CallSiteSplitting.h"
>   #include "llvm/ADT/Statistic.h"
>   #include "llvm/Analysis/TargetLibraryInfo.h"
> +#include "llvm/Analysis/TargetTransformInfo.h"
>   #include "llvm/IR/IntrinsicInst.h"
>   #include "llvm/IR/PatternMatch.h"
>   #include "llvm/Support/Debug.h"
>   #include "llvm/Transforms/Scalar.h"
>   #include "llvm/Transforms/Utils/BasicBlockUtils.h"
> +#include "llvm/Transforms/Utils/Cloning.h"
>   #include "llvm/Transforms/Utils/Local.h"
>   
>   using namespace llvm;
> @@ -73,6 +75,15 @@ using namespace PatternMatch;
>   
>   STATISTIC(NumCallSiteSplit, "Number of call-site split");
>   
> +/// Only allow instructions before a call, if their CodeSize cost is below
> +/// DuplicationThreshold. Those instructions need to be duplicated in all
> +/// split blocks.
> +static cl::opt<unsigned>
> +    DuplicationThreshold("callsite-splitting-duplication-threshold", cl::Hidden,
> +                         cl::desc("Only allow instructions before a call, if "
> +                                  "their cost is below DuplicationThreshold"),
> +                         cl::init(5));
> +
>   static void addNonNullAttribute(CallSite CS, Value *Op) {
>     unsigned ArgNo = 0;
>     for (auto &I : CS.args()) {
> @@ -168,20 +179,26 @@ static SmallVector<BasicBlock *, 2> getT
>     return Preds;
>   }
>   
> -static bool canSplitCallSite(CallSite CS) {
> +static bool canSplitCallSite(CallSite CS, TargetTransformInfo &TTI) {
>     // FIXME: As of now we handle only CallInst. InvokeInst could be handled
>     // without too much effort.
>     Instruction *Instr = CS.getInstruction();
>     if (!isa<CallInst>(Instr))
>       return false;
>   
> -  // Allow splitting a call-site only when there is no instruction before the
> -  // call-site in the basic block. Based on this constraint, we only clone the
> -  // call instruction, and we do not move a call-site across any other
> -  // instruction.
>     BasicBlock *CallSiteBB = Instr->getParent();
> -  if (Instr != CallSiteBB->getFirstNonPHIOrDbg())
> -    return false;
> +  // Allow splitting a call-site only when the CodeSize cost of the
> +  // instructions before the call is less then DuplicationThreshold. The
> +  // instructions before the call will be duplicated in the split blocks and
> +  // corresponding uses will be updated.
> +  unsigned Cost = 0;
> +  for (auto &InstBeforeCall :
> +       llvm::make_range(CallSiteBB->begin(), Instr->getIterator())) {
> +    Cost += TTI.getInstructionCost(&InstBeforeCall,
> +                                   TargetTransformInfo::TCK_CodeSize);
> +    if (Cost >= DuplicationThreshold)
> +      return false;
> +  }
>   
>     // Need 2 predecessors and cannot split an edge from an IndirectBrInst.
>     SmallVector<BasicBlock *, 2> Preds(predecessors(CallSiteBB));
> @@ -246,16 +263,21 @@ static void splitCallSite(
>       CallPN = PHINode::Create(Instr->getType(), Preds.size(), "phi.call");
>   
>     DEBUG(dbgs() << "split call-site : " << *Instr << " into \n");
> -  for (const auto &P : Preds) {
> -    BasicBlock *PredBB = P.first;
> -    BasicBlock *SplitBlock =
> -        SplitBlockPredecessors(TailBB, PredBB, ".predBB.split");
> +
> +  assert(Preds.size() == 2 && "The ValueToValueMaps array has size 2.");
> +  // ValueToValueMapTy is neither copy nor moveable, so we use a simple array
> +  // here.
> +  ValueToValueMapTy ValueToValueMaps[2];
> +  for (unsigned i = 0; i < Preds.size(); i++) {
> +    BasicBlock *PredBB = Preds[i].first;
> +    BasicBlock *SplitBlock = DuplicateInstructionsInSplitBetween(
> +        TailBB, PredBB, &*std::next(Instr->getIterator()), ValueToValueMaps[i]);
>       assert(SplitBlock && "Unexpected new basic block split.");
>   
> -    Instruction *NewCI = Instr->clone();
> +    Instruction *NewCI =
> +        &*std::prev(SplitBlock->getTerminator()->getIterator());
>       CallSite NewCS(NewCI);
> -    addConditions(NewCS, P.second);
> -    NewCI->insertBefore(&*SplitBlock->getFirstInsertionPt());
> +    addConditions(NewCS, Preds[i].second);
>   
>       // Handle PHIs used as arguments in the call-site.
>       for (PHINode &PN : TailBB->phis()) {
> @@ -273,13 +295,41 @@ static void splitCallSite(
>         CallPN->addIncoming(NewCI, SplitBlock);
>     }
>   
> +  auto *OriginalBegin = &*TailBB->begin();
>     // Replace users of the original call with a PHI mering call-sites split.
>     if (CallPN) {
> -    CallPN->insertBefore(TailBB->getFirstNonPHI());
> +    CallPN->insertBefore(OriginalBegin);
>       Instr->replaceAllUsesWith(CallPN);
>     }
>   
> -  Instr->eraseFromParent();
> +  // Remove instructions moved to split blocks from TailBB, from the duplicated
> +  // call instruction to the beginning of the basic block. If an instruction
> +  // has any uses, add a new PHI node to combine the values coming from the
> +  // split blocks. The new PHI nodes are placed before the first original
> +  // instruction, so we do not end up deleting them. By using reverse-order, we
> +  // do not introduce unnecessary PHI nodes for def-use chains from the call
> +  // instruction to the beginning of the block.
> +  auto I = Instr->getReverseIterator();
> +  while (I != TailBB->rend()) {
> +    Instruction *CurrentI = &*I++;
> +    if (!CurrentI->use_empty()) {
> +      // If an existing PHI has users after the call, there is no need to create
> +      // a new one.
> +      if (isa<PHINode>(CurrentI))
> +        continue;
> +      PHINode *NewPN = PHINode::Create(CurrentI->getType(), Preds.size());
> +      for (auto &Mapping : ValueToValueMaps)
> +        NewPN->addIncoming(Mapping[CurrentI],
> +                           cast<Instruction>(Mapping[CurrentI])->getParent());
> +      NewPN->insertBefore(&*TailBB->begin());
> +      CurrentI->replaceAllUsesWith(NewPN);
> +    }
> +    CurrentI->eraseFromParent();
> +    // We are done once we handled the first original instruction in TailBB.
> +    if (CurrentI == OriginalBegin)
> +      break;
> +  }
> +
>     NumCallSiteSplit++;
>   }
>   
> @@ -344,14 +394,15 @@ static bool tryToSplitOnPredicatedArgume
>     return true;
>   }
>   
> -static bool tryToSplitCallSite(CallSite CS) {
> -  if (!CS.arg_size() || !canSplitCallSite(CS))
> +static bool tryToSplitCallSite(CallSite CS, TargetTransformInfo &TTI) {
> +  if (!CS.arg_size() || !canSplitCallSite(CS, TTI))
>       return false;
>     return tryToSplitOnPredicatedArgument(CS) ||
>            tryToSplitOnPHIPredicatedArgument(CS);
>   }
>   
> -static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI) {
> +static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI,
> +                                TargetTransformInfo &TTI) {
>     bool Changed = false;
>     for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;) {
>       BasicBlock &BB = *BI++;
> @@ -364,7 +415,7 @@ static bool doCallSiteSplitting(Function
>         Function *Callee = CS.getCalledFunction();
>         if (!Callee || Callee->isDeclaration())
>           continue;
> -      Changed |= tryToSplitCallSite(CS);
> +      Changed |= tryToSplitCallSite(CS, TTI);
>       }
>     }
>     return Changed;
> @@ -379,6 +430,7 @@ struct CallSiteSplittingLegacyPass : pub
>   
>     void getAnalysisUsage(AnalysisUsage &AU) const override {
>       AU.addRequired<TargetLibraryInfoWrapperPass>();
> +    AU.addRequired<TargetTransformInfoWrapperPass>();
>       FunctionPass::getAnalysisUsage(AU);
>     }
>   
> @@ -387,7 +439,8 @@ struct CallSiteSplittingLegacyPass : pub
>         return false;
>   
>       auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
> -    return doCallSiteSplitting(F, TLI);
> +    auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
> +    return doCallSiteSplitting(F, TLI, TTI);
>     }
>   };
>   } // namespace
> @@ -396,6 +449,7 @@ char CallSiteSplittingLegacyPass::ID = 0
>   INITIALIZE_PASS_BEGIN(CallSiteSplittingLegacyPass, "callsite-splitting",
>                         "Call-site splitting", false, false)
>   INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
>   INITIALIZE_PASS_END(CallSiteSplittingLegacyPass, "callsite-splitting",
>                       "Call-site splitting", false, false)
>   FunctionPass *llvm::createCallSiteSplittingPass() {
> @@ -405,8 +459,9 @@ FunctionPass *llvm::createCallSiteSplitt
>   PreservedAnalyses CallSiteSplittingPass::run(Function &F,
>                                                FunctionAnalysisManager &AM) {
>     auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
> +  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
>   
> -  if (!doCallSiteSplitting(F, TLI))
> +  if (!doCallSiteSplitting(F, TLI, TTI))
>       return PreservedAnalyses::all();
>     PreservedAnalyses PA;
>     return PA;
> 
> Modified: llvm/trunk/test/Other/new-pm-lto-defaults.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-lto-defaults.ll?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/test/Other/new-pm-lto-defaults.ll (original)
> +++ llvm/trunk/test/Other/new-pm-lto-defaults.ll Wed Feb 14 05:59:12 2018
> @@ -35,6 +35,7 @@
>   ; CHECK-O2-NEXT: Starting llvm::Function pass manager run.
>   ; CHECK-O2-NEXT: Running pass: CallSiteSplittingPass on foo
>   ; CHECK-O2-NEXT: Running analysis: TargetLibraryAnalysis on foo
> +; CHECK-O2-NEXT: Running analysis: TargetIRAnalysis on foo
>   ; CHECK-O2-NEXT: Finished llvm::Function pass manager run.
>   ; CHECK-O2-NEXT: PGOIndirectCallPromotion
>   ; CHECK-O2-NEXT: Running analysis: ProfileSummaryAnalysis
> @@ -79,7 +80,6 @@
>   ; CHECK-O2-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}PostOrderFunctionAttrsPass>
>   ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
>   ; CHECK-O2-NEXT: Running analysis: MemoryDependenceAnalysis
> -; CHECK-O2-NEXT: Running analysis: TargetIRAnalysis on foo
>   ; CHECK-O2-NEXT: Running analysis: DemandedBitsAnalysis
>   ; CHECK-O2-NEXT: Running pass: CrossDSOCFIPass
>   ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}SimplifyCFGPass>
> 
> Added: llvm/trunk/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll?rev=325126&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll (added)
> +++ llvm/trunk/test/Transforms/CallSiteSplitting/callsite-instructions-before-call.ll Wed Feb 14 05:59:12 2018
> @@ -0,0 +1,253 @@
> +; RUN: opt -S -callsite-splitting < %s | FileCheck --check-prefix=CHECK %s
> +; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=0 < %s | FileCheck --check-prefix=NODUP %s
> +
> +; Instructions before a call that will be pushed to its predecessors
> +; with uses after the callsite, must be patched up as PHI nodes in
> +; the join block.
> +define i32* @test_split_branch_phi(i32* %ptrarg, i32 %i) {
> +Header:
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:                                    ; preds = %Header
> +  %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
> +  %0 = load i32, i32* %arrayidx, align 4
> +  %tobool1 = icmp ne i32 %0, 0
> +  br i1 %tobool1, label %CallSite, label %End
> +
> +CallSite:                                          ; preds = %TBB, %Header
> +  %somepointer = getelementptr i32, i32* %ptrarg, i64 18
> +  call void @bar(i32* %ptrarg, i32 %i)
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  %somepointerphi = phi i32* [ %somepointer, %CallSite ], [ null, %TBB ]
> +  ret i32* %somepointerphi
> +}
> +; NODUP-LABEL: test_split_branch_phi
> +; NODUP-NOT: split
> +; CHECK-LABEL: Header.split
> +; CHECK: %[[V1:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18
> +; CHECK: call void @bar(i32* null, i32 %i)
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: TBB.split:
> +; CHECK: %[[V2:somepointer[0-9]+]] = getelementptr i32, i32* %ptrarg, i64 18
> +; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i)
> +; CHECK: br label %CallSite
> +; CHECK: CallSite:
> +; CHECK: phi i32* [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]
> +
> +
> +define void @split_branch_no_extra_phi(i32* %ptrarg, i32 %i) {
> +Header:
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:                                    ; preds = %Header
> +  %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
> +  %0 = load i32, i32* %arrayidx, align 4
> +  %tobool1 = icmp ne i32 %0, 0
> +  br i1 %tobool1, label %CallSite, label %End
> +
> +CallSite:                                          ; preds = %TBB, %Header
> +  %i.add = add i32 %i, 99
> +  call void @bar(i32* %ptrarg, i32 %i.add)
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  ret void
> +}
> +; NODUP-LABEL: split_branch_no_extra_phi
> +; NODUP-NOT: split
> +; CHECK-LABEL: split_branch_no_extra_phi
> +; CHECK-LABEL: Header.split
> +; CHECK: %[[V1:.+]] = add i32 %i, 99
> +; CHECK: call void @bar(i32* null, i32 %[[V1]])
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: TBB.split:
> +; CHECK: %[[V2:.+]] = add i32 %i, 99
> +; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %[[V2]])
> +; CHECK: br label %CallSite
> +; CHECK: CallSite:
> +; CHECK-NOT: phi
> +
> +
> +; In this test case, the codesize cost of the instructions before the call to
> +; bar() is equal to the default DuplicationThreshold of 5, because calls are
> +; more expensive.
> +define void @test_no_split_threshold(i32* %ptrarg, i32 %i) {
> +Header:
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:                                    ; preds = %Header
> +  %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
> +  %0 = load i32, i32* %arrayidx, align 4
> +  %tobool1 = icmp ne i32 %0, 0
> +  br i1 %tobool1, label %CallSite, label %End
> +
> +CallSite:                                          ; preds = %TBB, %Header
> +  %i2 = add i32 %i, 10
> +  call void @bari(i32 %i2)
> +  call void @bari(i32 %i2)
> +  call void @bar(i32* %ptrarg, i32 %i2)
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  ret void
> +}
> +; NODUP-LABEL: test_no_split_threshold
> +; NODUP-NOT: split
> +; CHECK-LABEL: test_no_split_threshold
> +; CHECK-NOT: split
> +; CHECK-LABEL: CallSite:
> +; CHECK: call void @bar(i32* %ptrarg, i32 %i2)
> +
> +; In this test case, the phi node %l in CallSite should be removed, as after
> +; moving the call to the split blocks we can use the values directly.
> +define void @test_remove_unused_phi(i32* %ptrarg, i32 %i) {
> +Header:
> +  %l1 = load i32, i32* undef, align 16
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:                                    ; preds = %Header
> +  %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
> +  %0 = load i32, i32* %arrayidx, align 4
> +  %l2 = load i32, i32* undef, align 16
> +  %tobool1 = icmp ne i32 %0, 0
> +  br i1 %tobool1, label %CallSite, label %End
> +
> +CallSite:                                          ; preds = %TBB, %Header
> +  %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]
> +  call void @bar(i32* %ptrarg, i32 %l)
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  ret void
> +}
> +; NODUP-LABEL: test_remove_unused_phi
> +; NODUP-NOT: split
> +; CHECK-LABEL: test_remove_unused_phi
> +; CHECK-LABEL: Header.split
> +; CHECK: call void @bar(i32* null, i32 %l1)
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: TBB.split:
> +; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2)
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: CallSite:
> +; CHECK-NOT: phi
> +
> +; In this test case, we need to insert a new PHI node in TailBB to combine
> +; the loads we moved to the predecessors.
> +define void @test_add_new_phi(i32* %ptrarg, i32 %i) {
> +Header:
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:
> +  br i1 undef, label %CallSite, label %End
> +
> +CallSite:
> +  %arrayidx112 = getelementptr inbounds i32, i32* undef, i64 1
> +  %0 = load i32, i32* %arrayidx112, align 4
> +  call void @bar(i32* %ptrarg, i32 %i)
> +  %sub = sub nsw i32 %0, undef
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  ret void
> +}
> +; NODUP-LABEL: test_add_new_phi
> +; NODUP-NOT: split
> +; CHECK-LABEL: test_add_new_phi
> +; CHECK-LABEL: Header.split
> +; CHECK: %[[V1:.+]] = load i32, i32*
> +; CHECK: call void @bar(i32* null, i32 %i)
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: TBB.split:
> +; CHECK: %[[V2:.+]] = load i32, i32*
> +; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %i)
> +; CHECK: br label %CallSite
> +; CHECK-LABEL: CallSite:
> +; CHECK-NEXT: %[[V3:.+]] = phi i32 [ %[[V1]], %Header.split ], [ %[[V2]], %TBB.split ]
> +; CHECK: %sub = sub nsw i32 %[[V3]], undef
> +
> +define i32 @test_firstnophi(i32* %a, i32 %v) {
> +Header:
> +  %tobool1 = icmp eq i32* %a, null
> +  br i1 %tobool1, label %Tail, label %TBB
> +
> +TBB:
> +  %cmp = icmp eq i32 %v, 1
> +  br i1 %cmp, label %Tail, label %End
> +
> +Tail:
> +  %p = phi i32[1,%Header], [2, %TBB]
> +  store i32 %v, i32* %a
> +  %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
> +  ret i32 %r
> +
> +End:
> +  ret i32 %v
> +}
> +; NODUP-LABEL: @test_firstnophi
> +; NODUP-NOT: split:
> +; CHECK-LABEL: @test_firstnophi
> +; CHECK-LABEL: Header.split:
> +; CHECK-NEXT: store i32 %v, i32* %a
> +; CHECK-NEXT: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
> +; CHECK-NEXT: br label %Tail
> +; CHECK-LABEL: TBB.split:
> +; CHECK-NEXT: store i32 %v, i32* %a
> +; CHECK-NEXT: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
> +; CHECK-NEXT br label %Tail
> +; CHECK-LABEL: Tail:
> +; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
> +; CHECK: ret i32 %[[MERGED]]
> +define i32 @callee(i32* %a, i32 %v, i32 %p) {
> +    ret i32 0
> +}
> +
> +define void @test_no_remove_used_phi(i32* %ptrarg, i32 %i) {
> +Header:
> +  %l1 = load i32, i32* undef, align 16
> +  %tobool = icmp ne i32* %ptrarg, null
> +  br i1 %tobool, label %TBB, label %CallSite
> +
> +TBB:                                    ; preds = %Header
> +  %arrayidx = getelementptr inbounds i32, i32* %ptrarg, i64 42
> +  %0 = load i32, i32* %arrayidx, align 4
> +  %l2 = load i32, i32* undef, align 16
> +  %tobool1 = icmp ne i32 %0, 0
> +  br i1 %tobool1, label %CallSite, label %End
> +
> +CallSite:                                          ; preds = %TBB, %Header
> +  %l = phi i32 [ %l1, %Header ], [ %l2, %TBB ]
> +  call void @bar(i32* %ptrarg, i32 %l)
> +  call void @bari(i32 %l)
> +  br label %End
> +
> +End:                                           ; preds = %CallSite, %TBB
> +  ret void
> +}
> +; NODUP-LABEL: @test_no_remove_used_phi
> +; NODUP-NOT: split
> +; CHECK-LABEL: @test_no_remove_used_phi
> +; CHECK-LABEL: Header.split:
> +; CHECK: call void @bar(i32* null, i32 %l1)
> +; CHECK-NEXT: br label %CallSite
> +; CHECK-LABEL: TBB.split:
> +; CHECK: call void @bar(i32* nonnull %ptrarg, i32 %l2)
> +; CHECK-NEXT br label %CallSite
> +; CHECK-LABEL: CallSite:
> +; CHECK-NEXT:  %l = phi i32 [ %l1, %Header.split ], [ %l2, %TBB.split ]
> +; CHECK: call void @bari(i32 %l)
> +
> +define void @bar(i32*, i32) {
> +    ret void
> +}
> +
> +define  void @bari(i32) {
> +    ret void
> +}
> 
> Modified: llvm/trunk/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll (original)
> +++ llvm/trunk/test/Transforms/CallSiteSplitting/callsite-no-or-structure.ll Wed Feb 14 05:59:12 2018
> @@ -3,15 +3,15 @@
>   
>   ; CHECK-LABEL: @test_simple
>   ; CHECK-LABEL: Header:
> -; CHECK-NEXT: br i1 undef, label %Tail.predBB.split
> -; CHECK-LABEL: TBB:
> -; CHECK: br i1 %cmp, label %Tail.predBB.split1
> -; CHECK-LABEL: Tail.predBB.split:
> +; CHECK-NEXT: br i1 undef, label %Header.split
> +; CHECK-LABEL: Header.split:
>   ; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 %p)
> -; CHECK-LABEL: Tail.predBB.split1:
> +; CHECK-LABEL: TBB:
> +; CHECK: br i1 %cmp, label %TBB.split
> +; CHECK-LABEL: TBB.split:
>   ; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 %p)
>   ; CHECK-LABEL: Tail
> -; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ; CHECK: ret i32 %[[MERGED]]
>   define i32 @test_simple(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -31,15 +31,15 @@ End:
>   
>   ; CHECK-LABEL: @test_eq_eq_eq_untaken
>   ; CHECK-LABEL: Header:
> -; CHECK: br i1 %tobool1, label %TBB1, label %Tail.predBB.split
> -; CHECK-LABEL: TBB2:
> -; CHECK: br i1 %cmp2, label %Tail.predBB.split1, label %End
> -; CHECK-LABEL: Tail.predBB.split:
> +; CHECK: br i1 %tobool1, label %TBB1, label %Header.split
> +; CHECK-LABEL: Header.split:
>   ; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
> -; CHECK-LABEL: Tail.predBB.split1:
> +; CHECK-LABEL: TBB2:
> +; CHECK: br i1 %cmp2, label %TBB2.split, label %End
> +; CHECK-LABEL: TBB2.split:
>   ; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 99)
>   ; CHECK-LABEL: Tail
> -; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB2.split ]
>   ; CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq_eq_untaken2(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -64,15 +64,15 @@ End:
>   
>   ; CHECK-LABEL: @test_eq_ne_eq_untaken
>   ; CHECK-LABEL: Header:
> -; CHECK: br i1 %tobool1, label %TBB1, label %Tail.predBB.split
> -; CHECK-LABEL: TBB2:
> -; CHECK: br i1 %cmp2, label %Tail.predBB.split1, label %End
> -; CHECK-LABEL: Tail.predBB.split:
> +; CHECK: br i1 %tobool1, label %TBB1, label %Header.split
> +; CHECK-LABEL: Header.split:
>   ; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
> -; CHECK-LABEL: Tail.predBB.split1:
> +; CHECK-LABEL: TBB2:
> +; CHECK: br i1 %cmp2, label %TBB2.split, label %End
> +; CHECK-LABEL: TBB2.split:
>   ; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 99)
>   ; CHECK-LABEL: Tail
> -; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB2.split ]
>   ; CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_ne_eq_untaken(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -97,17 +97,17 @@ End:
>   
>   ; CHECK-LABEL: @test_header_header2_tbb
>   ; CHECK: Header2:
> -; CHECK:br i1 %tobool2, label %Tail.predBB.split, label %TBB1
> -; CHECK-LABEL: TBB2:
> -; CHECK: br i1 %cmp2, label %Tail.predBB.split1, label %End
> -; CHECK-LABEL: Tail.predBB.split:
> +; CHECK:br i1 %tobool2, label %Header2.split, label %TBB1
> +; CHECK-LABEL: Header2.split:
>   ; CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
> -; CHECK-LABEL: Tail.predBB.split1:
> +; CHECK-LABEL: TBB2:
> +; CHECK: br i1 %cmp2, label %TBB2.split, label %End
> +; CHECK-LABEL: TBB2.split:
>   ; NOTE: CallSiteSplitting cannot infer that %a is null here, as it currently
>   ;       only supports recording conditions along a single predecessor path.
>   ; CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 99)
>   ; CHECK-LABEL: Tail
> -; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +; CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB2.split ]
>   ; CHECK: ret i32 %[[MERGED]]
>   define i32 @test_header_header2_tbb(i32* %a, i32 %v, i32 %p) {
>   Header:
> 
> Modified: llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-debug.ll?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-debug.ll (original)
> +++ llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-debug.ll Wed Feb 14 05:59:12 2018
> @@ -48,10 +48,9 @@ attributes #0 = { nounwind readnone spec
>   ; CallSiteBB.
>   
>   ; CHECK-LABEL: @foo
> -; CHECK-LABEL: CallsiteBB.predBB.split:
> -; CHECK: [[TMP1:%[0-9]+]] = call i16 @bar(i16 1, i16 5)
> -; CHECK-LABEL: CallsiteBB.predBB.split1:
> -; CHECK: [[TMP2:%[0-9]+]] = call i16 @bar(i16 0, i16 5)
> +; CHECK-LABEL: bb1.split:
> +; CHECK: [[TMP1:%[0-9]+]] = call i16 @bar(i16 0, i16 5)
> +; CHECK-LABEL: bb2.split:
> +; CHECK: [[TMP2:%[0-9]+]] = call i16 @bar(i16 1, i16 5)
>   ; CHECK-LABEL: CallsiteBB
> -; CHECK: %phi.call = phi i16 [ [[TMP1]], %CallsiteBB.predBB.split ], [ [[TMP2]], %CallsiteBB.predBB.split1
> -
> +; CHECK: %phi.call = phi i16 [ [[TMP2]], %bb2.split ], [ [[TMP1]], %bb1.split
> 
> Modified: llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll (original)
> +++ llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split-or-phi.ll Wed Feb 14 05:59:12 2018
> @@ -5,13 +5,17 @@ target datalayout = "e-m:e-i8:8:32-i16:1
>   target triple = "aarch64-linaro-linux-gnueabi"
>   
>   ;CHECK-LABEL: @test_eq_eq
> -;CHECK-LABEL: Tail.predBB.split:
> +
> +;CHECK-LABEL: Header:
> +;CHECK: br i1 %tobool1, label %Header.split, label %TBB
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB:
> +;CHECK: br i1 %cmp, label %TBB.split, label %End
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq(i32* %a, i32 %v) {
>   Header:
> @@ -32,12 +36,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_eq_eq_eq
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 10)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq_eq(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -61,12 +65,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_eq_eq_eq_constrain_same_i32_arg
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 222, i32 %p)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 333, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq_eq_constrain_same_i32_arg(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -90,13 +94,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_eq
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_eq(i32* %a, i32 %v) {
>   Header:
> @@ -117,12 +120,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_eq_ne
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_eq_ne(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -146,13 +149,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_ne
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_ne(i32* %a, i32 %v) {
>   Header:
> @@ -173,12 +175,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_ne_ne_constrain_same_pointer_arg
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_ne_ne_constrain_same_pointer_arg(i32* %a, i32 %v, i32 %p, i32* %a2, i32* %a3) {
>   Header:
> @@ -204,13 +206,12 @@ End:
>   
>   
>   ;CHECK-LABEL: @test_eq_eq_untaken
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq_untaken(i32* %a, i32 %v) {
>   Header:
> @@ -231,12 +232,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_eq_eq_eq_untaken
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* nonnull %a, i32 %v, i32 10)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_eq_eq_eq_untaken(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -260,13 +261,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_eq_untaken
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_eq_untaken(i32* %a, i32 %v) {
>   Header:
> @@ -287,12 +287,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_eq_ne_untaken
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header2.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 10)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* null, i32 %v, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header2.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_eq_ne_untaken(i32* %a, i32 %v, i32 %p) {
>   Header:
> @@ -316,13 +316,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_ne_ne_untaken
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* null, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* nonnull %a, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_ne_ne_untaken(i32* %a, i32 %v) {
>   Header:
> @@ -343,13 +342,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_nonconst_const_phi
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 1, %Tail.predBB.split ], [ 2, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_nonconst_const_phi(i32* %a, i32* %b, i32 %v) {
>   Header:
> @@ -370,13 +368,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_nonconst_nonconst_phi
> -;CHECK-LABEL: Tail.predBB.split:
> -;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
> -;CHECK-LABEL: Tail.predBB.split1:
> -;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
> +;CHECK-LABEL: Header.split:
> +;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
> +;CHECK-LABEL: TBB.split:
> +;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 2, %Tail.predBB.split ], [ 1, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL2]], %TBB.split ], [ %[[CALL1]], %Header.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_nonconst_nonconst_phi(i32* %a, i32* %b, i32 %v, i32 %v2) {
>   Header:
> @@ -397,13 +394,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_cfg_no_or_phi
> -;CHECK-LABEL: Tail.predBB.split
> -;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
> -;CHECK-LABEL: Tail.predBB.split1:
> -;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
> +;CHECK-LABEL: TBB0.split
> +;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 1)
> +;CHECK-LABEL: TBB1.split:
> +;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 %v, i32 2)
>   ;CHECK-LABEL: Tail
> -;CHECK: %p = phi i32 [ 2, %Tail.predBB.split ], [ 1, %Tail.predBB.split1 ]
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL2]], %TBB1.split ], [ %[[CALL1]], %TBB0.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_cfg_no_or_phi(i32* %a,  i32 %v) {
>   entry:
> @@ -421,8 +417,8 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_nonconst_nonconst_phi_noncost
> -;CHECK-NOT: Tail.predBB.split:
> -;CHECK-NOT: Tail.predBB.split1:
> +;CHECK-NOT: Header.split:
> +;CHECK-NOT: TBB.split:
>   ;CHECK-LABEL: Tail:
>   ;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
>   ;CHECK: ret i32 %r
> @@ -444,34 +440,9 @@ End:
>     ret i32 %v
>   }
>   
> -;CHECK-LABEL: @test_fisrtnonphi
> -;CHECK-NOT: Tail.predBB.split:
> -;CHECK-NOT: Tail.predBB.split1:
> -;CHECK-LABEL: Tail:
> -;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
> -;CHECK: ret i32 %r
> -define i32 @test_fisrtnonphi(i32* %a, i32 %v) {
> -Header:
> -  %tobool1 = icmp eq i32* %a, null
> -  br i1 %tobool1, label %Tail, label %TBB
> -
> -TBB:
> -  %cmp = icmp eq i32 %v, 1
> -  br i1 %cmp, label %Tail, label %End
> -
> -Tail:
> -  %p = phi i32[1,%Header], [2, %TBB]
> -  store i32 %v, i32* %a
> -  %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
> -  ret i32 %r
> -
> -End:
> -  ret i32 %v
> -}
> -
>   ;CHECK-LABEL: @test_3preds_constphi
> -;CHECK-NOT: Tail.predBB.split:
> -;CHECK-NOT: Tail.predBB.split1:
> +;CHECK-NOT: Header.split:
> +;CHECK-NOT: TBB.split:
>   ;CHECK-LABEL: Tail:
>   ;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
>   ;CHECK: ret i32 %r
> @@ -495,8 +466,8 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_indirectbr_phi
> -;CHECK-NOT: Tail.predBB.split:
> -;CHECK-NOT: Tail.predBB.split1:
> +;CHECK-NOT: Header.split:
> +;CHECK-NOT: TBB.split:
>   ;CHECK-LABEL: Tail:
>   ;CHECK: %r = call i32 @callee(i32* %a, i32 %v, i32 %p)
>   ;CHECK: ret i32 %r
> @@ -519,12 +490,12 @@ End:
>   }
>   
>   ;CHECK-LABEL: @test_unreachable
> -;CHECK-LABEL: Tail.predBB.split:
> +;CHECK-LABEL: Header.split:
>   ;CHECK: %[[CALL1:.*]] = call i32 @callee(i32* %a, i32 %v, i32 10)
> -;CHECK-LABEL: Tail.predBB.split1:
> +;CHECK-LABEL: TBB.split:
>   ;CHECK: %[[CALL2:.*]] = call i32 @callee(i32* %a, i32 1, i32 %p)
>   ;CHECK-LABEL: Tail
> -;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Tail.predBB.split ], [ %[[CALL2]], %Tail.predBB.split1 ]
> +;CHECK: %[[MERGED:.*]] = phi i32 [ %[[CALL1]], %Header.split ], [ %[[CALL2]], %TBB.split ]
>   ;CHECK: ret i32 %[[MERGED]]
>   define i32 @test_unreachable(i32* %a, i32 %v, i32 %p) {
>   Entry:
> 
> Modified: llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split.ll?rev=325126&r1=325125&r2=325126&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split.ll (original)
> +++ llvm/trunk/test/Transforms/CallSiteSplitting/callsite-split.ll Wed Feb 14 05:59:12 2018
> @@ -7,10 +7,10 @@ target triple = "aarch64-linaro-linux-gn
>   %struct.bitmap = type { i32, %struct.bitmap* }
>   
>   ;CHECK-LABEL: @caller
> +;CHECK-LABEL: Top.split:
> +;CHECK: call void @callee(%struct.bitmap* null, %struct.bitmap* null, %struct.bitmap* %b_elt, i1 false)
>   ;CHECK-LABEL: NextCond:
>   ;CHECK: br {{.*}} label %callee.exit
> -;CHECK-LABEL: CallSiteBB.predBB.split:
> -;CHECK: call void @callee(%struct.bitmap* null, %struct.bitmap* null, %struct.bitmap* %b_elt, i1 false)
>   ;CHECK-LABEL: callee.exit:
>   ;CHECK: call void @dummy2(%struct.bitmap* %a_elt)
>   
> @@ -69,12 +69,12 @@ declare void @dummy1(%struct.bitmap*, %s
>   
>   
>   ;CHECK-LABEL: @caller2
> -;CHECK-LABEL: CallSiteBB.predBB.split:
> -;CHECK: call void @dummy3()
> -;CHECK-LABEL: CallSiteBB.predBB.split1:
> +;CHECK-LABEL: Top.split:
>   ;CHECK: call void @dummy4()
> +;CHECK-LABEL: NextCond.split:
> +;CHECK: call void @dummy3()
>   ;CheCK-LABEL: CallSiteBB:
> -;CHECK: %phi.call = phi i1 [ true, %CallSiteBB.predBB.split ], [ false, %CallSiteBB.predBB.split1 ]
> +;CHECK: %phi.call = phi i1 [ true, %NextCond.split ], [ false, %Top.split ]
>   ;CHECK: call void @foo(i1 %phi.call)
>   define void @caller2(i1 %c, %struct.bitmap* %a_elt, %struct.bitmap* %b_elt, %struct.bitmap* %c_elt) {
>   entry:
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> 
-------------- next part --------------
; RUN: opt -S -callsite-splitting < %s | FileCheck %s

define void @fn1(i16 %p1) {
entry:
  ret void
}

define void @fn2() {
  ret void

; Unreachable code below

for.inc:
  br i1 undef, label %for.end6, label %for.inc

for.end6:
  br i1 undef, label %lor.rhs, label %lor.end

lor.rhs:
  br label %lor.end

lor.end:
  call void @fn1(i16 0)
  ret void
}

; The input isn't changed, we just shouldn't loop forever in callsite-splitting.

;CHECK: define void @fn2() {
;CHECK:  ret void

;CHECK: for.inc:
;CHECK:   br i1 undef, label %for.end6, label %for.inc

;CHECK: for.end6:
;CHECK:   br i1 undef, label %lor.rhs, label %lor.end

;CHECK: lor.rhs:
;CHECK:   br label %lor.end

;CHECK: lor.end:
;CHECK:   call void @fn1(i16 0)
;CHECK:   ret void
;CHECK: }


More information about the llvm-commits mailing list