diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -78,6 +78,205 @@ STATISTIC(NumSimpl, "Number of blocks simplified"); +namespace { + +struct CompatibleSets { + using SetTy = SmallVector; + + SmallVector Sets; + + static bool shouldBelongToSameSet(ArrayRef Calls); + + SetTy &getCompatibleSet(CallInst *II); + + void insert(CallInst *II); +}; + +CompatibleSets::SetTy &CompatibleSets::getCompatibleSet(CallInst *II) { + // Perform a linear scan over all the existing sets, see if the new `call` + // is compatible with any particular set. Since we know that all the `calls` + // within a set are compatible, only check the first `call` in each set. + // WARNING: at worst, this has quadratic complexity. + for (CompatibleSets::SetTy &Set : Sets) { + if (CompatibleSets::shouldBelongToSameSet({Set.front(), II})) + return Set; + } + + // Otherwise, we either had no sets yet, or this call forms a new set. + return Sets.emplace_back(); +} + +void CompatibleSets::insert(CallInst *II) { + getCompatibleSet(II).emplace_back(II); +} + +bool CompatibleSets::shouldBelongToSameSet(ArrayRef Calls) { + assert(Calls.size() == 2 && "Always called with exactly two candidates."); + + // Can we theoretically merge these `call`s? + auto IsIllegalToMerge = [](CallInst *II) { + return II->cannotMerge() || II->isInlineAsm(); + }; + if (any_of(Calls, IsIllegalToMerge)) + return false; + + // Either both `call`s must be direct, + // or both `call`s must be indirect. + auto IsIndirectCall = [](CallInst *II) { return II->isIndirectCall(); }; + bool HaveIndirectCalls = any_of(Calls, IsIndirectCall); + bool AllCallsAreIndirect = all_of(Calls, IsIndirectCall); + if (HaveIndirectCalls) { + if (!AllCallsAreIndirect) + return false; + } else { + // All callees must be identical. + Value *Callee = nullptr; + for (CallInst *II : Calls) { + Value *CurrCallee = II->getCalledOperand(); + assert(CurrCallee && "There is always a called operand."); + if (!Callee) + Callee = CurrCallee; + else if (Callee != CurrCallee) + return false; + } + } + + // Ignoring arguments, these `call`s must be identical, + // including operand bundles. + const CallInst *II0 = Calls.front(); + for (auto *II : Calls.drop_front()) + if (!II->isSameOperationAs(II0)) + return false; + + // Can we theoretically form the data operands for the merged `call`? + auto IsIllegalToMergeArguments = [](auto Ops) { + Type *Ty = std::get<0>(Ops)->getType(); + assert(Ty == std::get<1>(Ops)->getType() && "Incompatible types?"); + return Ty->isTokenTy() && std::get<0>(Ops) != std::get<1>(Ops); + }; + assert(Calls.size() == 2 && "Always called with exactly two candidates."); + if (any_of(zip(Calls[0]->data_ops(), Calls[1]->data_ops()), + IsIllegalToMergeArguments)) + return false; + + return true; +} + +} // namespace + +// Merge all calls in the provided set, all of which are compatible +// as per the `CompatibleSets::shouldBelongToSameSet()`. +static void MergeCompatibleUnreachableTerminatedCallsImpl( + ArrayRef Calls, + std::vector *Updates) { + assert(Calls.size() >= 2 && "Must have at least two calls to merge."); + + if (Updates) + Updates->reserve(Updates->size() + Calls.size()); + + // Clone one of the calls into a new basic block. + // Since they are all compatible, it doesn't matter which call is cloned. + CallInst *MergedCall = [&Calls]() { + CallInst *II0 = Calls.front(); + BasicBlock *II0BB = II0->getParent(); + BasicBlock *InsertBeforeBlock = + II0->getParent()->getIterator()->getNextNode(); + Function *Func = II0BB->getParent(); + LLVMContext &Ctx = II0->getContext(); + + BasicBlock *MergedCallBB = + BasicBlock::Create(Ctx, "", Func, InsertBeforeBlock); + + auto *MergedCall = cast(II0->clone()); + // NOTE: all calls have the same attributes, so no handling needed. + MergedCallBB->getInstList().push_back(MergedCall); + new UnreachableInst(Ctx, MergedCallBB); + + return MergedCall; + }(); + + if (Updates) { + // Blocks that contained these calls will now branch to + // the new block that contains the merged call. + for (CallInst *CI : Calls) + Updates->push_back( + {DominatorTree::Insert, CI->getParent(), MergedCall->getParent()}); + } + + bool IsIndirectCall = Calls[0]->isIndirectCall(); + + // Form the merged operands for the merged call. + for (Use &U : MergedCall->operands()) { + // Only PHI together the indirect callees and data operands. + if (MergedCall->isCallee(&U)) { + if (!IsIndirectCall) + continue; + } else if (!MergedCall->isDataOperand(&U)) + continue; + + // Don't create trivial PHI's with all-identical incoming values. + bool NeedPHI = any_of(Calls, [&U](CallInst *CI) { + return CI->getOperand(U.getOperandNo()) != U.get(); + }); + if (!NeedPHI) + continue; + + // Form a PHI out of all the data ops under this index. + PHINode *PN = PHINode::Create( + U->getType(), /*NumReservedValues=*/Calls.size(), "", MergedCall); + for (CallInst *CI : Calls) + PN->addIncoming(CI->getOperand(U.getOperandNo()), CI->getParent()); + + U.set(PN); + } + + // And finally, replace the original `call`s with an unconditional branch + // to the block with the merged `call`. Also, give that merged `call` + // the merged debugloc of all the original `call`s. + const DILocation *MergedDebugLoc = nullptr; + for (CallInst *CI : Calls) { + // Compute the debug location common to all the original `call`s. + if (!MergedDebugLoc) + MergedDebugLoc = CI->getDebugLoc(); + else + MergedDebugLoc = + DILocation::getMergedLocation(MergedDebugLoc, CI->getDebugLoc()); + + // And replace the old `call`+`unreachable` with an unconditional branch + // to the block with the merged `call`. + BranchInst::Create(MergedCall->getParent(), CI->getParent()); + cast(CI->getNextNode())->eraseFromParent(); + CI->eraseFromParent(); + } + MergedCall->setDebugLoc(MergedDebugLoc); +} + +static bool MergeCompatibleUnreachableTerminatedCalls( + ArrayRef BBs, + std::vector *Updates) { + bool Changed = false; + + CompatibleSets Grouper; + + for (BasicBlock *BB : BBs) { + auto *Term = BB->getTerminator(); + assert(isa(Term) && + "Only for blocks with `unreachable` terminator."); + // Only deal with blocks where `unreachable` is preceeded by a `call`. + if (auto *CI = dyn_cast_or_null(Term->getPrevNode())) + Grouper.insert(CI); + } + + for (ArrayRef Calls : Grouper.Sets) { + if (Calls.size() < 2) + continue; + Changed = true; + MergeCompatibleUnreachableTerminatedCallsImpl(Calls, Updates); + } + + return Changed; +} + static bool performBlockTailMerging(Function &F, ArrayRef BBs, std::vector *Updates) { @@ -88,6 +287,10 @@ if (BBs.size() < 2) return false; + // Defer handling of `unreachable` blocks to the specialized utility. + if (isa(BBs[0]->getTerminator())) + return MergeCompatibleUnreachableTerminatedCalls(BBs, Updates); + if (Updates) Updates->reserve(Updates->size() + BBs.size()); @@ -172,6 +375,7 @@ switch (Term->getOpcode()) { case Instruction::Ret: case Instruction::Resume: + case Instruction::Unreachable: break; default: continue; diff --git a/llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll b/llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll --- a/llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll +++ b/llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll @@ -25,18 +25,18 @@ ; CHECK-NEXT: b LSJLJEH0 ; CHECK-NEXT: movs r0, #1 @ eh_setjmp end ; CHECK-NEXT: LSJLJEH0: -; CHECK-NEXT: cbz r0, LBB0_3 -; CHECK-NEXT: @ %bb.1: @ %if.then -; CHECK-NEXT: movw r0, :lower16:(L_g$non_lazy_ptr-(LPC0_0+4)) -; CHECK-NEXT: movt r0, :upper16:(L_g$non_lazy_ptr-(LPC0_0+4)) +; CHECK-NEXT: movw r1, :lower16:(L_g$non_lazy_ptr-(LPC0_0+4)) +; CHECK-NEXT: movt r1, :upper16:(L_g$non_lazy_ptr-(LPC0_0+4)) ; CHECK-NEXT: LPC0_0: -; CHECK-NEXT: add r0, pc -; CHECK-NEXT: ldr r1, [r0] +; CHECK-NEXT: add r1, pc +; CHECK-NEXT: cbz r0, LBB0_4 +; CHECK-NEXT: @ %bb.1: @ %if.then +; CHECK-NEXT: ldr r2, [r1] ; CHECK-NEXT: movs r0, #1 -; CHECK-NEXT: str r1, [sp] @ 4-byte Spill -; CHECK-NEXT: str r0, [r1] -; CHECK-NEXT: add r0, sp, #4 +; CHECK-NEXT: str r2, [sp] @ 4-byte Spill ; CHECK-NEXT: movs r1, #0 +; CHECK-NEXT: str r0, [r2] +; CHECK-NEXT: add r0, sp, #4 ; CHECK-NEXT: str r7, [sp, #4] ; CHECK-NEXT: str.w sp, [sp, #12] ; CHECK-NEXT: mov r1, pc @ eh_setjmp begin @@ -54,31 +54,26 @@ ; CHECK-NEXT: addne sp, #24 ; CHECK-NEXT: it ne ; CHECK-NEXT: popne.w {r4, r5, r6, r7, r8, r10, r11, pc} -; CHECK-NEXT: LBB0_2: @ %if2.else -; CHECK-NEXT: ldr r1, [sp] @ 4-byte Reload +; CHECK-NEXT: LBB0_2: +; CHECK-NEXT: movw r1, :lower16:(L_g$non_lazy_ptr-(LPC0_1+4)) +; CHECK-NEXT: add r2, sp, #4 +; CHECK-NEXT: movt r1, :upper16:(L_g$non_lazy_ptr-(LPC0_1+4)) ; CHECK-NEXT: movs r0, #2 -; CHECK-NEXT: str r0, [r1] -; CHECK-NEXT: add r1, sp, #4 -; CHECK-NEXT: movs r0, #0 -; CHECK-NEXT: ldr r0, [r1, #8] -; CHECK-NEXT: mov sp, r0 -; CHECK-NEXT: ldr r0, [r1, #4] -; CHECK-NEXT: ldr r7, [r1] -; CHECK-NEXT: bx r0 -; CHECK-NEXT: LBB0_3: @ %if.else -; CHECK-NEXT: movw r0, :lower16:(L_g$non_lazy_ptr-(LPC0_1+4)) -; CHECK-NEXT: movs r1, #0 -; CHECK-NEXT: movt r0, :upper16:(L_g$non_lazy_ptr-(LPC0_1+4)) ; CHECK-NEXT: LPC0_1: -; CHECK-NEXT: add r0, pc -; CHECK-NEXT: ldr r0, [r0] -; CHECK-NEXT: str r1, [r0] -; CHECK-NEXT: add r0, sp, #4 -; CHECK-NEXT: ldr r1, [r0, #8] -; CHECK-NEXT: mov sp, r1 -; CHECK-NEXT: ldr r1, [r0, #4] -; CHECK-NEXT: ldr r7, [r0] -; CHECK-NEXT: bx r1 +; CHECK-NEXT: add r1, pc +; CHECK-NEXT: LBB0_3: @ %if2.else +; CHECK-NEXT: ldr r1, [r1] +; CHECK-NEXT: str r0, [r1] +; CHECK-NEXT: movs r0, #0 +; CHECK-NEXT: ldr r0, [r2, #8] +; CHECK-NEXT: mov sp, r0 +; CHECK-NEXT: ldr r0, [r2, #4] +; CHECK-NEXT: ldr r7, [r2] +; CHECK-NEXT: bx r0 +; CHECK-NEXT: LBB0_4: +; CHECK-NEXT: add r2, sp, #4 +; CHECK-NEXT: movs r0, #0 +; CHECK-NEXT: b LBB0_3 entry: %buf = alloca [5 x i8*], align 4 %bufptr = bitcast [5 x i8*]* %buf to i8* diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/peel-multiple-unreachable-exits-for-vectorization.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/peel-multiple-unreachable-exits-for-vectorization.ll --- a/llvm/test/Transforms/PhaseOrdering/AArch64/peel-multiple-unreachable-exits-for-vectorization.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/peel-multiple-unreachable-exits-for-vectorization.ll @@ -30,64 +30,62 @@ ; CHECK-NEXT: [[C_PEEL:%.*]] = icmp sgt i64 [[N:%.*]], 0 ; CHECK-NEXT: br i1 [[C_PEEL]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: loop.preheader: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[SUB_I]], 0 ; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB_I7_PEEL]], i64 [[SUB_I]]) -; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 -; CHECK-NEXT: [[UMIN16:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN]], i64 [[TMP0]]) -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[UMIN16]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 5 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER22:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 0, i64 [[UMIN]] +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[N]], -1 +; CHECK-NEXT: [[UMIN16:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]]) +; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[UMIN16]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 5 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER28:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP1]], 3 -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP3]], 3 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] ; CHECK-NEXT: [[IND_END:%.*]] = add i64 [[N_VEC]], 1 -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> , i64 [[SUM_NEXT_PEEL]], i64 0 +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i64> , i64 [[SUM_NEXT_PEEL]], i64 0 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP4]], [[VECTOR_PH]] ], [ [[TMP15:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI18:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP16:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP6]], [[VECTOR_PH]] ], [ [[TMP17:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI18:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP18:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[OFFSET_IDX:%.*]] = or i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i64* [[TMP5]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, i64* [[TMP5]], i64 2 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP8:%.*]] = bitcast i64* [[TMP7]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD19:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8]], align 4 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i64, i64* [[TMP7]], i64 2 ; CHECK-NEXT: [[TMP10:%.*]] = bitcast i64* [[TMP9]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD20:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10]], align 4 -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i64, i64* [[TMP9]], i64 2 +; CHECK-NEXT: [[WIDE_LOAD25:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10]], align 4 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP12:%.*]] = bitcast i64* [[TMP11]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD21:%.*]] = load <2 x i64>, <2 x i64>* [[TMP12]], align 4 -; CHECK-NEXT: [[TMP13:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]] -; CHECK-NEXT: [[TMP14:%.*]] = add <2 x i64> [[WIDE_LOAD19]], [[VEC_PHI18]] -; CHECK-NEXT: [[TMP15]] = add <2 x i64> [[TMP13]], [[WIDE_LOAD20]] -; CHECK-NEXT: [[TMP16]] = add <2 x i64> [[TMP14]], [[WIDE_LOAD21]] +; CHECK-NEXT: [[WIDE_LOAD26:%.*]] = load <2 x i64>, <2 x i64>* [[TMP12]], align 4 +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i64, i64* [[TMP11]], i64 2 +; CHECK-NEXT: [[TMP14:%.*]] = bitcast i64* [[TMP13]] to <2 x i64>* +; CHECK-NEXT: [[WIDE_LOAD27:%.*]] = load <2 x i64>, <2 x i64>* [[TMP14]], align 4 +; CHECK-NEXT: [[TMP15:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[TMP16:%.*]] = add <2 x i64> [[WIDE_LOAD25]], [[VEC_PHI18]] +; CHECK-NEXT: [[TMP17]] = add <2 x i64> [[TMP15]], [[WIDE_LOAD26]] +; CHECK-NEXT: [[TMP18]] = add <2 x i64> [[TMP16]], [[WIDE_LOAD27]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP16]], [[TMP15]] -; CHECK-NEXT: [[TMP18:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]]) -; CHECK-NEXT: br label [[LOOP_PREHEADER22]] -; CHECK: loop.preheader22: +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP18]], [[TMP17]] +; CHECK-NEXT: [[TMP20:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]]) +; CHECK-NEXT: br label [[LOOP_PREHEADER28]] +; CHECK: loop.preheader28: ; CHECK-NEXT: [[IV_PH:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP18]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP20]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER22]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12]] ], [ [[SUM_PH]], [[LOOP_PREHEADER22]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER28]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12]] ], [ [[SUM_PH]], [[LOOP_PREHEADER28]] ] ; CHECK-NEXT: [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]] -; CHECK-NEXT: br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]] -; CHECK: error.i: -; CHECK-NEXT: tail call void @error() -; CHECK-NEXT: unreachable -; CHECK: at_with_int_conversion.exit: ; CHECK-NEXT: [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7_PEEL]], [[IV]] -; CHECK-NEXT: br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12]] -; CHECK: error.i11: +; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[INRANGE_I]], i1 true, i1 [[INRANGE_I8]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12]] +; CHECK: error.i: ; CHECK-NEXT: tail call void @error() ; CHECK-NEXT: unreachable ; CHECK: at_with_int_conversion.exit12: @@ -154,84 +152,79 @@ ; CHECK-NEXT: [[COND_PEEL:%.*]] = icmp sgt i64 [[N:%.*]], 0 ; CHECK-NEXT: br i1 [[COND_PEEL]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: loop.preheader: +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[SUB_I7_PEEL]], 0 ; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB_I19_PEEL]], i64 [[SUB_I7_PEEL]]) -; CHECK-NEXT: [[UMIN28:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN]], i64 [[SUB_I]]) -; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 -; CHECK-NEXT: [[UMIN29:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN28]], i64 [[TMP0]]) -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[UMIN29]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP1]], 5 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER37:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 0, i64 [[UMIN]] +; CHECK-NEXT: [[UMIN28:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[SUB_I]]) +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[N]], -1 +; CHECK-NEXT: [[UMIN29:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN28]], i64 [[TMP2]]) +; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[UMIN29]], 1 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP3]], 5 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER43:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP1]], 3 -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP3]] +; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP3]], 3 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP4]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[TMP5]] ; CHECK-NEXT: [[IND_END:%.*]] = add i64 [[N_VEC]], 1 -; CHECK-NEXT: [[TMP4:%.*]] = insertelement <2 x i64> , i64 [[SUM_NEXT_PEEL]], i64 0 +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i64> , i64 [[SUM_NEXT_PEEL]], i64 0 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP4]], [[VECTOR_PH]] ], [ [[TMP21:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI31:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP22:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP6]], [[VECTOR_PH]] ], [ [[TMP23:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI31:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP24:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[OFFSET_IDX:%.*]] = or i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i64* [[TMP5]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, i64* [[TMP5]], i64 2 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP8:%.*]] = bitcast i64* [[TMP7]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD32:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP8]], align 4 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i64, i64* [[TMP7]], i64 2 ; CHECK-NEXT: [[TMP10:%.*]] = bitcast i64* [[TMP9]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD33:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10]], align 4 -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i64, i64* [[TMP9]], i64 2 +; CHECK-NEXT: [[WIDE_LOAD38:%.*]] = load <2 x i64>, <2 x i64>* [[TMP10]], align 4 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP12:%.*]] = bitcast i64* [[TMP11]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD34:%.*]] = load <2 x i64>, <2 x i64>* [[TMP12]], align 4 -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i64, i64* [[START_I14_PEEL]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[WIDE_LOAD39:%.*]] = load <2 x i64>, <2 x i64>* [[TMP12]], align 4 +; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i64, i64* [[TMP11]], i64 2 ; CHECK-NEXT: [[TMP14:%.*]] = bitcast i64* [[TMP13]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD35:%.*]] = load <2 x i64>, <2 x i64>* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i64, i64* [[TMP13]], i64 2 +; CHECK-NEXT: [[WIDE_LOAD40:%.*]] = load <2 x i64>, <2 x i64>* [[TMP14]], align 4 +; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i64, i64* [[START_I14_PEEL]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP16:%.*]] = bitcast i64* [[TMP15]] to <2 x i64>* -; CHECK-NEXT: [[WIDE_LOAD36:%.*]] = load <2 x i64>, <2 x i64>* [[TMP16]], align 4 -; CHECK-NEXT: [[TMP17:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]] -; CHECK-NEXT: [[TMP18:%.*]] = add <2 x i64> [[WIDE_LOAD32]], [[VEC_PHI31]] -; CHECK-NEXT: [[TMP19:%.*]] = add <2 x i64> [[TMP17]], [[WIDE_LOAD33]] -; CHECK-NEXT: [[TMP20:%.*]] = add <2 x i64> [[TMP18]], [[WIDE_LOAD34]] -; CHECK-NEXT: [[TMP21]] = add <2 x i64> [[TMP19]], [[WIDE_LOAD35]] -; CHECK-NEXT: [[TMP22]] = add <2 x i64> [[TMP20]], [[WIDE_LOAD36]] +; CHECK-NEXT: [[WIDE_LOAD41:%.*]] = load <2 x i64>, <2 x i64>* [[TMP16]], align 4 +; CHECK-NEXT: [[TMP17:%.*]] = getelementptr i64, i64* [[TMP15]], i64 2 +; CHECK-NEXT: [[TMP18:%.*]] = bitcast i64* [[TMP17]] to <2 x i64>* +; CHECK-NEXT: [[WIDE_LOAD42:%.*]] = load <2 x i64>, <2 x i64>* [[TMP18]], align 4 +; CHECK-NEXT: [[TMP19:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[TMP20:%.*]] = add <2 x i64> [[WIDE_LOAD38]], [[VEC_PHI31]] +; CHECK-NEXT: [[TMP21:%.*]] = add <2 x i64> [[TMP19]], [[WIDE_LOAD39]] +; CHECK-NEXT: [[TMP22:%.*]] = add <2 x i64> [[TMP20]], [[WIDE_LOAD40]] +; CHECK-NEXT: [[TMP23]] = add <2 x i64> [[TMP21]], [[WIDE_LOAD41]] +; CHECK-NEXT: [[TMP24]] = add <2 x i64> [[TMP22]], [[WIDE_LOAD42]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP23:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP23]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK-NEXT: [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP25]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP22]], [[TMP21]] -; CHECK-NEXT: [[TMP24:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]]) -; CHECK-NEXT: br label [[LOOP_PREHEADER37]] -; CHECK: loop.preheader37: +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP24]], [[TMP23]] +; CHECK-NEXT: [[TMP26:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]]) +; CHECK-NEXT: br label [[LOOP_PREHEADER43]] +; CHECK: loop.preheader43: ; CHECK-NEXT: [[IV_PH:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP24]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER37]] ] -; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24]] ], [ [[SUM_PH]], [[LOOP_PREHEADER37]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER43]] ] +; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24]] ], [ [[SUM_PH]], [[LOOP_PREHEADER43]] ] ; CHECK-NEXT: [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]] ; CHECK-NEXT: br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]] ; CHECK: error.i: ; CHECK-NEXT: tail call void @error() ; CHECK-NEXT: unreachable ; CHECK: at_with_int_conversion.exit: +; CHECK-NEXT: [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7_PEEL]], [[IV]] +; CHECK-NEXT: [[INRANGE_I20:%.*]] = icmp ult i64 [[SUB_I19_PEEL]], [[IV]] +; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[INRANGE_I8]], i1 true, i1 [[INRANGE_I20]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[ERROR_I]], label [[AT_WITH_INT_CONVERSION_EXIT24]] +; CHECK: at_with_int_conversion.exit24: ; CHECK-NEXT: [[GEP_IDX_I:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[IV]] ; CHECK-NEXT: [[LV_I:%.*]] = load i64, i64* [[GEP_IDX_I]], align 4 -; CHECK-NEXT: [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7_PEEL]], [[IV]] -; CHECK-NEXT: br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12:%.*]] -; CHECK: error.i11: -; CHECK-NEXT: tail call void @error() -; CHECK-NEXT: unreachable -; CHECK: at_with_int_conversion.exit12: -; CHECK-NEXT: [[INRANGE_I20:%.*]] = icmp ult i64 [[SUB_I19_PEEL]], [[IV]] -; CHECK-NEXT: br i1 [[INRANGE_I20]], label [[ERROR_I23:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT24]] -; CHECK: error.i23: -; CHECK-NEXT: tail call void @error() -; CHECK-NEXT: unreachable -; CHECK: at_with_int_conversion.exit24: ; CHECK-NEXT: [[GEP_IDX_I9:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[IV]] ; CHECK-NEXT: [[LV_I10:%.*]] = load i64, i64* [[GEP_IDX_I9]], align 4 ; CHECK-NEXT: [[GEP_IDX_I21:%.*]] = getelementptr i64, i64* [[START_I14_PEEL]], i64 [[IV]] diff --git a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll --- a/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll +++ b/llvm/test/Transforms/SimplifyCFG/X86/merge-compatible-invokes-of-landingpad.ll @@ -1811,10 +1811,7 @@ ; CHECK-LABEL: @t30_completely_different_normal_dests( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C0:%.*]] = call i1 @cond() -; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]] -; CHECK: if.then0: -; CHECK-NEXT: invoke void @maybe_throw() -; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]] +; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]] ; CHECK: invoke.cont0: ; CHECK-NEXT: call void @sideeffect() ; CHECK-NEXT: unreachable @@ -1825,13 +1822,10 @@ ; CHECK-NEXT: resume { i8*, i32 } [[EH]] ; CHECK: if.else: ; CHECK-NEXT: [[C1:%.*]] = call i1 @cond() -; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]] -; CHECK: if.then1: +; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]] +; CHECK: if.then1.invoke: ; CHECK-NEXT: invoke void @maybe_throw() -; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]] -; CHECK: invoke.cont2: -; CHECK-NEXT: call void @sideeffect() -; CHECK-NEXT: unreachable +; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]] ; CHECK: if.end: ; CHECK-NEXT: call void @sideeffect() ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SimplifyCFG/implied-cond.ll b/llvm/test/Transforms/SimplifyCFG/implied-cond.ll --- a/llvm/test/Transforms/SimplifyCFG/implied-cond.ll +++ b/llvm/test/Transforms/SimplifyCFG/implied-cond.ll @@ -43,14 +43,12 @@ ; CHECK-NEXT: br i1 [[VAR29]], label [[NEXT:%.*]], label [[OUT_OF_BOUNDS:%.*]] ; CHECK: next: ; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[I]], [[LENGTH_I]] -; CHECK-NEXT: br i1 [[VAR30]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS2:%.*]] +; CHECK-NEXT: br i1 [[VAR30]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS]] ; CHECK: in_bounds: ; CHECK-NEXT: ret void ; CHECK: out_of_bounds: -; CHECK-NEXT: call void @foo(i64 0) -; CHECK-NEXT: unreachable -; CHECK: out_of_bounds2: -; CHECK-NEXT: call void @foo(i64 1) +; CHECK-NEXT: [[TMP1:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ 1, [[NEXT]] ] +; CHECK-NEXT: call void @foo(i64 [[TMP1]]) ; CHECK-NEXT: unreachable ; %iplus1 = add i32 %i, 1 diff --git a/llvm/test/Transforms/SimplifyCFG/iterative-simplify.ll b/llvm/test/Transforms/SimplifyCFG/iterative-simplify.ll --- a/llvm/test/Transforms/SimplifyCFG/iterative-simplify.ll +++ b/llvm/test/Transforms/SimplifyCFG/iterative-simplify.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: %"alloca point" = bitcast i32 0 to i32 ; CHECK-NEXT: store i32 0, i32* [[I]], align 4 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8 1, 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[COND_FALSE33:%.*]] +; CHECK-NEXT: br i1 [[TOBOOL]], label [[COND_TRUE:%.*]], label [[BB13:%.*]] ; CHECK: cond_true: ; CHECK-NEXT: store i32 0, i32* [[Z]], align 4 ; CHECK-NEXT: br label [[BB:%.*]] @@ -36,13 +36,10 @@ ; CHECK-NEXT: [[TMP10:%.*]] = icmp ne i32 [[TMP9]], 0 ; CHECK-NEXT: [[TMP1011:%.*]] = zext i1 [[TMP10]] to i8 ; CHECK-NEXT: [[TOBOOL12:%.*]] = icmp ne i8 [[TMP1011]], 0 -; CHECK-NEXT: br i1 [[TOBOOL12]], label [[BB]], label [[BB13:%.*]] +; CHECK-NEXT: br i1 [[TOBOOL12]], label [[BB]], label [[BB13]] ; CHECK: bb13: ; CHECK-NEXT: call void @exit(i32 0) ; CHECK-NEXT: unreachable -; CHECK: cond_false33: -; CHECK-NEXT: call void @exit(i32 0) -; CHECK-NEXT: unreachable ; entry: %retval = alloca i32, align 4 ; [#uses=1] diff --git a/llvm/test/Transforms/SimplifyCFG/tail-merge-assert.ll b/llvm/test/Transforms/SimplifyCFG/tail-merge-assert.ll --- a/llvm/test/Transforms/SimplifyCFG/tail-merge-assert.ll +++ b/llvm/test/Transforms/SimplifyCFG/tail-merge-assert.ll @@ -27,21 +27,17 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond.false: -; CHECK-NEXT: tail call void @glibc_assert_fail(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i32 3, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @__PRETTY_FUNCTION__._Z1fjj, i64 0, i64 0)) +; CHECK-NEXT: [[TMP0:%.*]] = phi i8* [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0), [[ENTRY:%.*]] ], [ getelementptr inbounds ([10 x i8], [10 x i8]* @.str.2, i64 0, i64 0), [[COND_END]] ], [ getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i64 0, i64 0), [[COND_END4:%.*]] ] +; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ 3, [[ENTRY]] ], [ 4, [[COND_END]] ], [ 5, [[COND_END4]] ] +; CHECK-NEXT: tail call void @glibc_assert_fail(i8* [[TMP0]], i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i32 [[TMP1]], i8* getelementptr inbounds ([35 x i8], [35 x i8]* @__PRETTY_FUNCTION__._Z1fjj, i64 0, i64 0)) ; CHECK-NEXT: unreachable ; CHECK: cond.end: ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y]], [[X]] ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[SUB]], 7 -; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END4:%.*]], label [[COND_FALSE3:%.*]] -; CHECK: cond.false3: -; CHECK-NEXT: tail call void @glibc_assert_fail(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.2, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i32 4, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @__PRETTY_FUNCTION__._Z1fjj, i64 0, i64 0)) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END4]], label [[COND_FALSE]] ; CHECK: cond.end4: ; CHECK-NEXT: [[CMP6:%.*]] = icmp ult i32 [[SUB]], 40 -; CHECK-NEXT: br i1 [[CMP6]], label [[COND_END9:%.*]], label [[COND_FALSE8:%.*]] -; CHECK: cond.false8: -; CHECK-NEXT: tail call void @glibc_assert_fail(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i64 0, i64 0), i32 5, i8* getelementptr inbounds ([35 x i8], [35 x i8]* @__PRETTY_FUNCTION__._Z1fjj, i64 0, i64 0)) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[CMP6]], label [[COND_END9:%.*]], label [[COND_FALSE]] ; CHECK: cond.end9: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimplifyCFG/tail-merge-noreturn.ll b/llvm/test/Transforms/SimplifyCFG/tail-merge-noreturn.ll --- a/llvm/test/Transforms/SimplifyCFG/tail-merge-noreturn.ll +++ b/llvm/test/Transforms/SimplifyCFG/tail-merge-noreturn.ll @@ -16,16 +16,10 @@ ; CHECK-NEXT: unreachable ; CHECK: cont1: ; CHECK-NEXT: [[C2:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A2:%.*]] -; CHECK: a2: -; CHECK-NEXT: call void @assert_fail_1(i32 0) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A1]] ; CHECK: cont2: ; CHECK-NEXT: [[C3:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A3:%.*]] -; CHECK: a3: -; CHECK-NEXT: call void @assert_fail_1(i32 0) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A1]] ; CHECK: cont3: ; CHECK-NEXT: ret void ; @@ -56,20 +50,15 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @foo() ; CHECK-NEXT: br i1 [[C1]], label [[CONT1:%.*]], label [[A1:%.*]] ; CHECK: a1: -; CHECK-NEXT: call void @assert_fail_1(i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[CONT1]] ], [ 2, [[CONT2:%.*]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP0]]) ; CHECK-NEXT: unreachable ; CHECK: cont1: ; CHECK-NEXT: [[C2:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A2:%.*]] -; CHECK: a2: -; CHECK-NEXT: call void @assert_fail_1(i32 1) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C2]], label [[CONT2]], label [[A1]] ; CHECK: cont2: ; CHECK-NEXT: [[C3:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A3:%.*]] -; CHECK: a3: -; CHECK-NEXT: call void @assert_fail_1(i32 2) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A1]] ; CHECK: cont3: ; CHECK-NEXT: ret void ; @@ -100,14 +89,12 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @foo() ; CHECK-NEXT: br i1 [[C1]], label [[CONT1:%.*]], label [[A1:%.*]] ; CHECK: a1: -; CHECK-NEXT: call void @assert_fail_1(i32 [[X:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[X:%.*]], [[TMP0:%.*]] ], [ [[Y:%.*]], [[CONT1]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP1]]) ; CHECK-NEXT: unreachable ; CHECK: cont1: ; CHECK-NEXT: [[C2:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A2:%.*]] -; CHECK: a2: -; CHECK-NEXT: call void @assert_fail_1(i32 [[Y:%.*]]) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A1]] ; CHECK: cont2: ; CHECK-NEXT: ret void ; @@ -171,13 +158,12 @@ ; CHECK-NEXT: [[C2:%.*]] = call i1 @bar() ; CHECK-NEXT: br i1 [[C2]], label [[A1]], label [[A2]] ; CHECK: a1: -; CHECK-NEXT: [[L1:%.*]] = phi i32 [ 0, [[S1]] ], [ 1, [[S2]] ] -; CHECK-NEXT: call void @assert_fail_1(i32 [[L1]]) +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[L2:%.*]], [[A2]] ], [ 0, [[S1]] ], [ 1, [[S2]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP0]]) ; CHECK-NEXT: unreachable ; CHECK: a2: -; CHECK-NEXT: [[L2:%.*]] = phi i32 [ 2, [[S1]] ], [ 3, [[S2]] ] -; CHECK-NEXT: call void @assert_fail_1(i32 [[L2]]) -; CHECK-NEXT: unreachable +; CHECK-NEXT: [[L2]] = phi i32 [ 2, [[S1]] ], [ 3, [[S2]] ] +; CHECK-NEXT: br label [[A1]] ; entry: br i1 %c, label %s1, label %s2 @@ -206,14 +192,13 @@ ; CHECK-NEXT: i32 42, label [[A3:%.*]] ; CHECK-NEXT: ] ; CHECK: a1: -; CHECK-NEXT: call void @assert_fail_1(i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 1, [[A2]] ], [ 2, [[A3]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP0]]) ; CHECK-NEXT: unreachable ; CHECK: a2: -; CHECK-NEXT: call void @assert_fail_1(i32 1) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br label [[A1]] ; CHECK: a3: -; CHECK-NEXT: call void @assert_fail_1(i32 2) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br label [[A1]] ; CHECK: ret: ; CHECK-NEXT: ret void ; @@ -242,15 +227,11 @@ ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB2:%.*]], label [[A1:%.*]] ; CHECK: bb2: ; CHECK-NEXT: [[C2:%.*]] = call i1 @bar() -; CHECK-NEXT: br i1 [[C2]], label [[A2:%.*]], label [[A3:%.*]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[C2]], i32 1, i32 2 +; CHECK-NEXT: br label [[A1]] ; CHECK: a1: -; CHECK-NEXT: call void @assert_fail_1(i32 0) -; CHECK-NEXT: unreachable -; CHECK: a2: -; CHECK-NEXT: call void @assert_fail_1(i32 1) -; CHECK-NEXT: unreachable -; CHECK: a3: -; CHECK-NEXT: call void @assert_fail_1(i32 2) +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ [[DOT]], [[BB2]] ], [ 0, [[BB1:%.*]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP0]]) ; CHECK-NEXT: unreachable ; bb1: @@ -276,18 +257,15 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @foo() ; CHECK-NEXT: br i1 [[C1]], label [[CONT1:%.*]], label [[A1:%.*]] ; CHECK: a1: -; CHECK-NEXT: call void @assert_fail_1(i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[CONT1]] ], [ 2, [[CONT2:%.*]] ] +; CHECK-NEXT: call void @assert_fail_1(i32 [[TMP0]]) ; CHECK-NEXT: unreachable ; CHECK: cont1: ; CHECK-NEXT: [[C2:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A2:%.*]] -; CHECK: a2: -; CHECK-NEXT: [[P2:%.*]] = phi i32 [ 1, [[CONT1]] ], [ 2, [[CONT2]] ] -; CHECK-NEXT: call void @assert_fail_1(i32 [[P2]]) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C2]], label [[CONT2]], label [[A1]] ; CHECK: cont2: ; CHECK-NEXT: [[C3:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A2]] +; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A1]] ; CHECK: cont3: ; CHECK-NEXT: ret void ; @@ -338,11 +316,13 @@ ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP0]]) +; CHECK-NEXT: br label [[TMP1:%.*]] +; CHECK: 1: ; CHECK-NEXT: call void @abort() ; CHECK-NEXT: unreachable ; CHECK: if.then3: -; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[Y]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32* [[Y]] to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP2]]) ; CHECK-NEXT: store i32 0, i32* [[Y]], align 4 ; CHECK-NEXT: [[TOBOOL5:%.*]] = icmp eq i32 [[C2]], 0 ; CHECK-NEXT: br i1 [[TOBOOL5]], label [[IF_END7:%.*]], label [[IF_THEN6:%.*]] @@ -350,9 +330,8 @@ ; CHECK-NEXT: call void @escape_i32_ptr(i32* nonnull [[Y]]) ; CHECK-NEXT: br label [[IF_END7]] ; CHECK: if.end7: -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP1]]) -; CHECK-NEXT: call void @abort() -; CHECK-NEXT: unreachable +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP2]]) +; CHECK-NEXT: br label [[TMP1]] ; CHECK: if.end9: ; CHECK-NEXT: ret void ; @@ -410,7 +389,6 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @foo() ; CHECK-NEXT: br i1 [[C1]], label [[CONT1:%.*]], label [[A1:%.*]] ; CHECK: a1: -; CHECK-NEXT: [[DEAD:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[CONT1]] ] ; CHECK-NEXT: call void @assert_fail_1(i32 0) ; CHECK-NEXT: unreachable ; CHECK: cont1: @@ -418,10 +396,7 @@ ; CHECK-NEXT: br i1 [[C2]], label [[CONT2:%.*]], label [[A1]] ; CHECK: cont2: ; CHECK-NEXT: [[C3:%.*]] = call i1 @foo() -; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A3:%.*]] -; CHECK: a3: -; CHECK-NEXT: call void @assert_fail_1(i32 0) -; CHECK-NEXT: unreachable +; CHECK-NEXT: br i1 [[C3]], label [[CONT3:%.*]], label [[A1]] ; CHECK: cont3: ; CHECK-NEXT: ret void ; @@ -451,14 +426,9 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[C:%.*]], metadata [[META5:![0-9]+]], metadata !DIExpression()), !dbg [[DBG7:![0-9]+]] ; CHECK-NEXT: switch i32 [[C]], label [[SW_EPILOG:%.*]] [ ; CHECK-NEXT: i32 13, label [[SW_BB:%.*]] -; CHECK-NEXT: i32 42, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 42, label [[SW_BB]] ; CHECK-NEXT: ] ; CHECK: sw.bb: -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 55, metadata [[META5]], metadata !DIExpression()), !dbg [[DBG7]] -; CHECK-NEXT: tail call void @abort() -; CHECK-NEXT: unreachable -; CHECK: sw.bb1: -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 67, metadata [[META5]], metadata !DIExpression()), !dbg [[DBG7]] ; CHECK-NEXT: tail call void @abort() ; CHECK-NEXT: unreachable ; CHECK: sw.epilog: @@ -491,18 +461,10 @@ ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[C:%.*]], metadata [[META5]], metadata !DIExpression()), !dbg [[DBG7]] ; CHECK-NEXT: switch i32 [[C]], label [[SW_EPILOG:%.*]] [ ; CHECK-NEXT: i32 13, label [[SW_BB:%.*]] -; CHECK-NEXT: i32 42, label [[SW_BB1:%.*]] -; CHECK-NEXT: i32 53, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 42, label [[SW_BB]] +; CHECK-NEXT: i32 53, label [[SW_BB]] ; CHECK-NEXT: ] ; CHECK: sw.bb: -; CHECK-NEXT: [[C_1:%.*]] = phi i32 [ 55, [[ENTRY:%.*]] ], [ 67, [[SW_BB1]] ] -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[C_1]], metadata [[META5]], metadata !DIExpression()), !dbg [[DBG7]] -; CHECK-NEXT: tail call void @abort() -; CHECK-NEXT: unreachable -; CHECK: sw.bb1: -; CHECK-NEXT: br label [[SW_BB]] -; CHECK: sw.bb2: -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 84, metadata [[META5]], metadata !DIExpression()), !dbg [[DBG7]] ; CHECK-NEXT: tail call void @abort() ; CHECK-NEXT: unreachable ; CHECK: sw.epilog: