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 @@ -20,6 +20,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -77,118 +78,113 @@ STATISTIC(NumSimpl, "Number of blocks simplified"); -/// If we have more than one empty (other than phi node) return blocks, -/// merge them together to promote recursive block merging. -static bool mergeEmptyReturnBlocks(Function &F, DomTreeUpdater *DTU) { - bool Changed = false; +static bool tailMergeBlocksWithSimilarFunctionTerminators(Function &F, + DomTreeUpdater *DTU) { + SmallMapVector, 4> + Structure; - std::vector Updates; - SmallVector DeadBlocks; - - BasicBlock *RetBlock = nullptr; - - // Scan all the blocks in the function, looking for empty return blocks. - for (BasicBlock &BB : make_early_inc_range(F)) { + // Scan all the blocks in the function, record the interesting-ones. + for (BasicBlock &BB : F) { if (DTU && DTU->isBBPendingDeletion(&BB)) continue; - // Only look at return blocks. - ReturnInst *Ret = dyn_cast(BB.getTerminator()); - if (!Ret) continue; - - // Only look at the block if it is empty or the only other thing in it is a - // single PHI node that is the operand to the return. - if (Ret != &BB.front()) { - // Check for something else in the block. - BasicBlock::iterator I(Ret); - --I; - // Skip over debug info. - while (isa(I) && I != BB.begin()) - --I; - if (!isa(I) && - (!isa(I) || I != BB.begin() || Ret->getNumOperands() == 0 || - Ret->getOperand(0) != &*I)) - continue; - } - - // If this is the first returning block, remember it and keep going. - if (!RetBlock) { - RetBlock = &BB; - continue; - } - - // Skip merging if this would result in a CallBr instruction with a - // duplicate destination. FIXME: See note in CodeGenPrepare.cpp. - bool SkipCallBr = false; - for (pred_iterator PI = pred_begin(&BB), E = pred_end(&BB); - PI != E && !SkipCallBr; ++PI) { - if (auto *CBI = dyn_cast((*PI)->getTerminator())) - for (unsigned i = 0, e = CBI->getNumSuccessors(); i != e; ++i) - if (RetBlock == CBI->getSuccessor(i)) { - SkipCallBr = true; - break; - } - } - if (SkipCallBr) + // We are only interested in function-terminating blocks. + if (!succ_empty(&BB)) + continue; + + auto *Term = BB.getTerminator(); + + // Fow now only support `ret` function terminators. + // FIXME: lift this restriction. + if (Term->getOpcode() != Instruction::Ret) + continue; + + // We can't tail-merge block that contains a musttail call. + if (BB.getTerminatingMustTailCall()) + continue; + + // Calls to experimental_deoptimize must be followed by a return + // of the value computed by experimental_deoptimize. + // I.e., we can not change `ret` to `br` for this block. + if (auto *CI = + dyn_cast_or_null(Term->getPrevNonDebugInstruction())) { + if (Function *F = CI->getCalledFunction()) + if (Intrinsic::ID ID = F->getIntrinsicID()) + if (ID == Intrinsic::experimental_deoptimize) + continue; + } + + // PHI nodes cannot have token type, so if the terminator has an operand + // with token type, we can not tail-merge this kind of function terminators. + if (any_of(Term->operands(), + [](Value *Op) { return Op->getType()->isTokenTy(); })) + continue; + + // Canonical blocks are uniqued based on the terminator type (opcode). + Structure[Term->getOpcode()].emplace_back(&BB); + } + + bool Changed = false; + + std::vector Updates; + + for (ArrayRef BBs : make_second_range(Structure)) { + BasicBlock *CanonicalBB = nullptr; + SmallVector Ops; + + // We don't want to change IR just because we can. + // Only do that if there are at least two blocks we'll tail-merge. + if (BBs.size() < 2) continue; - // Otherwise, we found a duplicate return block. Merge the two. Changed = true; - // Case when there is no input to the return or when the returned values - // agree is trivial. Note that they can't agree if there are phis in the - // blocks. - if (Ret->getNumOperands() == 0 || - Ret->getOperand(0) == - cast(RetBlock->getTerminator())->getOperand(0)) { - // All predecessors of BB should now branch to RetBlock instead. - if (DTU) { - SmallPtrSet PredsOfBB(pred_begin(&BB), pred_end(&BB)); - SmallPtrSet PredsOfRetBlock(pred_begin(RetBlock), - pred_end(RetBlock)); - Updates.reserve(Updates.size() + 2 * PredsOfBB.size()); - for (auto *Predecessor : PredsOfBB) - // But, iff Predecessor already branches to RetBlock, - // don't (re-)add DomTree edge, because it already exists. - if (!PredsOfRetBlock.contains(Predecessor)) - Updates.push_back({DominatorTree::Insert, Predecessor, RetBlock}); - for (auto *Predecessor : PredsOfBB) - Updates.push_back({DominatorTree::Delete, Predecessor, &BB}); - } - BB.replaceAllUsesWith(RetBlock); - DeadBlocks.emplace_back(&BB); - continue; - } - - // If the canonical return block has no PHI node, create one now. - PHINode *RetBlockPHI = dyn_cast(RetBlock->begin()); - if (!RetBlockPHI) { - Value *InVal = cast(RetBlock->getTerminator())->getOperand(0); - pred_iterator PB = pred_begin(RetBlock), PE = pred_end(RetBlock); - RetBlockPHI = PHINode::Create(Ret->getOperand(0)->getType(), - std::distance(PB, PE), "merge", - &RetBlock->front()); - - for (pred_iterator PI = PB; PI != PE; ++PI) - RetBlockPHI->addIncoming(InVal, *PI); - RetBlock->getTerminator()->setOperand(0, RetBlockPHI); - } - - // Turn BB into a block that just unconditionally branches to the return - // block. This handles the case when the two return blocks have a common - // predecessor but that return different things. - RetBlockPHI->addIncoming(Ret->getOperand(0), &BB); - BB.getTerminator()->eraseFromParent(); - BranchInst::Create(RetBlock, &BB); if (DTU) - Updates.push_back({DominatorTree::Insert, &BB, RetBlock}); + Updates.reserve(Updates.size() + BBs.size()); + + for (BasicBlock *BB : BBs) { + auto *Term = BB->getTerminator(); + + // Do we already have a canonical block for this function terminator type? + if (CanonicalBB == nullptr) { + // We do not. Create one now. + CanonicalBB = BasicBlock::Create( + F.getContext(), Twine("common.") + Term->getOpcodeName(), &F); + // We'll also need a PHI node per each operand of the terminator. + Ops.resize(Term->getNumOperands()); + for (auto I : zip(Term->operands(), Ops)) { + std::get<1>(I) = PHINode::Create(std::get<0>(I)->getType(), + /*NumReservedValues=*/BBs.size(), + CanonicalBB->getName() + ".op"); + CanonicalBB->getInstList().push_back(std::get<1>(I)); + } + // Make it so that this canonical block actually has the right + // terminator. + auto *CanonicalTerm = Term->clone(); + CanonicalBB->getInstList().push_back(CanonicalTerm); + // If the canonical terminator has operands, rewrite it to take PHI's. + for (auto I : zip(Ops, CanonicalTerm->operands())) + std::get<1>(I) = std::get<0>(I); + } + + // Aha, found a new non-canonical function terminator. + // If it has operands, forward them to the PHI nodes in the canonical + // block. + for (auto I : zip(Term->operands(), Ops)) + std::get<1>(I)->addIncoming(std::get<0>(I), BB); + + // And turn BB into a block that just unconditionally branches + // to the canonical block. + Term->eraseFromParent(); + BranchInst::Create(CanonicalBB, BB); + if (DTU) + Updates.push_back({DominatorTree::Insert, BB, CanonicalBB}); + } } if (DTU) DTU->applyUpdates(Updates); - DeleteDeadBlocks(DeadBlocks, DTU); - return Changed; } @@ -240,7 +236,8 @@ DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); bool EverChanged = removeUnreachableBlocks(F, DT ? &DTU : nullptr); - EverChanged |= mergeEmptyReturnBlocks(F, DT ? &DTU : nullptr); + EverChanged |= + tailMergeBlocksWithSimilarFunctionTerminators(F, DT ? &DTU : nullptr); EverChanged |= iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options); // If neither pass changed anything, we're done. diff --git a/llvm/test/CodeGen/AArch64/branch-relax-cbz.ll b/llvm/test/CodeGen/AArch64/branch-relax-cbz.ll --- a/llvm/test/CodeGen/AArch64/branch-relax-cbz.ll +++ b/llvm/test/CodeGen/AArch64/branch-relax-cbz.ll @@ -12,7 +12,7 @@ ; CHECK-NEXT: ldr w8, [x8] ; CHECK-NEXT: cbnz w8, LBB0_2 ; CHECK-NEXT: b LBB0_4 -; CHECK-NEXT: LBB0_2: ; %b8 +; CHECK-NEXT: LBB0_2: ; %common.ret ; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload ; CHECK-NEXT: ret ; CHECK-NEXT: LBB0_3: ; %b2 diff --git a/llvm/test/CodeGen/AArch64/cgp-usubo.ll b/llvm/test/CodeGen/AArch64/cgp-usubo.ll --- a/llvm/test/CodeGen/AArch64/cgp-usubo.ll +++ b/llvm/test/CodeGen/AArch64/cgp-usubo.ll @@ -126,10 +126,9 @@ ; CHECK-NEXT: tbz w3, #0, .LBB7_2 ; CHECK-NEXT: // %bb.1: // %t ; CHECK-NEXT: subs x8, x0, x1 -; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: cset w3, lo ; CHECK-NEXT: str x8, [x2] -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB7_2: // %f +; CHECK-NEXT: .LBB7_2: // %common.ret ; CHECK-NEXT: and w0, w3, #0x1 ; CHECK-NEXT: ret entry: @@ -151,30 +150,29 @@ define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) nounwind { ; CHECK-LABEL: usubo_ult_cmp_dominates_i64: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: str x30, [sp, #-48]! // 8-byte Folded Spill +; CHECK-NEXT: stp x30, x23, [sp, #-48]! // 16-byte Folded Spill ; CHECK-NEXT: stp x20, x19, [sp, #32] // 16-byte Folded Spill -; CHECK-NEXT: mov w20, w3 +; CHECK-NEXT: mov w19, w3 ; CHECK-NEXT: stp x22, x21, [sp, #16] // 16-byte Folded Spill ; CHECK-NEXT: tbz w3, #0, .LBB8_3 ; CHECK-NEXT: // %bb.1: // %t ; CHECK-NEXT: cmp x0, x1 -; CHECK-NEXT: mov x22, x0 -; CHECK-NEXT: cset w0, lo -; CHECK-NEXT: mov x19, x2 -; CHECK-NEXT: mov x21, x1 +; CHECK-NEXT: cset w21, lo +; CHECK-NEXT: mov x23, x0 +; CHECK-NEXT: mov w0, w21 +; CHECK-NEXT: mov x20, x2 +; CHECK-NEXT: mov x22, x1 ; CHECK-NEXT: bl call -; CHECK-NEXT: subs x8, x22, x21 +; CHECK-NEXT: subs x8, x23, x22 ; CHECK-NEXT: b.hs .LBB8_3 ; CHECK-NEXT: // %bb.2: // %end -; CHECK-NEXT: cset w0, lo -; CHECK-NEXT: str x8, [x19] -; CHECK-NEXT: b .LBB8_4 -; CHECK-NEXT: .LBB8_3: // %f -; CHECK-NEXT: and w0, w20, #0x1 -; CHECK-NEXT: .LBB8_4: // %f +; CHECK-NEXT: mov w19, w21 +; CHECK-NEXT: str x8, [x20] +; CHECK-NEXT: .LBB8_3: // %common.ret +; CHECK-NEXT: and w0, w19, #0x1 ; CHECK-NEXT: ldp x20, x19, [sp, #32] // 16-byte Folded Reload ; CHECK-NEXT: ldp x22, x21, [sp, #16] // 16-byte Folded Reload -; CHECK-NEXT: ldr x30, [sp], #48 // 8-byte Folded Reload +; CHECK-NEXT: ldp x30, x23, [sp], #48 // 16-byte Folded Reload ; CHECK-NEXT: ret entry: br i1 %cond, label %t, label %f diff --git a/llvm/test/CodeGen/AArch64/implicit-null-check.ll b/llvm/test/CodeGen/AArch64/implicit-null-check.ll --- a/llvm/test/CodeGen/AArch64/implicit-null-check.ll +++ b/llvm/test/CodeGen/AArch64/implicit-null-check.ll @@ -13,7 +13,7 @@ ; CHECK-NEXT: ldr w0, [x0] // on-fault: .LBB0_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB0_2: // %is_null +; CHECK-NEXT: .LBB0_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -36,7 +36,7 @@ ; CHECK-NEXT: ldr w0, [x0] // on-fault: .LBB1_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_2: // %is_null +; CHECK-NEXT: .LBB1_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -58,7 +58,7 @@ ; CHECK-NEXT: ldr w0, [x0] // on-fault: .LBB2_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB2_2: // %is_null +; CHECK-NEXT: .LBB2_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -83,7 +83,7 @@ ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ldar w0, [x0] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB3_2: // %is_null +; CHECK-NEXT: .LBB3_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -106,7 +106,7 @@ ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB4_2: // %is_null +; CHECK-NEXT: .LBB4_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -129,7 +129,7 @@ ; CHECK-NEXT: ldrb w0, [x0] // on-fault: .LBB5_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB5_2: // %is_null +; CHECK-NEXT: .LBB5_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -149,15 +149,14 @@ ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cbz x0, .LBB6_2 ; CHECK-NEXT: // %bb.1: // %not_null -; CHECK-NEXT: ldp x8, x1, [x0] ; CHECK-NEXT: ldp x2, x3, [x0, #16] -; CHECK-NEXT: mov x0, x8 +; CHECK-NEXT: ldp x0, x1, [x0] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB6_2: // %is_null -; CHECK-NEXT: mov w0, #42 +; CHECK-NEXT: .LBB6_2: ; CHECK-NEXT: mov x1, xzr ; CHECK-NEXT: mov x2, xzr ; CHECK-NEXT: mov x3, xzr +; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: %c = icmp eq i256* %x, null @@ -180,7 +179,7 @@ ; CHECK-NEXT: ldr w0, [x0, #128] // on-fault: .LBB7_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB7_2: // %is_null +; CHECK-NEXT: .LBB7_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -204,7 +203,7 @@ ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: add w0, w8, w1 ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB8_2: // %is_null +; CHECK-NEXT: .LBB8_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -231,7 +230,7 @@ ; CHECK-NEXT: udiv w9, w1, w2 ; CHECK-NEXT: add w0, w8, w9 ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB9_2: // %is_null +; CHECK-NEXT: .LBB9_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -260,7 +259,7 @@ ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: str w8, [x2] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB10_2: // %is_null +; CHECK-NEXT: .LBB10_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -287,7 +286,7 @@ ; CHECK-NEXT: add w8, w9, w8 ; CHECK-NEXT: add w0, w8, #4 // =4 ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB11_2: // %is_null +; CHECK-NEXT: .LBB11_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -316,7 +315,7 @@ ; CHECK-NEXT: dmb ishld ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB12_2: // %is_null +; CHECK-NEXT: .LBB12_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -342,7 +341,7 @@ ; CHECK-NEXT: dmb ish ; CHECK-NEXT: ldr w0, [x0] ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB13_2: // %is_null +; CHECK-NEXT: .LBB13_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: @@ -366,8 +365,7 @@ ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: mov w8, #1 ; CHECK-NEXT: str w8, [x0] -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB14_2: // %is_null +; CHECK-NEXT: .LBB14_2: // %common.ret ; CHECK-NEXT: ret entry: %c = icmp eq i32* %x, null @@ -389,8 +387,7 @@ ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: mov w8, #1 ; CHECK-NEXT: str w8, [x0] -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB15_2: // %is_null +; CHECK-NEXT: .LBB15_2: // %common.ret ; CHECK-NEXT: ret entry: %c = icmp eq i32* %x, null @@ -411,7 +408,7 @@ ; CHECK-NEXT: ldur w0, [x0, #-128] // on-fault: .LBB16_2 ; CHECK-NEXT: // %bb.1: // %not_null ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB16_2: // %is_null +; CHECK-NEXT: .LBB16_2: ; CHECK-NEXT: mov w0, #42 ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/ldst-opt-after-block-placement.ll b/llvm/test/CodeGen/AArch64/ldst-opt-after-block-placement.ll --- a/llvm/test/CodeGen/AArch64/ldst-opt-after-block-placement.ll +++ b/llvm/test/CodeGen/AArch64/ldst-opt-after-block-placement.ll @@ -20,7 +20,7 @@ ; CHECK-NEXT: b.ge .LBB0_4 ; CHECK-NEXT: .LBB0_3: // %exit1 ; CHECK-NEXT: str xzr, [x1, #8] -; CHECK-NEXT: .LBB0_4: // %exit2 +; CHECK-NEXT: .LBB0_4: // %common.ret ; CHECK-NEXT: ret entry: br i1 %cond, label %if.then, label %if.else diff --git a/llvm/test/CodeGen/AArch64/ldst-paired-aliasing.ll b/llvm/test/CodeGen/AArch64/ldst-paired-aliasing.ll --- a/llvm/test/CodeGen/AArch64/ldst-paired-aliasing.ll +++ b/llvm/test/CodeGen/AArch64/ldst-paired-aliasing.ll @@ -32,7 +32,7 @@ ; CHECK-NEXT: b .LBB0_3 ; CHECK-NEXT: .LBB0_2: // %if.then ; CHECK-NEXT: bl f2 -; CHECK-NEXT: .LBB0_3: // %for.inc +; CHECK-NEXT: .LBB0_3: // %common.ret ; CHECK-NEXT: ldr x30, [sp, #96] // 8-byte Folded Reload ; CHECK-NEXT: mov w0, wzr ; CHECK-NEXT: add sp, sp, #112 // =112 diff --git a/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll b/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll --- a/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll +++ b/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll @@ -147,11 +147,11 @@ ; CHECK-NEXT: mov w19, w0 ; CHECK-NEXT: ldr x0, [sp, #8] ; CHECK-NEXT: bl consume -; CHECK-NEXT: and w0, w19, #0x1 ; CHECK-NEXT: b .LBB8_3 -; CHECK-NEXT: .LBB8_2: // %right -; CHECK-NEXT: mov w0, #1 -; CHECK-NEXT: .LBB8_3: // %right +; CHECK-NEXT: .LBB8_2: +; CHECK-NEXT: mov w19, #1 +; CHECK-NEXT: .LBB8_3: // %common.ret +; CHECK-NEXT: and w0, w19, #0x1 ; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload ; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll b/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll --- a/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll +++ b/llvm/test/CodeGen/AArch64/use-cr-result-of-dom-icmp-st.ll @@ -19,13 +19,9 @@ ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 ; CHECK-NEXT: cmn x8, #2 // =2 -; CHECK-NEXT: b.le .LBB0_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB0_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -46,14 +42,11 @@ ; CHECK-LABEL: ll_a_op_b__1: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 -; CHECK-NEXT: tbnz x8, #63, .LBB1_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_2: // %if.end ; CHECK-NEXT: cmn x8, #1 // =1 -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x9, x1, xzr, eq +; CHECK-NEXT: mul x9, x9, x0 +; CHECK-NEXT: cmp x8, #0 // =0 +; CHECK-NEXT: csel x0, x1, x9, ge ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -75,13 +68,9 @@ ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 ; CHECK-NEXT: cmp x8, #0 // =0 -; CHECK-NEXT: b.le .LBB2_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB2_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -103,13 +92,9 @@ ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 ; CHECK-NEXT: cmp x8, #1 // =1 -; CHECK-NEXT: b.le .LBB3_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB3_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -131,13 +116,9 @@ ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: lsl x8, x0, x1 ; CHECK-NEXT: cmp x8, #2 // =2 -; CHECK-NEXT: b.le .LBB4_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB4_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %shl = shl i64 %a, %b @@ -158,13 +139,9 @@ ; CHECK-LABEL: ll_a__2: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmn x0, #2 // =2 -; CHECK-NEXT: b.le .LBB5_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB5_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, -2 @@ -183,14 +160,11 @@ define i64 @ll_a__1(i64 %a, i64 %b) { ; CHECK-LABEL: ll_a__1: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: tbnz x0, #63, .LBB6_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB6_2: // %if.end ; CHECK-NEXT: cmn x0, #1 // =1 -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: cmp x0, #0 // =0 +; CHECK-NEXT: csel x0, x1, x8, ge ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, -1 @@ -210,13 +184,9 @@ ; CHECK-LABEL: ll_a_0: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmp x0, #0 // =0 -; CHECK-NEXT: b.le .LBB7_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB7_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, 0 @@ -236,13 +206,9 @@ ; CHECK-LABEL: ll_a_1: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmp x0, #1 // =1 -; CHECK-NEXT: b.le .LBB8_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB8_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, 1 @@ -262,13 +228,9 @@ ; CHECK-LABEL: ll_a_2: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: cmp x0, #2 // =2 -; CHECK-NEXT: b.le .LBB9_2 -; CHECK-NEXT: // %bb.1: // %return -; CHECK-NEXT: mov x0, x1 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB9_2: // %if.end -; CHECK-NEXT: csinc x8, x1, xzr, ge -; CHECK-NEXT: mul x0, x8, x0 +; CHECK-NEXT: csinc x8, x1, xzr, eq +; CHECK-NEXT: mul x8, x8, x0 +; CHECK-NEXT: csel x0, x1, x8, gt ; CHECK-NEXT: ret entry: %cmp = icmp sgt i64 %a, 2 diff --git a/llvm/test/CodeGen/AArch64/vec-extract-branch.ll b/llvm/test/CodeGen/AArch64/vec-extract-branch.ll --- a/llvm/test/CodeGen/AArch64/vec-extract-branch.ll +++ b/llvm/test/CodeGen/AArch64/vec-extract-branch.ll @@ -14,7 +14,7 @@ ; CHECK-NEXT: mov w8, #42 ; CHECK-NEXT: sdiv w0, w8, w0 ; CHECK-NEXT: ret -; CHECK-NEXT: .LBB0_2: // %false +; CHECK-NEXT: .LBB0_2: ; CHECK-NEXT: mov w0, #88 ; CHECK-NEXT: ret %t1 = fcmp ogt <2 x double> %x, zeroinitializer diff --git a/llvm/test/Transforms/LoopUnroll/ARM/upperbound.ll b/llvm/test/Transforms/LoopUnroll/ARM/upperbound.ll --- a/llvm/test/Transforms/LoopUnroll/ARM/upperbound.ll +++ b/llvm/test/Transforms/LoopUnroll/ARM/upperbound.ll @@ -75,13 +75,10 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[L86_OFF:%.*]] = add i32 [[L86:%.*]], -1 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[L86_OFF]], 24 -; CHECK-NEXT: br i1 [[SWITCH]], label [[FOR_END_I_IF_END8_I_CRIT_EDGE_I:%.*]], label [[FOR_INC_I_3_I_5:%.*]] -; CHECK: for.end.i.if.end8.i_crit_edge.i: -; CHECK-NEXT: ret i32 0 -; CHECK: for.inc.i.3.i.5: ; CHECK-NEXT: [[DOTNOT30:%.*]] = icmp ne i32 [[L86]], 25 ; CHECK-NEXT: [[SPEC_SELECT24:%.*]] = zext i1 [[DOTNOT30]] to i32 -; CHECK-NEXT: ret i32 [[SPEC_SELECT24]] +; CHECK-NEXT: [[COMMON_RET31_OP:%.*]] = select i1 [[SWITCH]], i32 0, i32 [[SPEC_SELECT24]] +; CHECK-NEXT: ret i32 [[COMMON_RET31_OP]] ; entry: br label %for.body.i.i diff --git a/llvm/test/Transforms/PGOProfile/chr.ll b/llvm/test/Transforms/PGOProfile/chr.ll --- a/llvm/test/Transforms/PGOProfile/chr.ll +++ b/llvm/test/Transforms/PGOProfile/chr.ll @@ -392,7 +392,7 @@ ; CHECK-NEXT: br i1 [[TMP2]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_NONCHR:%.*]], !prof [[PROF15]] ; CHECK: entry.split: ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[SUM0:%.*]], 85 -; CHECK-NEXT: ret i32 [[TMP3]] +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: entry.split.nonchr: ; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[SUM0]], 42 ; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP0]], 1 @@ -402,7 +402,10 @@ ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP6]], 0 ; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[SUM1_NONCHR]], 43 ; CHECK-NEXT: [[SUM2_NONCHR:%.*]] = select i1 [[TMP7]], i32 [[SUM1_NONCHR]], i32 [[TMP8]], !prof [[PROF16]] -; CHECK-NEXT: ret i32 [[SUM2_NONCHR]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP3]], [[ENTRY_SPLIT]] ], [ [[SUM2_NONCHR]], [[ENTRY_SPLIT_NONCHR]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: %0 = load i32, i32* %i @@ -2012,10 +2015,12 @@ ; CHECK: bb0.split: ; CHECK-NEXT: [[V299:%.*]] = mul i64 [[V2]], 7860086430977039991 ; CHECK-NEXT: store i64 [[V299]], i64* [[J:%.*]], align 4 -; CHECK-NEXT: ret i64 99 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: bb0.split.nonchr: ; CHECK-NEXT: [[V299_NONCHR:%.*]] = mul i64 [[V2]], 7860086430977039991 ; CHECK-NEXT: store i64 [[V299_NONCHR]], i64* [[J]], align 4 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret i64 99 ; bb0: diff --git a/llvm/test/Transforms/PhaseOrdering/X86/simplifycfg-late.ll b/llvm/test/Transforms/PhaseOrdering/X86/simplifycfg-late.ll --- a/llvm/test/Transforms/PhaseOrdering/X86/simplifycfg-late.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/simplifycfg-late.ll @@ -11,14 +11,15 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = add i32 [[C:%.*]], -42 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7 -; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] ; CHECK: switch.lookup: ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[SWITCH_TABLEIDX]] to i64 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i64 0, i64 [[TMP1]] ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 -; CHECK-NEXT: ret i32 [[SWITCH_LOAD]] -; CHECK: return: -; CHECK-NEXT: ret i32 15 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 15, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: switch i32 %c, label %sw.default [ diff --git a/llvm/test/Transforms/PhaseOrdering/X86/vector-reductions.ll b/llvm/test/Transforms/PhaseOrdering/X86/vector-reductions.ll --- a/llvm/test/Transforms/PhaseOrdering/X86/vector-reductions.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/vector-reductions.ll @@ -292,14 +292,15 @@ ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[DIV]], 0x3EB0C6F7A0B5ED8D ; CHECK-NEXT: [[CMP4:%.*]] = fcmp olt double [[DIV3]], 0x3EB0C6F7A0B5ED8D ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP4]], i1 false -; CHECK-NEXT: br i1 [[OR_COND]], label [[CLEANUP:%.*]], label [[LOR_LHS_FALSE:%.*]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[COMMON_RET:%.*]], label [[LOR_LHS_FALSE:%.*]] ; CHECK: lor.lhs.false: ; CHECK-NEXT: [[CMP5:%.*]] = fcmp ule double [[DIV]], 1.000000e+00 ; CHECK-NEXT: [[CMP7:%.*]] = fcmp ule double [[DIV3]], 1.000000e+00 ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[CMP5]], i1 true, i1 [[CMP7]] -; CHECK-NEXT: ret i1 [[OR_COND1]] -; CHECK: cleanup: -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[OR_COND1]], [[LOR_LHS_FALSE]] ], [ false, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i1 [[COMMON_RET_OP]] ; entry: %fneg = fneg double %b diff --git a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll --- a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll +++ b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll @@ -16,31 +16,28 @@ define void @caller1(i1 %c, i64* align 1 %ptr) { ; ASSUMPTIONS-OFF-LABEL: @caller1( -; ASSUMPTIONS-OFF-NEXT: br i1 [[C:%.*]], label [[TRUE2:%.*]], label [[FALSE2:%.*]] -; ASSUMPTIONS-OFF: true2: -; ASSUMPTIONS-OFF-NEXT: store volatile i64 0, i64* [[PTR:%.*]], align 8 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 2, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: ret void +; ASSUMPTIONS-OFF-NEXT: br i1 [[C:%.*]], label [[COMMON_RET:%.*]], label [[FALSE2:%.*]] ; ASSUMPTIONS-OFF: false2: -; ASSUMPTIONS-OFF-NEXT: store volatile i64 1, i64* [[PTR]], align 4 +; ASSUMPTIONS-OFF-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 4 +; ASSUMPTIONS-OFF-NEXT: br label [[COMMON_RET]] +; ASSUMPTIONS-OFF: common.ret: +; ASSUMPTIONS-OFF-NEXT: [[DOTSINK:%.*]] = phi i64 [ 3, [[FALSE2]] ], [ 2, [[TMP0:%.*]] ] ; ASSUMPTIONS-OFF-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 ; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 ; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 ; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 ; ASSUMPTIONS-OFF-NEXT: store volatile i64 -1, i64* [[PTR]], align 4 -; ASSUMPTIONS-OFF-NEXT: store volatile i64 3, i64* [[PTR]], align 4 +; ASSUMPTIONS-OFF-NEXT: store volatile i64 [[DOTSINK]], i64* [[PTR]], align 4 ; ASSUMPTIONS-OFF-NEXT: ret void ; ; ASSUMPTIONS-ON-LABEL: @caller1( -; ASSUMPTIONS-ON-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]] +; ASSUMPTIONS-ON-NEXT: br i1 [[C:%.*]], label [[COMMON_RET:%.*]], label [[FALSE1:%.*]] ; ASSUMPTIONS-ON: false1: ; ASSUMPTIONS-ON-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 8 +; ASSUMPTIONS-ON-NEXT: br label [[COMMON_RET]] +; ASSUMPTIONS-ON: common.ret: +; ASSUMPTIONS-ON-NEXT: [[DOTSINK:%.*]] = phi i64 [ 3, [[FALSE1]] ], [ 2, [[TMP0:%.*]] ] ; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] ; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 @@ -48,17 +45,7 @@ ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 3, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: ret void -; ASSUMPTIONS-ON: true2.critedge: -; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] -; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 -; ASSUMPTIONS-ON-NEXT: store volatile i64 2, i64* [[PTR]], align 8 +; ASSUMPTIONS-ON-NEXT: store volatile i64 [[DOTSINK]], i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: ret void ; br i1 %c, label %true1, label %false1 diff --git a/llvm/test/Transforms/PruneEH/ipo-nounwind.ll b/llvm/test/Transforms/PruneEH/ipo-nounwind.ll --- a/llvm/test/Transforms/PruneEH/ipo-nounwind.ll +++ b/llvm/test/Transforms/PruneEH/ipo-nounwind.ll @@ -30,17 +30,6 @@ } define i32 @caller(i32* %ptr) personality i32 3 { -; CHECK-LABEL: @caller( -; CHECK-NEXT: entry: -; CHECK-NEXT: invoke void @callee(i32* [[PTR:%.*]]) -; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[UNWIND:%.*]] -; CHECK: normal: -; CHECK-NEXT: ret i32 1 -; CHECK: unwind: -; CHECK-NEXT: [[RES:%.*]] = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: ret i32 2 -; entry: invoke void @callee(i32* %ptr) diff --git a/llvm/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch.ll b/llvm/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch.ll --- a/llvm/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch.ll +++ b/llvm/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch.ll @@ -70,10 +70,10 @@ ; Test folding switch -> branch define i32 @test4(i32 %C) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: L1: +; CHECK-NEXT: common.ret: ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C:%.*]], 0 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 1, i32 0 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 1, i32 0 +; CHECK-NEXT: ret i32 [[DOT]] ; switch i32 %C, label %L1 [ i32 0, label %L2 @@ -87,10 +87,10 @@ ; Can fold into a cond branch! define i32 @test5(i32 %C) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: L1: +; CHECK-NEXT: common.ret: ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C:%.*]], 0 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 1, i32 0 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 1, i32 0 +; CHECK-NEXT: ret i32 [[DOT]] ; switch i32 %C, label %L1 [ i32 0, label %L2 diff --git a/llvm/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll b/llvm/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll --- a/llvm/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll +++ b/llvm/test/Transforms/SimplifyCFG/ConditionalTrappingConstantExpr.ll @@ -9,14 +9,13 @@ define i32 @admiral(i32 %a, i32 %b) { ; CHECK-LABEL: @admiral( ; CHECK-NEXT: [[C:%.*]] = icmp sle i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: br i1 [[C]], label [[BB2:%.*]], label [[BB1:%.*]] +; CHECK-NEXT: br i1 [[C]], label [[COMMON_RET:%.*]], label [[BB1:%.*]] ; CHECK: bb1: ; CHECK-NEXT: [[D:%.*]] = icmp sgt i32 sdiv (i32 -32768, i32 ptrtoint (i32* @G to i32)), 0 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[D]], i32 927, i32 42 -; CHECK-NEXT: br label [[BB2]] -; CHECK: bb2: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 42, [[TMP0:%.*]] ], [ [[SPEC_SELECT]], [[BB1]] ] -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK: common.ret: +; CHECK-NEXT: ret i32 42 ; %c = icmp sle i32 %a, %b br i1 %c, label %bb2, label %bb1 @@ -31,13 +30,12 @@ define i32 @ackbar(i1 %c) { ; CHECK-LABEL: @ackbar( -; CHECK-NEXT: br i1 [[C:%.*]], label [[BB5:%.*]], label [[BB6:%.*]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[BB5:%.*]], label [[COMMON_RET:%.*]] ; CHECK: bb5: ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 icmp sgt (i32 sdiv (i32 32767, i32 ptrtoint (i32* @G to i32)), i32 0), i32 42, i32 927 -; CHECK-NEXT: br label [[BB6]] -; CHECK: bb6: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 42, [[TMP0:%.*]] ], [ [[SPEC_SELECT]], [[BB5]] ] -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK: common.ret: +; CHECK-NEXT: ret i32 42 ; br i1 %c, label %bb5, label %bb6 bb5: @@ -52,10 +50,11 @@ define i32 @tarp(i1 %c) { ; CHECK-LABEL: @tarp( -; CHECK-NEXT: bb9: -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 fcmp oeq (float fdiv (float 3.000000e+00, float sitofp (i32 ptrtoint (i32* @G to i32) to float)), float 1.000000e+00), i32 42, i32 927 -; CHECK-NEXT: [[MERGE:%.*]] = select i1 [[C:%.*]], i32 [[SPEC_SELECT]], i32 42 -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: common.ret: +; CHECK-NEXT: [[C_NOT:%.*]] = xor i1 [[C:%.*]], true +; CHECK-NEXT: [[BRMERGE:%.*]] = or i1 [[C_NOT]], fcmp oeq (float fdiv (float 3.000000e+00, float sitofp (i32 ptrtoint (i32* @G to i32) to float)), float 1.000000e+00) +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[BRMERGE]], i32 42, i32 927 +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; br i1 %c, label %bb8, label %bb9 bb8: diff --git a/llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll b/llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll --- a/llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll +++ b/llvm/test/Transforms/SimplifyCFG/DeadSetCC.ll @@ -15,9 +15,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[L2:%.*]], label [[L1:%.*]] ; CHECK: L1: ; CHECK-NEXT: call void @foo() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: L2: ; CHECK-NEXT: call void @bar() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C = icmp eq i32 %V, 18 diff --git a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase-2.ll b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase-2.ll --- a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase-2.ll +++ b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase-2.ll @@ -13,7 +13,7 @@ ; CHECK-NEXT: to label [[BB14:%.*]] unwind label [[BB21:%.*]] ; CHECK: bb14: ; CHECK-NEXT: [[I0:%.*]] = invoke i16 @baz() -; CHECK-NEXT: to label [[BB15:%.*]] unwind label [[BB25:%.*]] +; CHECK-NEXT: to label [[BB15:%.*]] unwind label [[BB21]] ; CHECK: bb15: ; CHECK-NEXT: switch i16 [[I0]], label [[BB19:%.*]] [ ; CHECK-NEXT: i16 42, label [[BB23:%.*]] @@ -21,22 +21,18 @@ ; CHECK-NEXT: ] ; CHECK: bb19: ; CHECK-NEXT: invoke void @snork() -; CHECK-NEXT: to label [[BB20:%.*]] unwind label [[BB25]] +; CHECK-NEXT: to label [[BB20:%.*]] unwind label [[BB21]] ; CHECK: bb20: ; CHECK-NEXT: unreachable ; CHECK: bb21: ; CHECK-NEXT: [[I22:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: bb23: ; CHECK-NEXT: invoke void @spam() -; CHECK-NEXT: to label [[BB24:%.*]] unwind label [[BB25]] -; CHECK: bb24: +; CHECK-NEXT: to label [[COMMON_RET]] unwind label [[BB21]] +; CHECK: common.ret: ; CHECK-NEXT: ret void -; CHECK: bb25: -; CHECK-NEXT: [[I26:%.*]] = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: br label [[BB24]] ; bb: invoke void @widget() diff --git a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase.ll b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase.ll --- a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase.ll +++ b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-domtree-preservation-edgecase.ll @@ -4,19 +4,19 @@ define dso_local i32 @readCBPandCoeffsFromNAL(i1 %c, i32 %x, i32 %y) local_unnamed_addr { ; CHECK-LABEL: @readCBPandCoeffsFromNAL( ; CHECK-NEXT: if.end: -; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_END80:%.*]], label [[IF_THEN64:%.*]] -; CHECK: if.then64: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[Y:%.*]], [[IF_END:%.*]] ], [ 1, [[IF_END172237:%.*]] ], [ 0, [[IF_END80]] ], [ 0, [[IF_END80]] ] -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_END80:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if.end80: ; CHECK-NEXT: switch i32 [[X:%.*]], label [[INFLOOP:%.*]] [ -; CHECK-NEXT: i32 10, label [[IF_END172237]] +; CHECK-NEXT: i32 10, label [[IF_END172237:%.*]] ; CHECK-NEXT: i32 14, label [[IF_END172237]] -; CHECK-NEXT: i32 9, label [[IF_THEN64]] -; CHECK-NEXT: i32 12, label [[IF_THEN64]] +; CHECK-NEXT: i32 9, label [[COMMON_RET]] +; CHECK-NEXT: i32 12, label [[COMMON_RET]] ; CHECK-NEXT: ] ; CHECK: if.end172237: -; CHECK-NEXT: br label [[IF_THEN64]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[Y:%.*]], [[IF_END:%.*]] ], [ 1, [[IF_END172237]] ], [ 0, [[IF_END80]] ], [ 0, [[IF_END80]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; CHECK: infloop: ; CHECK-NEXT: br label [[INFLOOP]] ; diff --git a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-no-new-successors.ll b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-no-new-successors.ll --- a/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-no-new-successors.ll +++ b/llvm/test/Transforms/SimplifyCFG/FoldValueComparisonIntoPredecessors-no-new-successors.ll @@ -5,8 +5,8 @@ ; CHECK-LABEL: @widget( ; CHECK-NEXT: bb: ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[ARG:%.*]], 2 -; CHECK-NEXT: br i1 [[SWITCH]], label [[BB2:%.*]], label [[INFLOOP:%.*]] -; CHECK: bb2: +; CHECK-NEXT: br i1 [[SWITCH]], label [[COMMON_RET:%.*]], label [[INFLOOP:%.*]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; CHECK: infloop: ; CHECK-NEXT: br label [[INFLOOP]] diff --git a/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll b/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll --- a/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll +++ b/llvm/test/Transforms/SimplifyCFG/Hexagon/switch-to-lookup-table.ll @@ -11,13 +11,14 @@ ; ENABLE-LABEL: @foo( ; ENABLE-NEXT: entry: ; ENABLE-NEXT: [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 6 -; ENABLE-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]] +; ENABLE-NEXT: br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] ; ENABLE: switch.lookup: ; ENABLE-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @switch.table.foo, i32 0, i32 [[X]] ; ENABLE-NEXT: [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4 -; ENABLE-NEXT: ret i32 [[SWITCH_LOAD]] -; ENABLE: return: -; ENABLE-NEXT: ret i32 19 +; ENABLE-NEXT: br label [[COMMON_RET]] +; ENABLE: common.ret: +; ENABLE-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 19, [[ENTRY:%.*]] ] +; ENABLE-NEXT: ret i32 [[COMMON_RET_OP]] ; ; DISABLE-LABEL: @foo( ; DISABLE-NEXT: entry: diff --git a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll --- a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll +++ b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll @@ -4,6 +4,7 @@ define void @foo(i1 %C, i32* %P) { ; CHECK-LABEL: @foo( +; CHECK-NEXT: common.ret: ; CHECK-NEXT: store i32 7, i32* [[P:%.*]], align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimplifyCFG/SimplifyEqualityComparisonWithOnlyPredecessor-domtree-preservation-edgecase.ll b/llvm/test/Transforms/SimplifyCFG/SimplifyEqualityComparisonWithOnlyPredecessor-domtree-preservation-edgecase.ll --- a/llvm/test/Transforms/SimplifyCFG/SimplifyEqualityComparisonWithOnlyPredecessor-domtree-preservation-edgecase.ll +++ b/llvm/test/Transforms/SimplifyCFG/SimplifyEqualityComparisonWithOnlyPredecessor-domtree-preservation-edgecase.ll @@ -10,17 +10,17 @@ ; CHECK-NEXT: [[C1_NOT:%.*]] = xor i1 [[C1:%.*]], true ; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[C0_NOT]], i1 true, i1 [[C1_NOT]] ; CHECK-NEXT: [[R0_MUX:%.*]] = select i1 [[C0_NOT]], i32 [[R0:%.*]], i32 [[R1:%.*]] -; CHECK-NEXT: br i1 [[BRMERGE]], label [[IF_THEN:%.*]], label [[DO_BODY:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[R0_MUX]], [[ENTRY:%.*]] ], [ [[R1]], [[DO_BODY]] ] -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: br i1 [[BRMERGE]], label [[COMMON_RET:%.*]], label [[DO_BODY:%.*]] ; CHECK: do.body: ; CHECK-NEXT: call void @zzz() -; CHECK-NEXT: switch i32 [[V:%.*]], label [[IF_THEN]] [ +; CHECK-NEXT: switch i32 [[V:%.*]], label [[COMMON_RET]] [ ; CHECK-NEXT: i32 10, label [[DO_BODY]] ; CHECK-NEXT: i32 32, label [[DO_BODY]] ; CHECK-NEXT: i32 9, label [[DO_BODY]] ; CHECK-NEXT: ] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[R0_MUX]], [[ENTRY:%.*]] ], [ [[R1]], [[DO_BODY]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: br i1 %c0, label %if.end, label %if.then diff --git a/llvm/test/Transforms/SimplifyCFG/basictest.ll b/llvm/test/Transforms/SimplifyCFG/basictest.ll --- a/llvm/test/Transforms/SimplifyCFG/basictest.ll +++ b/llvm/test/Transforms/SimplifyCFG/basictest.ll @@ -34,11 +34,11 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[A]], 0 ; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[OR_COND]], label [[ELSE:%.*]], label [[UNTAKEN:%.*]] +; CHECK-NEXT: br i1 [[OR_COND]], label [[ELSE:%.*]], label [[COMMON_RET:%.*]] ; CHECK: else: ; CHECK-NEXT: call void @foo() -; CHECK-NEXT: ret void -; CHECK: untaken: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp1 = icmp eq i32 %a, %b @@ -84,6 +84,7 @@ ; PR5795 define void @test5(i32 %A) { ; CHECK-LABEL: @test5( +; CHECK-NEXT: common.ret: ; CHECK-NEXT: ret void ; switch i32 %A, label %return [ diff --git a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll --- a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll +++ b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll @@ -6,11 +6,11 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true ; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[A_NOT]], i1 true, i1 [[B:%.*]] -; CHECK-NEXT: br i1 [[BRMERGE]], label [[B:%.*]], label [[C:%.*]] +; CHECK-NEXT: br i1 [[BRMERGE]], label [[B:%.*]], label [[COMMON_RET:%.*]] ; CHECK: b: ; CHECK-NEXT: store i32 123, i32* [[P:%.*]], align 4 -; CHECK-NEXT: ret void -; CHECK: c: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimplifyCFG/duplicate-landingpad.ll b/llvm/test/Transforms/SimplifyCFG/duplicate-landingpad.ll --- a/llvm/test/Transforms/SimplifyCFG/duplicate-landingpad.ll +++ b/llvm/test/Transforms/SimplifyCFG/duplicate-landingpad.ll @@ -13,13 +13,13 @@ ; CHECK-NEXT: to label [[INVOKE2:%.*]] unwind label [[LPAD2:%.*]] ; CHECK: invoke2: ; CHECK-NEXT: invoke void @fn() -; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD2]] -; CHECK: invoke.cont: -; CHECK-NEXT: ret void +; CHECK-NEXT: to label [[COMMON_RET:%.*]] unwind label [[LPAD2]] ; CHECK: lpad2: ; CHECK-NEXT: [[EXN2:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup ; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -56,9 +56,7 @@ ; CHECK-NEXT: to label [[INVOKE2:%.*]] unwind label [[LPAD1:%.*]] ; CHECK: invoke2: ; CHECK-NEXT: invoke void @fn() -; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD2:%.*]] -; CHECK: invoke.cont: -; CHECK-NEXT: ret void +; CHECK-NEXT: to label [[COMMON_RET:%.*]] unwind label [[LPAD2:%.*]] ; CHECK: lpad1: ; CHECK-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: filter [0 x i8*] zeroinitializer @@ -70,6 +68,8 @@ ; CHECK-NEXT: br label [[SHARED_RESUME]] ; CHECK: shared_resume: ; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -107,9 +107,7 @@ ; CHECK-NEXT: to label [[INVOKE2:%.*]] unwind label [[LPAD1:%.*]] ; CHECK: invoke2: ; CHECK-NEXT: invoke void @fn() -; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD2:%.*]] -; CHECK: invoke.cont: -; CHECK-NEXT: ret void +; CHECK-NEXT: to label [[COMMON_RET:%.*]] unwind label [[LPAD2:%.*]] ; CHECK: lpad1: ; CHECK-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: filter [0 x i8*] zeroinitializer @@ -120,6 +118,8 @@ ; CHECK-NEXT: br label [[SHARED_RESUME]] ; CHECK: shared_resume: ; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-two-preds-cost.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-two-preds-cost.ll --- a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-two-preds-cost.ll +++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-two-preds-cost.ll @@ -28,9 +28,11 @@ ; THR1-NEXT: br i1 [[C3]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; THR1: final_left: ; THR1-NEXT: call void @sideeffect0() -; THR1-NEXT: ret void +; THR1-NEXT: br label [[COMMON_RET:%.*]] ; THR1: final_right: ; THR1-NEXT: call void @sideeffect1() +; THR1-NEXT: br label [[COMMON_RET]] +; THR1: common.ret: ; THR1-NEXT: ret void ; ; THR2-LABEL: @two_preds_with_extra_op( @@ -51,9 +53,11 @@ ; THR2-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; THR2: final_left: ; THR2-NEXT: call void @sideeffect0() -; THR2-NEXT: ret void +; THR2-NEXT: br label [[COMMON_RET:%.*]] ; THR2: final_right: ; THR2-NEXT: call void @sideeffect1() +; THR2-NEXT: br label [[COMMON_RET]] +; THR2: common.ret: ; THR2-NEXT: ret void ; entry: @@ -101,9 +105,11 @@ ; ALL-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; ALL: final_left: ; ALL-NEXT: call void @sideeffect0() -; ALL-NEXT: ret void +; ALL-NEXT: br label [[COMMON_RET:%.*]] ; ALL: final_right: ; ALL-NEXT: call void @sideeffect1() +; ALL-NEXT: br label [[COMMON_RET]] +; ALL: common.ret: ; ALL-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll --- a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll +++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll @@ -18,9 +18,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -54,9 +56,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -91,9 +95,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -130,9 +136,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -169,9 +177,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -211,9 +221,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -252,9 +264,11 @@ ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -284,9 +298,11 @@ ; CHECK-NEXT: call void @sideeffect0() ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -325,9 +341,11 @@ ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: call void @sideeffect1() ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -376,9 +394,11 @@ ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ] ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -428,9 +448,11 @@ ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]]) ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -472,9 +494,11 @@ ; CHECK: final_left: ; CHECK-NEXT: call void @sideeffect0() ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -504,9 +528,11 @@ ; CHECK-NEXT: call void @sideeffect0() ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; pred: @@ -548,9 +574,11 @@ ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ] ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -600,9 +628,11 @@ ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]]) ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -650,9 +680,11 @@ ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: call void @sideeffect1() ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -700,9 +732,11 @@ ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ] ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]]) ; CHECK-NEXT: call void @sideeffect0() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: final_right: ; CHECK-NEXT: call void @sideeffect1() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/guards.ll b/llvm/test/Transforms/SimplifyCFG/guards.ll --- a/llvm/test/Transforms/SimplifyCFG/guards.ll +++ b/llvm/test/Transforms/SimplifyCFG/guards.ll @@ -18,12 +18,13 @@ ; Demonstrate that we (intentionally) do not simplify a guard on undef ; CHECK-LABEL: @f_1( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[COMMON_RET:%.*]] ; CHECK: true: ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ] -; CHECK-NEXT: ret i32 10 -; CHECK: false: -; CHECK-NEXT: ret i32 20 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 10, [[TRUE]] ], [ 20, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: @@ -71,8 +72,8 @@ ; CHECK-NEXT: unreachable ; CHECK: merge_block: ; CHECK-NEXT: [[C1:%.*]] = load volatile i1, i1* [[C]], align 1 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C1]], i32 50, i32 100 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[C1]], i32 50, i32 100 +; CHECK-NEXT: ret i32 [[DOT]] ; entry: %c0 = load volatile i1, i1* %c diff --git a/llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll b/llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll --- a/llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll +++ b/llvm/test/Transforms/SimplifyCFG/hoist-dbgvalue.ll @@ -76,8 +76,8 @@ ; CHECK-NEXT: [[C_0:%.*]] = icmp sgt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[C_0]], i1 true, i1 [[C_2:%.*]] ; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[C_0]], i16 0, i16 20 -; CHECK-NEXT: br i1 [[BRMERGE]], label [[EXIT_1:%.*]], label [[FOR_COND]] -; CHECK: exit.1: +; CHECK-NEXT: br i1 [[BRMERGE]], label [[COMMON_RET:%.*]], label [[FOR_COND]] +; CHECK: common.ret: ; CHECK-NEXT: ret i16 [[DOTMUX]] ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/indirectbr.ll b/llvm/test/Transforms/SimplifyCFG/indirectbr.ll --- a/llvm/test/Transforms/SimplifyCFG/indirectbr.ll +++ b/llvm/test/Transforms/SimplifyCFG/indirectbr.ll @@ -23,9 +23,11 @@ ; CHECK: BB1: ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[BB0]] ], [ 1, [[ENTRY:%.*]] ] ; CHECK-NEXT: call void @B(i32 [[X]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: BB2: ; CHECK-NEXT: call void @C() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -107,9 +109,11 @@ ; CHECK-NEXT: br i1 [[COND:%.*]], label [[L1:%.*]], label [[L2:%.*]] ; CHECK: L1: ; CHECK-NEXT: call void @A() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: L2: ; CHECK-NEXT: call void @C() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/invoke.ll b/llvm/test/Transforms/SimplifyCFG/invoke.ll --- a/llvm/test/Transforms/SimplifyCFG/invoke.ll +++ b/llvm/test/Transforms/SimplifyCFG/invoke.ll @@ -168,12 +168,12 @@ ; CHECK-LABEL: @f6( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[FOO:%.*]] = invoke i32 @fn() -; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD:%.*]] -; CHECK: invoke.cont2: -; CHECK-NEXT: ret void +; CHECK-NEXT: to label [[COMMON_RET:%.*]] unwind label [[LPAD:%.*]] ; CHECK: lpad: ; CHECK-NEXT: [[TMP0:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/pr39807.ll b/llvm/test/Transforms/SimplifyCFG/pr39807.ll --- a/llvm/test/Transforms/SimplifyCFG/pr39807.ll +++ b/llvm/test/Transforms/SimplifyCFG/pr39807.ll @@ -4,7 +4,7 @@ define void @test(i1 %b) personality void()* @personality !dbg !1 { ; CHECK: invoke void @inlinable() -; CHECK-NEXT: to label %success unwind label %failure, !dbg ![[DBGLOC:[0-9]+]] +; CHECK-NEXT: to label %common.ret unwind label %failure, !dbg ![[DBGLOC:[0-9]+]] br i1 %b, label %if, label %else if: diff --git a/llvm/test/Transforms/SimplifyCFG/pr46638.ll b/llvm/test/Transforms/SimplifyCFG/pr46638.ll --- a/llvm/test/Transforms/SimplifyCFG/pr46638.ll +++ b/llvm/test/Transforms/SimplifyCFG/pr46638.ll @@ -11,12 +11,14 @@ ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0 ; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP2]] to i32 ; CHECK-NEXT: call void @dummy(i32 [[EXT]]) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: true2.critedge: ; CHECK-NEXT: [[CMP2_C:%.*]] = icmp sgt i32 [[X]], 0 ; CHECK-NEXT: [[EXT_C:%.*]] = zext i1 [[CMP2_C]] to i32 ; CHECK-NEXT: call void @dummy(i32 [[EXT_C]]) ; CHECK-NEXT: call void @dummy(i32 2) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp1 = icmp slt i32 %x, 0 diff --git a/llvm/test/Transforms/SimplifyCFG/pr48778-sdiv-speculation.ll b/llvm/test/Transforms/SimplifyCFG/pr48778-sdiv-speculation.ll --- a/llvm/test/Transforms/SimplifyCFG/pr48778-sdiv-speculation.ll +++ b/llvm/test/Transforms/SimplifyCFG/pr48778-sdiv-speculation.ll @@ -4,15 +4,14 @@ ; sdiv INT_MIN / -1 should not be speculated. define i32 @test(i1 %cmp) { ; CHECK-LABEL: @test( -; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if: ; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 -2147483648, -1 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[DIV]], 0 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP2]], i32 1, i32 0 -; CHECK-NEXT: br label [[ELSE]] -; CHECK: else: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[SPEC_SELECT]], [[IF]] ] -; CHECK-NEXT: ret i32 [[MERGE]] +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK: common.ret: +; CHECK-NEXT: ret i32 0 ; br i1 %cmp, label %if, label %else diff --git a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll --- a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll +++ b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll @@ -15,9 +15,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof [[PROF0:![0-9]+]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -47,9 +49,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof [[PROF1:![0-9]+]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -75,9 +79,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof [[PROF2:![0-9]+]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -104,9 +110,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof [[PROF1]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -133,9 +141,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Z:%.*]], label [[Y:%.*]], !prof [[PROF1]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -264,9 +274,11 @@ ; CHECK-NEXT: br i1 [[OR_COND]], label [[Y:%.*]], label [[Z:%.*]], !prof [[PROF5:![0-9]+]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -293,9 +305,11 @@ ; CHECK-NEXT: br i1 [[BRMERGE]], label [[Y:%.*]], label [[Z:%.*]], !prof [[PROF6:![0-9]+]] ; CHECK: Y: ; CHECK-NEXT: call void @helper(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: Z: ; CHECK-NEXT: call void @helper(i32 1) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -322,9 +336,11 @@ ; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B:%.*]], !prof [[PROF7:![0-9]+]] ; CHECK: a: ; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1:[0-9]+]] -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: b: ; CHECK-NEXT: call void @helper(i32 1) #[[ATTR1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -360,13 +376,16 @@ ; CHECK: a: ; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]] ; CHECK-NEXT: [[RETA:%.*]] = icmp slt i32 [[X]], [[Y:%.*]] -; CHECK-NEXT: ret i1 [[RETA]] +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: bees: ; CHECK-NEXT: br label [[END]] ; CHECK: end: ; CHECK-NEXT: [[RET:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[BEES]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] ; CHECK-NEXT: call void @helper(i32 2) #[[ATTR1]] -; CHECK-NEXT: ret i1 [[RET]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[RETA]], [[A]] ], [ [[RET]], [[END]] ] +; CHECK-NEXT: ret i1 [[COMMON_RET_OP]] ; entry: switch i32 %x, label %bees [ @@ -398,9 +417,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[LOR_END:%.*]], label [[LOR_RHS:%.*]], !prof [[PROF9:![0-9]+]] ; CHECK: lor.rhs: ; CHECK-NEXT: call void @helper(i32 1) #[[ATTR1]] -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: lor.end: ; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -428,9 +449,11 @@ ; CHECK-NEXT: br i1 [[COND]], label [[C:%.*]], label [[A:%.*]], !prof [[PROF10:![0-9]+]] ; CHECK: a: ; CHECK-NEXT: call void @helper(i32 0) #[[ATTR1]] -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: c: ; CHECK-NEXT: call void @helper(i32 2) #[[ATTR1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %i = shl i32 %x, 1 diff --git a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll --- a/llvm/test/Transforms/SimplifyCFG/rangereduce.ll +++ b/llvm/test/Transforms/SimplifyCFG/rangereduce.ll @@ -10,21 +10,21 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 0, label [[ONE:%.*]] ; CHECK-NEXT: i32 1, label [[TWO:%.*]] ; CHECK-NEXT: i32 2, label [[THREE:%.*]] ; CHECK-NEXT: i32 3, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 97, label %one @@ -47,21 +47,21 @@ ; Optimization shouldn't trigger; bitwidth > 64 define i128 @test2(i128 %a) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: switch i128 [[A:%.*]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i128 [[A:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i128 97, label [[ONE:%.*]] ; CHECK-NEXT: i128 101, label [[TWO:%.*]] ; CHECK-NEXT: i128 105, label [[THREE:%.*]] ; CHECK-NEXT: i128 109, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i128 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i128 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i128 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i128 [[COMMON_RET_OP]] ; switch i128 %a, label %def [ i128 97, label %one @@ -84,20 +84,20 @@ ; Optimization shouldn't trigger; no holes present define i32 @test3(i32 %a) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 97, label [[ONE:%.*]] ; CHECK-NEXT: i32 98, label [[TWO:%.*]] ; CHECK-NEXT: i32 99, label [[THREE:%.*]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 97, label %one @@ -119,21 +119,21 @@ ; Optimization shouldn't trigger; not an arithmetic progression define i32 @test4(i32 %a) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 97, label [[ONE:%.*]] ; CHECK-NEXT: i32 102, label [[TWO:%.*]] ; CHECK-NEXT: i32 105, label [[THREE:%.*]] ; CHECK-NEXT: i32 109, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 97, label %one @@ -156,21 +156,21 @@ ; Optimization shouldn't trigger; not a power of two define i32 @test5(i32 %a) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: switch i32 [[A:%.*]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 97, label [[ONE:%.*]] ; CHECK-NEXT: i32 102, label [[TWO:%.*]] ; CHECK-NEXT: i32 107, label [[THREE:%.*]] ; CHECK-NEXT: i32 112, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 97, label %one @@ -196,21 +196,21 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 3, label [[ONE:%.*]] ; CHECK-NEXT: i32 2, label [[TWO:%.*]] ; CHECK-NEXT: i32 1, label [[THREE:%.*]] ; CHECK-NEXT: i32 0, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 -97, label %one @@ -237,14 +237,14 @@ ; CHECK-NEXT: [[TMP3:%.*]] = shl i8 [[TMP1]], 6 ; CHECK-NEXT: [[TMP4:%.*]] = or i8 [[TMP2]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i8 [[TMP4]], 4 -; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[DEF:%.*]] +; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]] ; CHECK: switch.lookup: ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[TMP4]] to i32 ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul i32 [[SWITCH_CAST]], 8 ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -943228976, [[SWITCH_SHIFTAMT]] ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8 ; CHECK-NEXT: ret i8 [[SWITCH_MASKED]] -; CHECK: def: +; CHECK: common.ret: ; CHECK-NEXT: ret i8 -93 ; switch i8 %a, label %def [ @@ -271,21 +271,21 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 0, label [[ONE:%.*]] ; CHECK-NEXT: i32 1, label [[TWO:%.*]] ; CHECK-NEXT: i32 2, label [[THREE:%.*]] ; CHECK-NEXT: i32 4, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 97, label %one @@ -311,21 +311,21 @@ ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 31 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]] -; CHECK-NEXT: switch i32 [[TMP4]], label [[DEF:%.*]] [ +; CHECK-NEXT: switch i32 [[TMP4]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 6, label [[ONE:%.*]] ; CHECK-NEXT: i32 7, label [[TWO:%.*]] ; CHECK-NEXT: i32 0, label [[THREE:%.*]] ; CHECK-NEXT: i32 2, label [[THREE]] ; CHECK-NEXT: ] -; CHECK: def: -; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ 8867, [[TMP0:%.*]] ], [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ] -; CHECK-NEXT: ret i32 [[MERGE]] ; CHECK: one: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: two: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: three: -; CHECK-NEXT: br label [[DEF]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; switch i32 %a, label %def [ i32 18, label %one diff --git a/llvm/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll b/llvm/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll --- a/llvm/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll +++ b/llvm/test/Transforms/SimplifyCFG/suppress-zero-branch-weights.ll @@ -12,16 +12,16 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SEXT:%.*]] = sext i8 [[CONDITION:%.*]] to i32 ; CHECK-NEXT: switch i32 [[SEXT]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[A:%.*]] -; CHECK-NEXT: i32 127, label [[A]] -; CHECK-NEXT: i32 -128, label [[A]] -; CHECK-NEXT: i32 -1, label [[A]] +; CHECK-NEXT: i32 0, label [[COMMON_RET:%.*]] +; CHECK-NEXT: i32 127, label [[COMMON_RET]] +; CHECK-NEXT: i32 -128, label [[COMMON_RET]] +; CHECK-NEXT: i32 -1, label [[COMMON_RET]] ; CHECK-NEXT: ] -; CHECK: a: -; CHECK-NEXT: [[MERGE:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ false, [[DEFAULT]] ] -; CHECK-NEXT: ret i1 [[MERGE]] ; CHECK: default: -; CHECK-NEXT: br label [[A]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ false, [[DEFAULT]] ], [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] +; CHECK-NEXT: ret i1 [[COMMON_RET_OP]] ; entry: %sext = sext i8 %condition to i32 diff --git a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll --- a/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-dead-default.ll @@ -11,9 +11,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; switch i1 %a, label %default [i1 1, label %true @@ -39,18 +41,20 @@ ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: case1: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: case2: ; CHECK-NEXT: call void @foo(i32 2) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: case3: ; CHECK-NEXT: call void @foo(i32 3) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: default1: ; CHECK-NEXT: unreachable +; CHECK: common.ret: +; CHECK-NEXT: ret void ; switch i2 %a, label %default [i2 0, label %case0 i2 1, label %case1 @@ -84,15 +88,17 @@ ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: case1: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: case2: ; CHECK-NEXT: call void @foo(i32 2) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: default: ; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; switch i2 %a, label %default [i2 0, label %case0 @@ -123,12 +129,14 @@ ; CHECK-NEXT: ] ; CHECK: case0: ; CHECK-NEXT: call void @foo(i32 0) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: case1: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: default: ; CHECK-NEXT: call void @foo(i32 2) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; switch i128 %a, label %default [i128 0, label %case0 @@ -155,9 +163,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp = icmp ult i8 %a, 2 @@ -186,9 +196,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i8 %a, 254 @@ -219,9 +231,11 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @foo(i32 1) -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @foo(i32 3) +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i8 %a, 254 diff --git a/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll b/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll --- a/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-masked-bits.ll @@ -3,11 +3,11 @@ define i32 @test1(i32 %x) nounwind { ; CHECK-LABEL: @test1( -; CHECK-NEXT: a: +; CHECK-NEXT: common.ret: ; CHECK-NEXT: [[I:%.*]] = shl i32 [[X:%.*]], 1 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I]], 24 -; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[COND]], i32 5, i32 0 -; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK-NEXT: [[DOT:%.*]] = select i1 [[COND]], i32 5, i32 0 +; CHECK-NEXT: ret i32 [[DOT]] ; %i = shl i32 %x, 1 switch i32 %i, label %a [ @@ -51,16 +51,16 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[SEXT:%.*]] = sext i8 [[CONDITION:%.*]] to i32 ; CHECK-NEXT: switch i32 [[SEXT]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[A:%.*]] -; CHECK-NEXT: i32 127, label [[A]] -; CHECK-NEXT: i32 -128, label [[A]] -; CHECK-NEXT: i32 -1, label [[A]] +; CHECK-NEXT: i32 0, label [[COMMON_RET:%.*]] +; CHECK-NEXT: i32 127, label [[COMMON_RET]] +; CHECK-NEXT: i32 -128, label [[COMMON_RET]] +; CHECK-NEXT: i32 -1, label [[COMMON_RET]] ; CHECK-NEXT: ] -; CHECK: a: -; CHECK-NEXT: [[MERGE:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ false, [[DEFAULT]] ] -; CHECK-NEXT: ret i1 [[MERGE]] ; CHECK: default: -; CHECK-NEXT: br label [[A]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ false, [[DEFAULT]] ], [ true, [[ENTRY:%.*]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] +; CHECK-NEXT: ret i1 [[COMMON_RET_OP]] ; entry: %sext = sext i8 %condition to i32 diff --git a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll --- a/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-on-const-select.ll @@ -12,11 +12,14 @@ ; CHECK-NEXT: br i1 [[LT]], label [[A:%.*]], label [[B]] ; CHECK: a: ; CHECK-NEXT: tail call void @bees.a() #[[ATTR0:[0-9]+]] -; CHECK-NEXT: ret i32 1 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: b: ; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[SWITCH]] ], [ 2, [[ENTRY:%.*]] ] ; CHECK-NEXT: tail call void @bees.b() #[[ATTR0]] -; CHECK-NEXT: ret i32 [[RETVAL]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 1, [[A]] ], [ [[RETVAL]], [[B]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: %eq = icmp eq i64 %x, %y @@ -125,10 +128,13 @@ ; CHECK-LABEL: @xyzzy( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[EQ:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: br i1 [[EQ]], label [[COMMON_RET:%.*]], label [[CONT:%.*]] +; CHECK: cont: ; CHECK-NEXT: [[LT:%.*]] = icmp slt i64 [[X]], [[Y]] ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[LT]], i32 -1, i32 1 -; CHECK-NEXT: [[VAL:%.*]] = select i1 [[EQ]], i32 0, i32 [[SPEC_SELECT]] -; CHECK-NEXT: ret i32 [[VAL]] +; CHECK-NEXT: ret i32 [[SPEC_SELECT]] +; CHECK: common.ret: +; CHECK-NEXT: ret i32 0 ; entry: %eq = icmp eq i64 %x, %y diff --git a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll --- a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -11,10 +11,13 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[DEFAULT:%.*]] ; CHECK: default: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: a: ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0]], [[DEFAULT]] ], [ [[TMP1]], [[A]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: @@ -40,10 +43,13 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] ; CHECK: a: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: b: ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0]], [[A]] ], [ [[TMP1]], [[B]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: @@ -75,10 +81,13 @@ ; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] ; CHECK: a: ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @f(i32 0) -; CHECK-NEXT: ret i32 [[TMP0]] +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: b: ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @f(i32 1) -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0]], [[A]] ], [ [[TMP1]], [[B]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll --- a/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create-custom-dl.ll @@ -14,9 +14,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 %V, 4 ; [#uses=1] @@ -40,9 +42,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) @@ -66,9 +70,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) @@ -91,9 +97,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp ne i32 %V, 4 ; [#uses=1] @@ -116,9 +124,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 %V, 4 ; [#uses=1] @@ -248,14 +258,14 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] ; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ +; CHECK-NEXT: switch i8 [[C:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i8 99, label [[IF_THEN]] ; CHECK-NEXT: i8 97, label [[IF_THEN]] ; CHECK-NEXT: ] ; CHECK: if.then: ; CHECK-NEXT: tail call void @foo1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void -; CHECK: if.end: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -283,16 +293,17 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] ; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ +; CHECK-NEXT: switch i8 [[C:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i8 99, label [[IF_THEN]] ; CHECK-NEXT: i8 97, label [[IF_THEN]] ; CHECK-NEXT: ] ; CHECK: if.then: ; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] ; CHECK-NEXT: tail call void @foo1() #[[ATTR2]] -; CHECK-NEXT: ret i32 [[A]] -; CHECK: if.end: -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[A]], [[IF_THEN]] ], [ 0, [[SWITCH_EARLY_TEST]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: br i1 %C, label %N, label %if.then @@ -397,10 +408,13 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret i32 123 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret i32 324 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 123, [[T]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -636,11 +650,11 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[Y:%.*]], 2 ; CHECK-NEXT: [[OR_COND775:%.*]] = or i1 [[CMP]], [[SWITCH]] -; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[COMMON_RET:%.*]] ; CHECK: lor.lhs.false8: ; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: ret void -; CHECK: return: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp = icmp ult i32 %x, 3 @@ -735,15 +749,15 @@ define void @test19(i32 %arg) { ; CHECK-LABEL: @test19( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ +; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 32, label [[IF:%.*]] ; CHECK-NEXT: i32 13, label [[IF]] ; CHECK-NEXT: i32 12, label [[IF]] ; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i32 %arg, -2 @@ -767,11 +781,11 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 13 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32 ; CHECK-NEXT: [[PRED:%.*]] = or i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i32 %arg, -2 @@ -792,14 +806,14 @@ define void @test21(i32 %arg) { ; CHECK-LABEL: @test21( ; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[IF:%.*]] [ -; CHECK-NEXT: i32 32, label [[ELSE:%.*]] -; CHECK-NEXT: i32 13, label [[ELSE]] -; CHECK-NEXT: i32 12, label [[ELSE]] +; CHECK-NEXT: i32 32, label [[COMMON_RET:%.*]] +; CHECK-NEXT: i32 13, label [[COMMON_RET]] +; CHECK-NEXT: i32 12, label [[COMMON_RET]] ; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = or i32 %arg, 1 @@ -823,11 +837,11 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[AND]], 12 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[ARG]], 32 ; CHECK-NEXT: [[PRED:%.*]] = and i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = or i32 %arg, 1 diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll --- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll @@ -14,9 +14,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 %V, 4 ; [#uses=1] @@ -39,9 +41,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 %V, 4 @@ -65,9 +69,11 @@ ; DL-NEXT: ] ; DL: T: ; DL-NEXT: call void @foo1() -; DL-NEXT: ret void +; DL-NEXT: br label [[COMMON_RET:%.*]] ; DL: F: ; DL-NEXT: call void @foo2() +; DL-NEXT: br label [[COMMON_RET]] +; DL: common.ret: ; DL-NEXT: ret void ; %C1 = icmp eq i32* %V, inttoptr (i32 4 to i32*) @@ -91,9 +97,11 @@ ; DL-NEXT: ] ; DL: T: ; DL-NEXT: call void @foo1() -; DL-NEXT: ret void +; DL-NEXT: br label [[COMMON_RET:%.*]] ; DL: F: ; DL-NEXT: call void @foo2() +; DL-NEXT: br label [[COMMON_RET]] +; DL: common.ret: ; DL-NEXT: ret void ; %C1 = icmp eq i32 addrspace(1)* %V, inttoptr (i32 4 to i32 addrspace(1)*) @@ -116,9 +124,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp ne i32 %V, 4 ; [#uses=1] @@ -141,9 +151,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp ne i32 %V, 4 @@ -166,9 +178,11 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %C1 = icmp eq i32 %V, 4 ; [#uses=1] @@ -298,14 +312,14 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[SWITCH_EARLY_TEST:%.*]] ; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ +; CHECK-NEXT: switch i8 [[C:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i8 99, label [[IF_THEN]] ; CHECK-NEXT: i8 97, label [[IF_THEN]] ; CHECK-NEXT: ] ; CHECK: if.then: ; CHECK-NEXT: tail call void @foo1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void -; CHECK: if.end: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; entry: @@ -333,16 +347,17 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN]], label [[SWITCH_EARLY_TEST:%.*]] ; CHECK: switch.early.test: -; CHECK-NEXT: switch i8 [[C:%.*]], label [[IF_END:%.*]] [ +; CHECK-NEXT: switch i8 [[C:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i8 99, label [[IF_THEN]] ; CHECK-NEXT: i8 97, label [[IF_THEN]] ; CHECK-NEXT: ] ; CHECK: if.then: ; CHECK-NEXT: [[A:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 42, [[SWITCH_EARLY_TEST]] ], [ 42, [[N]] ], [ 42, [[SWITCH_EARLY_TEST]] ] ; CHECK-NEXT: tail call void @foo1() #[[ATTR2]] -; CHECK-NEXT: ret i32 [[A]] -; CHECK: if.end: -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[A]], [[IF_THEN]] ], [ 0, [[SWITCH_EARLY_TEST]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; entry: br i1 %C, label %N, label %if.then @@ -447,10 +462,13 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret i32 123 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret i32 324 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 123, [[T]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -476,10 +494,13 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret i32 123 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret i32 324 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 123, [[T]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -506,10 +527,13 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret i32 123 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret i32 324 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 123, [[T]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -535,10 +559,13 @@ ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret i32 123 +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: F: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret i32 324 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: +; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 123, [[T]] ], [ 324, [[F]] ] +; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] ; %A = icmp ne i32 %mode, 0 %B = icmp ne i32 %mode, 51 @@ -774,11 +801,11 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[Y:%.*]], 2 ; CHECK-NEXT: [[OR_COND775:%.*]] = or i1 [[CMP]], [[SWITCH]] -; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[COMMON_RET:%.*]] ; CHECK: lor.lhs.false8: ; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: ret void -; CHECK: return: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp = icmp ult i32 %x, 3 @@ -800,11 +827,11 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 3 ; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[Y:%.*]], 2 ; CHECK-NEXT: [[OR_COND775:%.*]] = select i1 [[CMP]], i1 true, i1 [[SWITCH]] -; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[RETURN:%.*]] +; CHECK-NEXT: br i1 [[OR_COND775]], label [[LOR_LHS_FALSE8:%.*]], label [[COMMON_RET:%.*]] ; CHECK: lor.lhs.false8: ; CHECK-NEXT: tail call void @foo1() -; CHECK-NEXT: ret void -; CHECK: return: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %cmp = icmp ult i32 %x, 3 @@ -900,15 +927,15 @@ ; Form a switch when and'ing a negated power of two define void @test19(i32 %arg) { ; CHECK-LABEL: @test19( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ +; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 32, label [[IF:%.*]] ; CHECK-NEXT: i32 13, label [[IF]] ; CHECK-NEXT: i32 12, label [[IF]] ; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i32 %arg, -2 @@ -927,15 +954,15 @@ define void @test19_select(i32 %arg) { ; CHECK-LABEL: @test19_select( -; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[ELSE:%.*]] [ +; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[COMMON_RET:%.*]] [ ; CHECK-NEXT: i32 32, label [[IF:%.*]] ; CHECK-NEXT: i32 13, label [[IF]] ; CHECK-NEXT: i32 12, label [[IF]] ; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i32 %arg, -2 @@ -959,11 +986,11 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[AND]], 13 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[ARG]], 32 ; CHECK-NEXT: [[PRED:%.*]] = or i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = and i32 %arg, -2 @@ -984,14 +1011,14 @@ define void @test21(i32 %arg) { ; CHECK-LABEL: @test21( ; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[IF:%.*]] [ -; CHECK-NEXT: i32 32, label [[ELSE:%.*]] -; CHECK-NEXT: i32 13, label [[ELSE]] -; CHECK-NEXT: i32 12, label [[ELSE]] +; CHECK-NEXT: i32 32, label [[COMMON_RET:%.*]] +; CHECK-NEXT: i32 13, label [[COMMON_RET]] +; CHECK-NEXT: i32 12, label [[COMMON_RET]] ; CHECK-NEXT: ] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = or i32 %arg, 1 @@ -1015,11 +1042,11 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[AND]], 12 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[ARG]], 32 ; CHECK-NEXT: [[PRED:%.*]] = and i1 [[CMP1]], [[CMP2]] -; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK-NEXT: br i1 [[PRED]], label [[IF:%.*]], label [[COMMON_RET:%.*]] ; CHECK: if: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: else: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; %and = or i32 %arg, 1 diff --git a/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll b/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll --- a/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_switch_fold.ll @@ -22,12 +22,14 @@ ; CHECK-NEXT: ] ; CHECK: A: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: B: ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: D: ; CHECK-NEXT: call void @foo4() +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; CHECK: infloop: ; CHECK-NEXT: br label [[INFLOOP]] diff --git a/llvm/test/Transforms/SimplifyCFG/switch_thread.ll b/llvm/test/Transforms/SimplifyCFG/switch_thread.ll --- a/llvm/test/Transforms/SimplifyCFG/switch_thread.ll +++ b/llvm/test/Transforms/SimplifyCFG/switch_thread.ll @@ -13,16 +13,16 @@ ; CHECK-LABEL: @test1( ; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ ; CHECK-NEXT: i32 4, label [[T:%.*]] -; CHECK-NEXT: i32 17, label [[DONE:%.*]] +; CHECK-NEXT: i32 17, label [[COMMON_RET:%.*]] ; CHECK-NEXT: ] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: call void @foo2() -; CHECK-NEXT: br label [[DONE]] +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: A: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: br label [[DONE]] -; CHECK: Done: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; switch i32 %V, label %A [ @@ -68,20 +68,20 @@ ; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ ; CHECK-NEXT: i32 4, label [[T:%.*]] ; CHECK-NEXT: i32 17, label [[D:%.*]] -; CHECK-NEXT: i32 1234, label [[E:%.*]] +; CHECK-NEXT: i32 1234, label [[COMMON_RET:%.*]] ; CHECK-NEXT: ] ; CHECK: A: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V]], 42 -; CHECK-NEXT: br i1 [[COND]], label [[D]], label [[E]] +; CHECK-NEXT: br i1 [[COND]], label [[D]], label [[COMMON_RET]] ; CHECK: T: ; CHECK-NEXT: call void @foo1() ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET]] ; CHECK: D: ; CHECK-NEXT: call void @foo1() -; CHECK-NEXT: ret void -; CHECK: E: +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; switch i32 %V, label %A [ diff --git a/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll b/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll --- a/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll +++ b/llvm/test/Transforms/SimplifyCFG/unprofitable-pr.ll @@ -18,7 +18,7 @@ ; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) ; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: true2.critedge: ; CHECK-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64 ; CHECK-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7 @@ -26,6 +26,8 @@ ; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND_C]]) ; CHECK-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; br i1 %c, label %true1, label %false1 @@ -68,7 +70,7 @@ ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: true2.critedge: ; CHECK-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64 ; CHECK-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7 @@ -81,6 +83,8 @@ ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; br i1 %c, label %true1, label %false1 @@ -133,9 +137,11 @@ ; CHECK-NEXT: br label [[TRUE1]] ; CHECK: true2: ; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8 -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: false2: ; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; br i1 %c, label %true1, label %false1 @@ -184,7 +190,7 @@ ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 3, i64* [[PTR]], align 8 -; CHECK-NEXT: ret void +; CHECK-NEXT: br label [[COMMON_RET:%.*]] ; CHECK: true2.critedge: ; CHECK-NEXT: [[VTABLEI8_C:%.*]] = bitcast [3 x i8*]* [[VTABLE]] to i8* ; CHECK-NEXT: [[P_C:%.*]] = call i1 @llvm.type.test(i8* [[VTABLEI8_C]], metadata !"foo") @@ -196,6 +202,8 @@ ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; CHECK-NEXT: store volatile i64 2, i64* [[PTR]], align 8 +; CHECK-NEXT: br label [[COMMON_RET]] +; CHECK: common.ret: ; CHECK-NEXT: ret void ; br i1 %c, label %true1, label %false1