diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 685ea31f9ed25b..0272db8844c038 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -116,23 +116,13 @@ static cl::opt FreezeLoopUnswitchCond( cl::desc("If enabled, the freeze instruction will be added to condition " "of loop unswitch to prevent miscompilation.")); -// Helper to skip (select x, true, false), which matches both a logical AND and -// OR and can confuse code that tries to determine if \p Cond is either a -// logical AND or OR but not both. -static Value *skipTrivialSelect(Value *Cond) { - Value *CondNext; - while (match(Cond, m_Select(m_Value(CondNext), m_One(), m_Zero()))) - Cond = CondNext; - return Cond; -} - /// Collect all of the loop invariant input values transitively used by the /// homogeneous instruction graph from a given root. /// /// This essentially walks from a root recursively through loop variant operands -/// which have perform the same logical operation (AND or OR) and finds all -/// inputs which are loop invariant. For some operations these can be -/// re-associated and unswitched out of the loop entirely. +/// which have the exact same opcode and finds all inputs which are loop +/// invariant. For some operations these can be re-associated and unswitched out +/// of the loop entirely. static TinyPtrVector collectHomogenousInstGraphLoopInvariants(Loop &L, Instruction &Root, LoopInfo &LI) { @@ -162,7 +152,7 @@ collectHomogenousInstGraphLoopInvariants(Loop &L, Instruction &Root, } // If not an instruction with the same opcode, nothing we can do. - Instruction *OpI = dyn_cast(skipTrivialSelect(OpV)); + Instruction *OpI = dyn_cast(OpV); if (OpI && ((IsRootAnd && match(OpI, m_LogicalAnd())) || (IsRootOr && match(OpI, m_LogicalOr())))) { @@ -464,8 +454,7 @@ static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT, Invariants.push_back(BI.getCondition()); FullUnswitch = true; } else { - if (auto *CondInst = - dyn_cast(skipTrivialSelect(BI.getCondition()))) + if (auto *CondInst = dyn_cast(BI.getCondition())) Invariants = collectHomogenousInstGraphLoopInvariants(L, *CondInst, LI); if (Invariants.empty()) { LLVM_DEBUG(dbgs() << " Couldn't find invariant inputs!\n"); @@ -499,9 +488,8 @@ static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT, // is a graph of `or` operations, or the exit block is along the false edge // and the condition is a graph of `and` operations. if (!FullUnswitch) { - Value *Cond = skipTrivialSelect(BI.getCondition()); - if (ExitDirection ? !match(Cond, m_LogicalOr()) - : !match(Cond, m_LogicalAnd())) { + if (ExitDirection ? !match(BI.getCondition(), m_LogicalOr()) + : !match(BI.getCondition(), m_LogicalAnd())) { LLVM_DEBUG(dbgs() << " Branch condition is in improper form for " "non-full unswitch!\n"); return false; @@ -581,11 +569,11 @@ static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT, // Only unswitching a subset of inputs to the condition, so we will need to // build a new branch that merges the invariant inputs. if (ExitDirection) - assert(match(skipTrivialSelect(BI.getCondition()), m_LogicalOr()) && + assert(match(BI.getCondition(), m_LogicalOr()) && "Must have an `or` of `i1`s or `select i1 X, true, Y`s for the " "condition!"); else - assert(match(skipTrivialSelect(BI.getCondition()), m_LogicalAnd()) && + assert(match(BI.getCondition(), m_LogicalAnd()) && "Must have an `and` of `i1`s or `select i1 X, Y, false`s for the" " condition!"); buildPartialUnswitchConditionalBranch( @@ -2083,14 +2071,14 @@ static void unswitchNontrivialInvariants( bool Direction = true; int ClonedSucc = 0; if (!FullUnswitch) { - Value *Cond = skipTrivialSelect(BI->getCondition()); + Value *Cond = BI->getCondition(); (void)Cond; assert(((match(Cond, m_LogicalAnd()) ^ match(Cond, m_LogicalOr())) || PartiallyInvariant) && "Only `or`, `and`, an `select`, partially invariant instructions " "can combine invariants being unswitched."); - if (!match(Cond, m_LogicalOr())) { - if (match(Cond, m_LogicalAnd()) || + if (!match(BI->getCondition(), m_LogicalOr())) { + if (match(BI->getCondition(), m_LogicalAnd()) || (PartiallyInvariant && !PartialIVInfo.KnownValue->isOneValue())) { Direction = false; ClonedSucc = 1; @@ -2768,16 +2756,22 @@ static bool unswitchBestCondition( BI->getSuccessor(0) == BI->getSuccessor(1)) continue; - Value *Cond = skipTrivialSelect(BI->getCondition()); + // If BI's condition is 'select _, true, false', simplify it to confuse + // matchers + Value *Cond = BI->getCondition(), *CondNext; + while (match(Cond, m_Select(m_Value(CondNext), m_One(), m_Zero()))) + Cond = CondNext; + BI->setCondition(Cond); + if (isa(Cond)) continue; - if (L.isLoopInvariant(Cond)) { - UnswitchCandidates.push_back({BI, {Cond}}); + if (L.isLoopInvariant(BI->getCondition())) { + UnswitchCandidates.push_back({BI, {BI->getCondition()}}); continue; } - Instruction &CondI = *cast(Cond); + Instruction &CondI = *cast(BI->getCondition()); if (match(&CondI, m_CombineOr(m_LogicalAnd(), m_LogicalOr()))) { TinyPtrVector Invariants = collectHomogenousInstGraphLoopInvariants(L, CondI, LI); @@ -2919,11 +2913,10 @@ static bool unswitchBestCondition( // its cost. if (!FullUnswitch) { auto &BI = cast(TI); - Value *Cond = skipTrivialSelect(BI.getCondition()); - if (match(Cond, m_LogicalAnd())) { + if (match(BI.getCondition(), m_LogicalAnd())) { if (SuccBB == BI.getSuccessor(1)) continue; - } else if (match(Cond, m_LogicalOr())) { + } else if (match(BI.getCondition(), m_LogicalOr())) { if (SuccBB == BI.getSuccessor(0)) continue; } else if ((PartialIVInfo.KnownValue->isOneValue() && diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll index ff9feab4a74c02..7b8cf5fd85778a 100644 --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-freeze.ll @@ -2346,7 +2346,7 @@ define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c. ; CHECK: loop: ; 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-NEXT: br i1 true, label [[LOOP]], label [[EXIT_SPLIT:%.*]] ; CHECK: exit.split: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-invariant-select-bug.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-invariant-select-bug.ll index 3abd1bd683fdb6..4097d3523ab30b 100644 --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-invariant-select-bug.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-invariant-select-bug.ll @@ -16,7 +16,7 @@ define void @foo() { ; CHECK-NEXT: br label [[HEADER:%.*]] ; CHECK: header: ; CHECK-NEXT: [[VAL:%.*]] = select i1 true, i1 true, i1 false -; CHECK-NEXT: br i1 [[VAL]], label [[EXIT:%.*]], label [[HEADER]] +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[HEADER]] ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll index 001595d8217452..86441591b8f3e4 100644 --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll @@ -4277,7 +4277,7 @@ loop_begin: ; CHECK-NEXT: %[[V2:.*]] = load i1, i1* %ptr2 ; CHECK-NEXT: %[[AND1:.*]] = select i1 %[[V1]], i1 true, i1 false ; CHECK-NEXT: %[[AND2:.*]] = select i1 %[[AND1]], i1 true, i1 false -; CHECK-NEXT: br i1 %[[AND2]], label %loop_a, label %loop_b +; CHECK-NEXT: br i1 %[[V1]], label %loop_a, label %loop_b loop_a: call i32 @a() @@ -4357,7 +4357,7 @@ loop_begin: ; CHECK-NEXT: %[[V2:.*]] = load i1, i1* %ptr2 ; CHECK-NEXT: %[[AND1:.*]] = select i1 %[[V1]], i1 true, i1 false ; CHECK-NEXT: %[[AND2:.*]] = select i1 %[[AND1]], i1 true, i1 false -; CHECK-NEXT: br i1 %[[AND2]], label %loop_b, label %loop_a +; CHECK-NEXT: br i1 %[[V1]], label %loop_b, label %loop_a loop_a: call i32 @a() diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll index 5e68c5ca32e87a..831dd5f6c03945 100644 --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll @@ -11,9 +11,14 @@ define i32 @need_freeze_of_individual_or_conditions1(i1 %cond1, i1 %cond2, i1 %c ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4_FR]], [[COND1_FR]] ; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] ; CHECK: entry.split: +; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2:%.*]] +; CHECK-NEXT: [[COND3_FR:%.*]] = freeze i1 [[COND3:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[COND2_FR]], [[COND3_FR]] +; CHECK-NEXT: br i1 [[TMP1]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; CHECK: entry.split.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[OR:%.*]] = or i1 [[COND2:%.*]], [[COND3:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i1 true, true ; CHECK-NEXT: [[AND1:%.*]] = and i1 [[OR]], true ; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 true, i1 false ; CHECK-NEXT: br i1 [[AND2]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]] @@ -21,6 +26,8 @@ define i32 @need_freeze_of_individual_or_conditions1(i1 %cond1, i1 %cond2, i1 %c ; CHECK-NEXT: call void @some_func() ; CHECK-NEXT: br label [[LOOP_HEADER]] ; CHECK: exit: +; CHECK-NEXT: br label [[EXIT_SPLIT1]] +; CHECK: exit.split1: ; CHECK-NEXT: br label [[EXIT_SPLIT]] ; CHECK: exit.split: ; CHECK-NEXT: ret i32 0 @@ -49,9 +56,14 @@ define i32 @need_freeze_of_individual_or_conditions2(i1 noundef %cond1, i1 %cond ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4_FR]], [[COND1:%.*]] ; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] ; CHECK: entry.split: +; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2:%.*]] +; CHECK-NEXT: [[COND3_FR:%.*]] = freeze i1 [[COND3:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[COND2_FR]], [[COND3_FR]] +; CHECK-NEXT: br i1 [[TMP1]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; CHECK: entry.split.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[OR:%.*]] = or i1 [[COND2:%.*]], [[COND3:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i1 true, true ; CHECK-NEXT: [[AND1:%.*]] = and i1 [[OR]], true ; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 true, i1 false ; CHECK-NEXT: br i1 [[AND2]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]] @@ -59,6 +71,8 @@ define i32 @need_freeze_of_individual_or_conditions2(i1 noundef %cond1, i1 %cond ; CHECK-NEXT: call void @some_func() ; CHECK-NEXT: br label [[LOOP_HEADER]] ; CHECK: exit: +; CHECK-NEXT: br label [[EXIT_SPLIT1]] +; CHECK: exit.split1: ; CHECK-NEXT: br label [[EXIT_SPLIT]] ; CHECK: exit.split: ; CHECK-NEXT: ret i32 0 @@ -87,9 +101,14 @@ define i32 @need_freeze_of_individual_or_conditions3(i1 %cond1, i1 %cond2, i1 %c ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4:%.*]], [[COND1_FR]] ; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] ; CHECK: entry.split: +; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2:%.*]] +; CHECK-NEXT: [[COND3_FR:%.*]] = freeze i1 [[COND3:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[COND2_FR]], [[COND3_FR]] +; CHECK-NEXT: br i1 [[TMP1]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; CHECK: entry.split.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[OR:%.*]] = or i1 [[COND2:%.*]], [[COND3:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or i1 true, true ; CHECK-NEXT: [[AND1:%.*]] = and i1 [[OR]], true ; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 true, i1 false ; CHECK-NEXT: br i1 [[AND2]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]] @@ -97,6 +116,8 @@ define i32 @need_freeze_of_individual_or_conditions3(i1 %cond1, i1 %cond2, i1 %c ; CHECK-NEXT: call void @some_func() ; CHECK-NEXT: br label [[LOOP_HEADER]] ; CHECK: exit: +; CHECK-NEXT: br label [[EXIT_SPLIT1]] +; CHECK: exit.split1: ; CHECK-NEXT: br label [[EXIT_SPLIT]] ; CHECK: exit.split: ; CHECK-NEXT: ret i32 0 diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll index 2af8dec51db2bb..320813542dae3b 100644 --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll @@ -8,15 +8,20 @@ declare void @some_func() define void @test_select_logical_and_or_with_and_1(i1 noundef %cond1, i1 noundef %cond2) { ; CHECK-LABEL: @test_select_logical_and_or_with_and_1( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND2:%.*]], [[COND1:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 [[COND2:%.*]], [[COND1:%.*]] +; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, false ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false ; CHECK-NEXT: br i1 [[SEL]], label [[EXIT:%.*]], label [[LOOP_LATCH:%.*]] ; CHECK: loop.latch: ; CHECK-NEXT: call void @some_func() ; CHECK-NEXT: br label [[LOOP_HEADER]] ; CHECK: exit: +; CHECK-NEXT: br label [[EXIT_SPLIT]] +; CHECK: exit.split: ; CHECK-NEXT: ret void ; entry: @@ -109,15 +114,20 @@ exit: define void @test_select_logical_and_or_with_or_2(i1 noundef %cond1, i1 noundef %cond2) { ; CHECK-LABEL: @test_select_logical_and_or_with_or_2( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND2:%.*]], [[COND1:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] +; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: -; CHECK-NEXT: [[COND_AND1:%.*]] = or i1 [[COND2:%.*]], [[COND1:%.*]] +; CHECK-NEXT: [[COND_AND1:%.*]] = or i1 true, true ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND_AND1]], i1 true, i1 false ; CHECK-NEXT: br i1 [[SEL]], label [[LOOP_LATCH:%.*]], label [[EXIT:%.*]] ; CHECK: loop.latch: ; CHECK-NEXT: call void @some_func() ; CHECK-NEXT: br label [[LOOP_HEADER]] ; CHECK: exit: +; CHECK-NEXT: br label [[EXIT_SPLIT]] +; CHECK: exit.split: ; CHECK-NEXT: ret void ; entry: @@ -137,6 +147,8 @@ exit: } ; Check that loop unswitch looks through a combination of or and select instructions. +; Note that cond6 can be unswitched because `select i1 %cond_or5, i1 true, i1 false` is +; both logical-or and logical-and. define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 %cond2, i1 %cond3, i1 %cond4, i1 %cond5, i1 %cond6) { ; CHECK-LABEL: @test_partial_condition_unswitch_or_select( ; CHECK-NEXT: entry: @@ -149,6 +161,9 @@ define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 % ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1_FR]] ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split: +; CHECK-NEXT: [[COND6_FR:%.*]] = freeze i1 [[COND6:%.*]] +; CHECK-NEXT: br i1 [[COND6_FR]], label [[LOOP_EXIT_SPLIT1:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]] +; CHECK: entry.split.split: ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] ; CHECK: loop_begin: ; CHECK-NEXT: [[VAR_VAL:%.*]] = load i32, i32* [[VAR:%.*]], align 4 @@ -157,7 +172,7 @@ define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 % ; CHECK-NEXT: [[COND_OR2:%.*]] = or i1 false, false ; CHECK-NEXT: [[COND_OR3:%.*]] = or i1 [[COND_OR1]], [[COND_OR2]] ; CHECK-NEXT: [[COND_XOR1:%.*]] = xor i1 [[COND5:%.*]], [[VAR_COND]] -; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 [[COND6:%.*]], [[VAR_COND]] +; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, [[VAR_COND]] ; CHECK-NEXT: [[COND_OR4:%.*]] = or i1 [[COND_XOR1]], [[COND_AND1]] ; CHECK-NEXT: [[COND_OR5:%.*]] = select i1 [[COND_OR3]], i1 true, i1 [[COND_OR4]] ; CHECK-NEXT: [[COND_OR6:%.*]] = select i1 [[COND_OR5]], i1 true, i1 false @@ -166,6 +181,8 @@ define i32 @test_partial_condition_unswitch_or_select(i32* %var, i1 %cond1, i1 % ; CHECK-NEXT: call void @some_func() #[[ATTR0:[0-9]+]] ; CHECK-NEXT: br label [[LOOP_BEGIN]] ; CHECK: loop_exit: +; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT1]] +; CHECK: loop_exit.split1: ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]] ; CHECK: loop_exit.split: ; CHECK-NEXT: ret i32 0 @@ -194,8 +211,6 @@ loop_exit: ret i32 0 } -; Same as test_partial_condition_unswitch_or_select, but with arguments marked -; as noundef. define i32 @test_partial_condition_unswitch_or_select_noundef(i32* noundef %var, i1 noundef %cond1, i1 noundef %cond2, i1 noundef %cond3, i1 noundef %cond4, i1 noundef %cond5, i1 noundef %cond6) { ; CHECK-LABEL: @test_partial_condition_unswitch_or_select_noundef( ; CHECK-NEXT: entry: @@ -204,6 +219,8 @@ define i32 @test_partial_condition_unswitch_or_select_noundef(i32* noundef %var, ; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1:%.*]] ; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split: +; CHECK-NEXT: br i1 [[COND6:%.*]], label [[LOOP_EXIT_SPLIT1:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]] +; CHECK: entry.split.split: ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]] ; CHECK: loop_begin: ; CHECK-NEXT: [[VAR_VAL:%.*]] = load i32, i32* [[VAR:%.*]], align 4 @@ -212,7 +229,7 @@ define i32 @test_partial_condition_unswitch_or_select_noundef(i32* noundef %var, ; CHECK-NEXT: [[COND_OR2:%.*]] = or i1 false, false ; CHECK-NEXT: [[COND_OR3:%.*]] = or i1 [[COND_OR1]], [[COND_OR2]] ; CHECK-NEXT: [[COND_XOR1:%.*]] = xor i1 [[COND5:%.*]], [[VAR_COND]] -; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 [[COND6:%.*]], [[VAR_COND]] +; CHECK-NEXT: [[COND_AND1:%.*]] = and i1 false, [[VAR_COND]] ; CHECK-NEXT: [[COND_OR4:%.*]] = or i1 [[COND_XOR1]], [[COND_AND1]] ; CHECK-NEXT: [[COND_OR5:%.*]] = select i1 [[COND_OR3]], i1 true, i1 [[COND_OR4]] ; CHECK-NEXT: [[COND_OR6:%.*]] = select i1 [[COND_OR5]], i1 true, i1 false @@ -221,6 +238,8 @@ define i32 @test_partial_condition_unswitch_or_select_noundef(i32* noundef %var, ; CHECK-NEXT: call void @some_func() #[[ATTR0]] ; CHECK-NEXT: br label [[LOOP_BEGIN]] ; CHECK: loop_exit: +; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT1]] +; CHECK: loop_exit.split1: ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]] ; CHECK: loop_exit.split: ; CHECK-NEXT: ret i32 0