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 @@ -204,13 +204,19 @@ /// branch on a single value. static void buildPartialUnswitchConditionalBranch( BasicBlock &BB, ArrayRef Invariants, bool Direction, - BasicBlock &UnswitchedSucc, BasicBlock &NormalSucc, bool InsertFreeze) { + BasicBlock &UnswitchedSucc, BasicBlock &NormalSucc, bool InsertFreeze, + Instruction *I, AssumptionCache *AC, DominatorTree &DT) { IRBuilder<> IRB(&BB); - Value *Cond = Direction ? IRB.CreateOr(Invariants) : - IRB.CreateAnd(Invariants); - if (InsertFreeze) - Cond = IRB.CreateFreeze(Cond, Cond->getName() + ".fr"); + SmallVector FrozenInvariants; + for (Value *Inv : Invariants) { + if (InsertFreeze && !isGuaranteedNotToBeUndefOrPoison(Inv, AC, I, &DT)) + Inv = IRB.CreateFreeze(Inv, Inv->getName() + ".fr"); + FrozenInvariants.push_back(Inv); + } + + Value *Cond = Direction ? IRB.CreateOr(FrozenInvariants) + : IRB.CreateAnd(FrozenInvariants); IRB.CreateCondBr(Cond, Direction ? &UnswitchedSucc : &NormalSucc, Direction ? &NormalSucc : &UnswitchedSucc); } @@ -572,10 +578,7 @@ " condition!"); buildPartialUnswitchConditionalBranch( *OldPH, Invariants, ExitDirection, *UnswitchedBB, *NewPH, - FreezeLoopUnswitchCond && any_of(Invariants, [&](Value *C) { - return !isGuaranteedNotToBeUndefOrPoison(C, nullptr, - OldPH->getTerminator(), &DT); - })); + FreezeLoopUnswitchCond, OldPH->getTerminator(), nullptr, DT); } // Update the dominator tree with the added edge. @@ -2318,11 +2321,9 @@ buildPartialInvariantUnswitchConditionalBranch( *SplitBB, Invariants, Direction, *ClonedPH, *LoopPH, L, MSSAU); else { - buildPartialUnswitchConditionalBranch( - *SplitBB, Invariants, Direction, *ClonedPH, *LoopPH, - InsertFreeze && any_of(Invariants, [&](Value *C) { - return !isGuaranteedNotToBeUndefOrPoison(C, &AC, BI, &DT); - })); + buildPartialUnswitchConditionalBranch(*SplitBB, Invariants, Direction, + *ClonedPH, *LoopPH, InsertFreeze, + BI, &AC, DT); } DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH}); diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-freeze-individual-conditions.ll @@ -6,13 +6,15 @@ define i32 @need_freeze_of_individual_or_conditions1(i1 %cond1, i1 %cond2, i1 %cond3, i1 %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_or_conditions1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] +; CHECK-NEXT: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]] +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]] +; 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: [[TMP1:%.*]] = and i1 [[COND2:%.*]], [[COND3:%.*]] -; CHECK-NEXT: [[DOTFR2:%.*]] = freeze i1 [[TMP1]] -; CHECK-NEXT: br i1 [[DOTFR2]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; 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: @@ -50,13 +52,14 @@ define i32 @need_freeze_of_individual_or_conditions2(i1 noundef %cond1, i1 %cond2, i1 %cond3, i1 %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_or_conditions2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] +; CHECK-NEXT: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4_FR]], [[COND1:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] ; CHECK: entry.split: -; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[COND2:%.*]], [[COND3:%.*]] -; CHECK-NEXT: [[DOTFR2:%.*]] = freeze i1 [[TMP1]] -; CHECK-NEXT: br i1 [[DOTFR2]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; 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: @@ -94,13 +97,14 @@ define i32 @need_freeze_of_individual_or_conditions3(i1 %cond1, i1 %cond2, i1 %cond3, i1 noundef %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_or_conditions3( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[COND4:%.*]], [[COND1_FR]] +; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[EXIT_SPLIT:%.*]] ; CHECK: entry.split: -; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[COND2:%.*]], [[COND3:%.*]] -; CHECK-NEXT: [[DOTFR2:%.*]] = freeze i1 [[TMP1]] -; CHECK-NEXT: br i1 [[DOTFR2]], label [[ENTRY_SPLIT_SPLIT:%.*]], label [[EXIT_SPLIT1:%.*]] +; 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: @@ -138,9 +142,10 @@ define i32 @need_freeze_of_individual_and_conditions1(i1 %cond1, i1 %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_and_conditions1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]] +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4_FR]], [[COND1_FR]] +; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: @@ -172,9 +177,9 @@ define i32 @need_freeze_of_individual_and_conditions2(i1 noundef %cond1, i1 %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_and_conditions2( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4_FR]], [[COND1:%.*]] +; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: @@ -206,9 +211,9 @@ define i32 @need_freeze_of_individual_and_conditions3(i1 %cond1, i1 noundef %cond4) { ; CHECK-LABEL: @need_freeze_of_individual_and_conditions3( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP0]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND1_FR]] +; CHECK-NEXT: br i1 [[TMP0]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] ; CHECK: entry.split: ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] ; CHECK: loop.header: diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch-logical-and-or.ll @@ -152,11 +152,14 @@ 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: -; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4:%.*]], [[COND2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[TMP0]], [[COND3:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[TMP1]], [[COND1:%.*]] -; CHECK-NEXT: [[DOTFR:%.*]] = freeze i1 [[TMP2]] -; CHECK-NEXT: br i1 [[DOTFR]], label [[LOOP_EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK-NEXT: [[COND4_FR:%.*]] = freeze i1 [[COND4:%.*]] +; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2:%.*]] +; CHECK-NEXT: [[COND3_FR:%.*]] = freeze i1 [[COND3:%.*]] +; CHECK-NEXT: [[COND1_FR:%.*]] = freeze i1 [[COND1:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[COND4_FR]], [[COND2_FR]] +; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[TMP0]], [[COND3_FR]] +; 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:%.*]] diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll @@ -591,11 +591,14 @@ entry: br label %loop_begin ; CHECK-NEXT: entry: -; CHECK-NEXT: %[[INV_OR1:.*]] = or i1 %cond4, %cond2 -; CHECK-NEXT: %[[INV_OR2:.*]] = or i1 %[[INV_OR1]], %cond3 -; CHECK-NEXT: %[[INV_OR3:.*]] = or i1 %[[INV_OR2]], %cond1 -; CHECK-NEXT: [[FROZEN:%.+]] = freeze i1 %[[INV_OR3]] -; CHECK-NEXT: br i1 [[FROZEN]], label %loop_exit.split, label %entry.split +; CHECK-NEXT: %[[C4_FR:.+]] = freeze i1 %cond4 +; CHECK-NEXT: %[[C2_FR:.+]] = freeze i1 %cond2 +; CHECK-NEXT: %[[C3_FR:.+]] = freeze i1 %cond3 +; CHECK-NEXT: %[[C1_FR:.+]] = freeze i1 %cond1 +; CHECK-NEXT: %[[INV_OR1:.*]] = or i1 %[[C4_FR]], %[[C2_FR]] +; CHECK-NEXT: %[[INV_OR2:.*]] = or i1 %[[INV_OR1]], %[[C3_FR]] +; CHECK-NEXT: %[[INV_OR3:.*]] = or i1 %[[INV_OR2]], %[[C1_FR]] +; CHECK-NEXT: br i1 %[[INV_OR3]], label %loop_exit.split, label %entry.split ; ; CHECK: entry.split: ; CHECK-NEXT: br label %loop_begin