diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -2839,6 +2839,24 @@ const Loop &L, const LoopInfo &LI, AAResults &AA, const MemorySSAUpdater *MSSAU) { assert(UnswitchCandidates.empty() && "Should be!"); + + auto AddUnswitchCandidatesForInst = [&](Instruction *I, Value *Cond) { + Cond = skipTrivialSelect(Cond); + if (isa(Cond)) + return; + if (L.isLoopInvariant(Cond)) { + UnswitchCandidates.push_back({I, {Cond}}); + return; + } + if (match(Cond, m_CombineOr(m_LogicalAnd(), m_LogicalOr()))) { + TinyPtrVector Invariants = + collectHomogenousInstGraphLoopInvariants( + L, *static_cast(Cond), LI); + if (!Invariants.empty()) + UnswitchCandidates.push_back({I, std::move(Invariants)}); + } + }; + // Whether or not we should also collect guards in the loop. bool CollectGuards = false; if (UnswitchGuards) { @@ -2854,10 +2872,10 @@ for (auto &I : *BB) { if (auto *SI = dyn_cast(&I)) { - auto *Cond = skipTrivialSelect(SI->getCondition()); - // restrict to simple boolean selects - if (!isa(Cond) && L.isLoopInvariant(Cond) && Cond->getType()->isIntegerTy(1)) - UnswitchCandidates.push_back({&I, {Cond}}); + auto *Cond = SI->getCondition(); + // Do not unswitch vector selects and logical and/or selects + if (Cond->getType()->isIntegerTy(1) && !SI->getType()->isIntegerTy(1)) + AddUnswitchCandidatesForInst(SI, Cond); } else if (CollectGuards && isGuard(&I)) { auto *Cond = skipTrivialSelect(cast(&I)->getArgOperand(0)); @@ -2877,29 +2895,11 @@ } auto *BI = dyn_cast(BB->getTerminator()); - if (!BI || !BI->isConditional() || isa(BI->getCondition()) || + if (!BI || !BI->isConditional() || BI->getSuccessor(0) == BI->getSuccessor(1)) continue; - Value *Cond = skipTrivialSelect(BI->getCondition()); - if (isa(Cond)) - continue; - - if (L.isLoopInvariant(Cond)) { - UnswitchCandidates.push_back({BI, {Cond}}); - continue; - } - - Instruction &CondI = *cast(Cond); - if (match(&CondI, m_CombineOr(m_LogicalAnd(), m_LogicalOr()))) { - TinyPtrVector Invariants = - collectHomogenousInstGraphLoopInvariants(L, CondI, LI); - if (Invariants.empty()) - continue; - - UnswitchCandidates.push_back({BI, std::move(Invariants)}); - continue; - } + AddUnswitchCandidatesForInst(BI, BI->getCondition()); } if (MSSAU && !findOptionMDForLoop(&L, "llvm.loop.unswitch.partial.disable") && @@ -3318,6 +3318,10 @@ // cost for that terminator. auto ComputeUnswitchedCost = [&](Instruction &TI, bool FullUnswitch) -> InstructionCost { + // Unswitching selects unswitches the entire loop. + if (isa(TI)) + return LoopCost; + BasicBlock &BB = *TI.getParent(); SmallPtrSet Visited; @@ -3367,8 +3371,7 @@ // loop. This is computing the new cost of unswitching a condition. // Note that guards always have 2 unique successors that are implicit and // will be materialized if we decide to unswitch it. - int SuccessorsCount = - isGuard(&TI) || isa(TI) ? 2 : Visited.size(); + int SuccessorsCount = isGuard(&TI) ? 2 : Visited.size(); assert(SuccessorsCount > 1 && "Cannot unswitch a condition without multiple distinct successors!"); return (LoopCost - Cost) * (SuccessorsCount - 1); diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll @@ -2332,26 +2332,21 @@ define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c.1, i1 noundef %c.2) { ; CHECK-LABEL: @test_partial_unswitch_all_conds_guaranteed_non_poison( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C_1:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[C_1:%.*]], [[C_2:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]] ; CHECK: entry.split.us: ; CHECK-NEXT: br label [[LOOP_US:%.*]] ; CHECK: loop.us: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @a() -; CHECK-NEXT: br label [[TMP1:%.*]] -; CHECK: 1: -; CHECK-NEXT: br label [[TMP2:%.*]] -; CHECK: 2: -; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i1 [ [[C_2:%.*]], [[TMP1]] ] -; CHECK-NEXT: br i1 [[UNSWITCHED_SELECT_US]], label [[LOOP_US]], label [[EXIT_SPLIT_US:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @a() +; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]] ; CHECK: exit.split.us: ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[TMP3:%.*]] = call i32 @a() -; CHECK-NEXT: br label [[TMP4:%.*]] -; CHECK: 4: -; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT_SPLIT:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @a() +; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false +; CHECK-NEXT: br i1 [[SEL]], label [[LOOP]], label [[EXIT_SPLIT:%.*]] ; CHECK: exit.split: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-select.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-select.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-select.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-select.ll @@ -827,21 +827,43 @@ ; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0 ; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.body.preheader: +; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]] +; CHECK: for.body.preheader.split.us: +; CHECK-NEXT: br label [[FOR_BODY_US:%.*]] +; CHECK: for.body.us: +; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP0:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ] +; CHECK-NEXT: br label [[TMP0]] +; CHECK: 0: +; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ 0, [[FOR_BODY_US]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]]) +; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1 +; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]] +; CHECK: for.cond.cleanup.loopexit.split.us: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] +; CHECK: for.body.preheader.split: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit.split: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]] ; CHECK: for.cond.cleanup.loopexit: ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret i32 undef ; CHECK: for.body: -; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP3:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ] ; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND]], [[CMP1]] -; CHECK-NEXT: [[COND2:%.*]] = select i1 [[TMP0]], i32 [[I_07]], i32 0 -; CHECK-NEXT: tail call void @bar(i32 noundef [[COND2]]) +; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[CMP1]] +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3]] +; CHECK: 2: +; CHECK-NEXT: br label [[TMP3]] +; CHECK: 3: +; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP2]] ], [ 0, [[FOR_BODY]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]]) ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]] ; entry: %cmp6 = icmp sgt i32 %num, 0 @@ -870,21 +892,43 @@ ; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0 ; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.body.preheader: +; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]] +; CHECK: for.body.preheader.split.us: +; CHECK-NEXT: br label [[FOR_BODY_US:%.*]] +; CHECK: for.body.us: +; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP0:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ] +; CHECK-NEXT: br label [[TMP0]] +; CHECK: 0: +; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ 0, [[FOR_BODY_US]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]]) +; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1 +; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]] +; CHECK: for.cond.cleanup.loopexit.split.us: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] +; CHECK: for.body.preheader.split: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit.split: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]] ; CHECK: for.cond.cleanup.loopexit: ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret i32 undef ; CHECK: for.body: -; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP3:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ] ; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CMP1]], [[COND]] -; CHECK-NEXT: [[COND2:%.*]] = select i1 [[TMP0]], i32 [[I_07]], i32 0 -; CHECK-NEXT: tail call void @bar(i32 noundef [[COND2]]) +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[CMP1]], true +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3]] +; CHECK: 2: +; CHECK-NEXT: br label [[TMP3]] +; CHECK: 3: +; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP2]] ], [ 0, [[FOR_BODY]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]]) ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]] ; entry: %cmp6 = icmp sgt i32 %num, 0 @@ -913,21 +957,45 @@ ; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0 ; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.body.preheader: +; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]] +; CHECK: for.body.preheader.split.us: +; CHECK-NEXT: br label [[FOR_BODY_US:%.*]] +; CHECK: for.body.us: +; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP1:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ] +; CHECK-NEXT: br label [[TMP0:%.*]] +; CHECK: 0: +; CHECK-NEXT: br label [[TMP1]] +; CHECK: 1: +; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_07_US]], [[TMP0]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]]) +; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1 +; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]] +; CHECK: for.cond.cleanup.loopexit.split.us: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] +; CHECK: for.body.preheader.split: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit.split: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]] ; CHECK: for.cond.cleanup.loopexit: ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret i32 undef ; CHECK: for.body: -; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP4:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ] ; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND]], [[CMP1]] -; CHECK-NEXT: [[COND2:%.*]] = select i1 [[TMP0]], i32 [[I_07]], i32 0 -; CHECK-NEXT: tail call void @bar(i32 noundef [[COND2]]) +; CHECK-NEXT: [[TMP2:%.*]] = or i1 false, [[CMP1]] +; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4]] +; CHECK: 3: +; CHECK-NEXT: br label [[TMP4]] +; CHECK: 4: +; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP3]] ], [ 0, [[FOR_BODY]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]]) ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]] ; entry: %cmp6 = icmp sgt i32 %num, 0 @@ -956,21 +1024,45 @@ ; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[NUM]], 0 ; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.body.preheader: +; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: br i1 [[COND_FR]], label [[FOR_BODY_PREHEADER_SPLIT_US:%.*]], label [[FOR_BODY_PREHEADER_SPLIT:%.*]] +; CHECK: for.body.preheader.split.us: +; CHECK-NEXT: br label [[FOR_BODY_US:%.*]] +; CHECK: for.body.us: +; CHECK-NEXT: [[I_07_US:%.*]] = phi i32 [ [[INC_US:%.*]], [[TMP1:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT_US]] ] +; CHECK-NEXT: br label [[TMP0:%.*]] +; CHECK: 0: +; CHECK-NEXT: br label [[TMP1]] +; CHECK: 1: +; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i32 [ [[I_07_US]], [[TMP0]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT_US]]) +; CHECK-NEXT: [[INC_US]] = add nuw nsw i32 [[I_07_US]], 1 +; CHECK-NEXT: [[EXITCOND_NOT_US:%.*]] = icmp eq i32 [[INC_US]], [[NUM]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT_US]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT_US:%.*]], label [[FOR_BODY_US]] +; CHECK: for.cond.cleanup.loopexit.split.us: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] +; CHECK: for.body.preheader.split: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit.split: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP_LOOPEXIT]] ; CHECK: for.cond.cleanup.loopexit: ; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret i32 undef ; CHECK: for.body: -; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[I_07:%.*]] = phi i32 [ [[INC:%.*]], [[TMP4:%.*]] ], [ 0, [[FOR_BODY_PREHEADER_SPLIT]] ] ; CHECK-NEXT: [[REM:%.*]] = and i32 [[I_07]], 1 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[REM]], 0 -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[CMP1]], [[COND]] -; CHECK-NEXT: [[COND2:%.*]] = select i1 [[TMP0]], i32 [[I_07]], i32 0 -; CHECK-NEXT: tail call void @bar(i32 noundef [[COND2]]) +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[CMP1]], false +; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4]] +; CHECK: 3: +; CHECK-NEXT: br label [[TMP4]] +; CHECK: 4: +; CHECK-NEXT: [[UNSWITCHED_SELECT:%.*]] = phi i32 [ [[I_07]], [[TMP3]] ], [ 0, [[FOR_BODY]] ] +; CHECK-NEXT: tail call void @bar(i32 noundef [[UNSWITCHED_SELECT]]) ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_07]], 1 ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC]], [[NUM]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP_LOOPEXIT_SPLIT:%.*]], label [[FOR_BODY]] ; entry: %cmp6 = icmp sgt i32 %num, 0 diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-trivial-select.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-trivial-select.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-trivial-select.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-trivial-select.ll @@ -88,34 +88,21 @@ ; CHECK-LABEL: @unswitch_trivial_select_cmp_outside( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[X:%.*]], 100 -; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] -; CHECK-NEXT: br i1 [[C_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: br i1 [[C]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split.us: ; CHECK-NEXT: br label [[LOOP_US:%.*]] ; CHECK: loop.us: -; CHECK-NEXT: [[P_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ 35, [[TMP1:%.*]] ] -; CHECK-NEXT: br label [[TMP0:%.*]] -; CHECK: 0: -; CHECK-NEXT: br label [[TMP1]] -; CHECK: 1: -; CHECK-NEXT: [[UNSWITCHED_SELECT_US:%.*]] = phi i1 [ true, [[TMP0]] ] -; CHECK-NEXT: br i1 [[UNSWITCHED_SELECT_US]], label [[LOOP_US]], label [[EXIT_SPLIT_US:%.*]] -; CHECK: exit.split.us: -; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[P_US]], [[TMP1]] ] -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: [[P_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ 35, [[LOOP_US]] ] +; CHECK-NEXT: br label [[LOOP_US]] ; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ 35, [[TMP2:%.*]] ] -; CHECK-NEXT: br label [[TMP2]] -; CHECK: 2: -; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT_SPLIT:%.*]] -; CHECK: exit.split: -; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[P]], [[TMP2]] ] -; CHECK-NEXT: br label [[EXIT]] +; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ] +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 false, i1 true, i1 false +; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[EXIT_SPLIT]] ], [ [[LCSSA_US]], [[EXIT_SPLIT_US]] ] -; CHECK-NEXT: ret i32 [[DOTUS_PHI]] +; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[P]], [[LOOP]] ] +; CHECK-NEXT: ret i32 [[LCSSA]] ; entry: %c = icmp ult i32 %x, 100