[llvm] 181628b - [SimpleLoopUnswitch] Fix introduction of UB when hoisted condition may be undef or poison

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 27 16:42:49 PST 2020


Juneyong,

Not entirely surprisingly, we're seeing some performance regressions 
from these changes.  Looking at some of the IR, it looks like pretty 
basic handling of freeze might be missing.  I'm seeing what looks to be 
failures to speculate freezes outside of loops, and (possibly) failures 
to CSE identical free instructions.

Given that, I need to ask that this patch be reverted until that 
infrastructure can be addressed.

Philip

p.s. Here's small test cases for some of the obvious cases.  -O3 doesn't 
change them.


define i1 @cse(i1 %a) {
   %b = freeze i1 %a
   %c = freeze i1 %a
   %and = and i1 %b, %c
   ret i1 %and
}

define void @licm(i1 %a) {
entry:
   br label %loop
loop:
   %b = freeze i1 %a
   call void @use(i1 %b)
   br label %loop
}

declare void @use(i1)


On 2/25/20 8:47 PM, Juneyoung Lee via llvm-commits wrote:
> Author: Juneyoung Lee
> Date: 2020-02-26T13:47:33+09:00
> New Revision: 181628b52d390f2136fb5a63fe644d230a9b822d
>
> URL: https://github.com/llvm/llvm-project/commit/181628b52d390f2136fb5a63fe644d230a9b822d
> DIFF: https://github.com/llvm/llvm-project/commit/181628b52d390f2136fb5a63fe644d230a9b822d.diff
>
> LOG: [SimpleLoopUnswitch] Fix introduction of UB when hoisted condition may be undef or poison
>
> Summary:
> Loop unswitch hoists branches on loop-invariant conditions. However, if this
> condition is poison/undef and the branch wasn't originally reachable, loop
> unswitch introduces UB (since the optimized code will branch on poison/undef and
> the original one didn't)).
> We fix this problem by freezing the condition to ensure we don't introduce UB.
>
> We will now transform the following:
>    while (...) {
>      if (C) { A }
>      else   { B }
>    }
>
> Into:
>    C' = freeze(C)
>    if (C') {
>      while (...) { A }
>    } else {
>      while (...) { B }
>    }
>
> This patch fixes the root cause of the following bug reports (which use the old loop unswitch, but can be reproduced with minor changes in the code and -enable-nontrivial-unswitch):
> - https://llvm.org/bugs/show_bug.cgi?id=27506
> - https://llvm.org/bugs/show_bug.cgi?id=31652
>
> Reviewers: reames, majnemer, chenli, sanjoy, hfinkel
>
> Reviewed By: reames
>
> Subscribers: hiraditya, jvesely, nhaehnle, filcab, regehr, trentxintong, nlopes, llvm-commits, mzolotukhin
>
> Tags: #llvm
>
> Differential Revision: https://reviews.llvm.org/D29015
>
> Added:
>      
>
> Modified:
>      llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
>      llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll
>      llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll
>      llvm/test/Transforms/SimpleLoopUnswitch/exponential-switch-unswitch.ll
>      llvm/test/Transforms/SimpleLoopUnswitch/guards.ll
>      llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll
>      llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
>
> Removed:
>      
>
>
> ################################################################################
> diff  --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
> index 8f9db3db26c4..4a82fd939dae 100644
> --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
> +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
> @@ -26,7 +26,9 @@
>   #include "llvm/Analysis/LoopPass.h"
>   #include "llvm/Analysis/MemorySSA.h"
>   #include "llvm/Analysis/MemorySSAUpdater.h"
> +#include "llvm/Analysis/MustExecute.h"
>   #include "llvm/Analysis/Utils/Local.h"
> +#include "llvm/Analysis/ValueTracking.h"
>   #include "llvm/IR/BasicBlock.h"
>   #include "llvm/IR/Constant.h"
>   #include "llvm/IR/Constants.h"
> @@ -180,11 +182,14 @@ static void buildPartialUnswitchConditionalBranch(BasicBlock &BB,
>                                                     ArrayRef<Value *> Invariants,
>                                                     bool Direction,
>                                                     BasicBlock &UnswitchedSucc,
> -                                                  BasicBlock &NormalSucc) {
> +                                                  BasicBlock &NormalSucc,
> +                                                  bool insertFreeze) {
>     IRBuilder<> IRB(&BB);
> -
> +
>     Value *Cond = Direction ? IRB.CreateOr(Invariants) :
>       IRB.CreateAnd(Invariants);
> +  if (insertFreeze)
> +    Cond = IRB.CreateFreeze(Cond, Cond->getName() + ".fr");
>     IRB.CreateCondBr(Cond, Direction ? &UnswitchedSucc : &NormalSucc,
>                      Direction ? &NormalSucc : &UnswitchedSucc);
>   }
> @@ -498,7 +503,7 @@ static bool unswitchTrivialBranch(Loop &L, BranchInst &BI, DominatorTree &DT,
>                    Instruction::And &&
>                "Must have an `and` of `i1`s for the condition!");
>       buildPartialUnswitchConditionalBranch(*OldPH, Invariants, ExitDirection,
> -                                          *UnswitchedBB, *NewPH);
> +                                          *UnswitchedBB, *NewPH, false);
>     }
>   
>     // Update the dominator tree with the added edge.
> @@ -2009,6 +2014,10 @@ static void unswitchNontrivialInvariants(
>         SE->forgetTopmostLoop(&L);
>     }
>   
> +  ICFLoopSafetyInfo SafetyInfo(&DT);
> +  SafetyInfo.computeLoopSafetyInfo(&L);
> +  bool insertFreeze = !SafetyInfo.isGuaranteedToExecute(TI, &DT, &L);
> +
>     // If the edge from this terminator to a successor dominates that successor,
>     // store a map from each block in its dominator subtree to it. This lets us
>     // tell when cloning for a particular successor if a block is dominated by
> @@ -2066,6 +2075,12 @@ static void unswitchNontrivialInvariants(
>         BasicBlock *ClonedPH = ClonedPHs.begin()->second;
>         BI->setSuccessor(ClonedSucc, ClonedPH);
>         BI->setSuccessor(1 - ClonedSucc, LoopPH);
> +      if (insertFreeze) {
> +        auto Cond = BI->getCondition();
> +        if (!isGuaranteedNotToBeUndefOrPoison(Cond))
> +          BI->setCondition(new FreezeInst(Cond, Cond->getName() + ".fr", BI));
> +      }
> +
>         DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});
>       } else {
>         assert(SI && "Must either be a branch or switch!");
> @@ -2080,6 +2095,12 @@ static void unswitchNontrivialInvariants(
>           else
>             Case.setSuccessor(ClonedPHs.find(Case.getCaseSuccessor())->second);
>   
> +      if (insertFreeze) {
> +        auto Cond = SI->getCondition();
> +        if (!isGuaranteedNotToBeUndefOrPoison(Cond))
> +          SI->setCondition(new FreezeInst(Cond, Cond->getName() + ".fr", SI));
> +      }
> +
>         // We need to use the set to populate domtree updates as even when there
>         // are multiple cases pointing at the same successor we only want to
>         // remove and insert one edge in the domtree.
> @@ -2156,7 +2177,7 @@ static void unswitchNontrivialInvariants(
>       // When doing a partial unswitch, we have to do a bit more work to build up
>       // the branch in the split block.
>       buildPartialUnswitchConditionalBranch(*SplitBB, Invariants, Direction,
> -                                          *ClonedPH, *LoopPH);
> +                                          *ClonedPH, *LoopPH, insertFreeze);
>       DTUpdates.push_back({DominatorTree::Insert, SplitBB, ClonedPH});
>   
>       if (MSSAU) {
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll
> index d2ca06357cfe..04d027cd502c 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested.ll
> @@ -85,8 +85,14 @@
>   
>   declare void @bar()
>   
> -define void @loop_nested3_conds5(i32* %addr, i1 %c1, i1 %c2, i1 %c3, i1 %c4, i1 %c5) {
> +define void @loop_nested3_conds5(i32* %addr, i1 %c1i, i1 %c2i, i1 %c3i, i1 %c4i, i1 %c5i) {
>   entry:
> +  ; c1 ~ c5 are guaranteed to be never undef or poison.
> +  %c1 = freeze i1 %c1i
> +  %c2 = freeze i1 %c2i
> +  %c3 = freeze i1 %c3i
> +  %c4 = freeze i1 %c4i
> +  %c5 = freeze i1 %c5i
>     %addr1 = getelementptr i32, i32* %addr, i64 0
>     %addr2 = getelementptr i32, i32* %addr, i64 1
>     %addr3 = getelementptr i32, i32* %addr, i64 2
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll
> index e8879e79c53f..26179ad9068e 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-nontrivial-unswitch-nested2.ll
> @@ -97,8 +97,14 @@
>   
>   declare void @bar()
>   
> -define void @loop_nested3_conds5(i32* %addr, i1 %c1, i1 %c2, i1 %c3, i1 %c4, i1 %c5) {
> +define void @loop_nested3_conds5(i32* %addr, i1 %c1i, i1 %c2i, i1 %c3i, i1 %c4i, i1 %c5i) {
>   entry:
> +  ; c1 ~ c5 are guaranteed to be never undef or poison.
> +  %c1 = freeze i1 %c1i
> +  %c2 = freeze i1 %c2i
> +  %c3 = freeze i1 %c3i
> +  %c4 = freeze i1 %c4i
> +  %c5 = freeze i1 %c5i
>     %addr1 = getelementptr i32, i32* %addr, i64 0
>     %addr2 = getelementptr i32, i32* %addr, i64 1
>     %addr3 = getelementptr i32, i32* %addr, i64 2
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-switch-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-switch-unswitch.ll
> index 35d431e5ee26..6606a1931d4d 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/exponential-switch-unswitch.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/exponential-switch-unswitch.ll
> @@ -86,8 +86,11 @@
>   ; LOOP-MAX-COUNT-111:     Loop at depth 2 containing:
>   ; LOOP-MAX-NOT: Loop at depth 2 containing:
>   
> -define i32 @loop_switch(i32* %addr, i32 %c1, i32 %c2) {
> +define i32 @loop_switch(i32* %addr, i32 %c1i, i32 %c2i) {
>   entry:
> +  ; c1, c2 are guaranteed to be never undef or poison.
> +  %c1 = freeze i32 %c1i
> +  %c2 = freeze i32 %c2i
>     %addr1 = getelementptr i32, i32* %addr, i64 0
>     %addr2 = getelementptr i32, i32* %addr, i64 1
>     %check0 = icmp eq i32 %c2, 0
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/guards.ll b/llvm/test/Transforms/SimpleLoopUnswitch/guards.ll
> index de57075b6222..9365829f976a 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/guards.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/guards.ll
> @@ -81,7 +81,8 @@ exit:
>   define void @test_conditional_guards(i1 %cond, i32 %N) {
>   ; CHECK-LABEL: @test_conditional_guards(
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
> +; CHECK-NEXT:    [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
> +; CHECK-NEXT:    br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
>   ; CHECK:       entry.split.us:
>   ; CHECK-NEXT:    br label [[LOOP_US:%.*]]
>   ; CHECK:       loop.us:
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll
> index 692799db1c60..7b2c8280e7a3 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-cost.ll
> @@ -57,7 +57,8 @@ define void @test_unswitch(i1* %ptr, i1 %cond) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     call void @x()
> @@ -127,7 +128,8 @@ define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     call void @x()
> @@ -208,7 +210,8 @@ define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     call void @x()
> @@ -364,7 +367,8 @@ define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     call void @x()
> @@ -441,7 +445,8 @@ define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     call void @x()
>
> diff  --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
> index 0aec52d447d5..02b3bd5b4c3d 100644
> --- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
> +++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
> @@ -814,7 +814,8 @@ inner_loop_begin:
>   ; CHECK-NEXT:    %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
>   ; CHECK-NEXT:    %[[B:.*]] = load i32, i32* %b.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
>   
>   inner_inner_loop_begin:
>     %v1 = load i1, i1* %ptr
> @@ -967,7 +968,8 @@ inner_loop_begin:
>   ; CHECK-NEXT:    %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
>   ; CHECK-NEXT:    %[[B:.*]] = load i32, i32* %b.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
>   
>   inner_inner_loop_begin:
>     %v1 = load i1, i1* %ptr
> @@ -1120,7 +1122,8 @@ inner_loop_begin:
>   ; CHECK-NEXT:    %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
>   ; CHECK-NEXT:    %[[B:.*]] = load i32, i32* %b.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
>   
>   inner_inner_loop_begin:
>     %v1 = load i1, i1* %ptr
> @@ -1240,7 +1243,8 @@ inner_loop_begin:
>   ; CHECK-NEXT:    %[[A_INNER_PHI:.*]] = phi i32 [ %[[A]], %loop_begin ], [ %[[A2:.*]], %inner_inner_loop_exit ]
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
>   ; CHECK-NEXT:    %[[B:.*]] = load i32, i32* %b.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_begin.split.us, label %inner_loop_begin.split
>   
>   inner_inner_loop_begin:
>     %v1 = load i1, i1* %ptr
> @@ -1482,7 +1486,8 @@ define i32 @test10a(i1* %ptr, i1 %cond, i32* %a.ptr) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     %a = load i32, i32* %a.ptr
> @@ -1562,7 +1567,8 @@ define i32 @test10b(i1* %ptr, i1 %cond, i32* %a.ptr) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     %a = load i32, i32* %a.ptr
> @@ -1661,7 +1667,8 @@ inner_loop_ph:
>     br label %inner_loop_begin
>   ; CHECK:       inner_loop_ph:
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
>   
>   inner_loop_begin:
>     call void @sink1(i32 %b)
> @@ -1755,7 +1762,8 @@ inner_loop_ph:
>     br label %inner_loop_begin
>   ; CHECK:       inner_loop_ph:
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_loop_ph.split.us, label %inner_loop_ph.split
>   
>   inner_loop_begin:
>     call void @sink1(i32 %b)
> @@ -1853,7 +1861,8 @@ inner_inner_loop_ph:
>     br label %inner_inner_loop_begin
>   ; CHECK:       inner_inner_loop_ph:
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
>   
>   inner_inner_loop_begin:
>     call void @sink1(i32 %b)
> @@ -1961,7 +1970,8 @@ inner_inner_loop_ph:
>     br label %inner_inner_loop_begin
>   ; CHECK:       inner_inner_loop_ph:
>   ; CHECK-NEXT:    %[[COND:.*]] = load i1, i1* %cond.ptr
> -; CHECK-NEXT:    br i1 %[[COND]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %[[COND]]
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %inner_inner_loop_ph.split.us, label %inner_inner_loop_ph.split
>   
>   inner_inner_loop_begin:
>     call void @sink1(i32 %b)
> @@ -2048,7 +2058,8 @@ define i32 @test13a(i1* %ptr, i1 %cond, i32* %a.ptr, i32* %b.ptr) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     %a = load i32, i32* %a.ptr
> @@ -2172,7 +2183,8 @@ define i32 @test13b(i1* %ptr, i1 %cond, i32* %a.ptr, i32* %b.ptr) {
>   entry:
>     br label %loop_begin
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    br i1 %cond, label %entry.split.us, label %entry.split
> +; CHECK-NEXT:    %[[COND_FR:.*]] = freeze i1 %cond
> +; CHECK-NEXT:    br i1 %[[COND_FR]], label %entry.split.us, label %entry.split
>   
>   loop_begin:
>     %a = load i32, i32* %a.ptr
> @@ -2420,9 +2432,10 @@ loop_exit:
>   ; paths to reach an inner loop after unswitching, and one of them is via the
>   ; predecessors of the unswitched loop header. That can allow us to find the loop
>   ; through multiple
> diff erent paths.
> -define void @test21(i1 %a, i1 %b) {
> +define void @test21(i1 %a0, i1 %b) {
>   ; CHECK-LABEL: @test21(
>   bb:
> +  %a = freeze i1 %a0
>     br label %bb3
>   ; CHECK-NOT:     br i1 %a
>   ;
> @@ -2553,7 +2566,8 @@ define void @test23(i1 %arg, i1* %ptr) {
>   entry:
>     br label %outer.header
>   ; CHECK:       entry:
> -; CHECK-NEXT:    br i1 %arg,
> +; CHECK-NEXT:    %[[ARG_FR:.*]] = freeze i1 %arg
> +; CHECK-NEXT:    br i1 %[[ARG_FR]],
>   ;
>   ; Just verify that we unswitched the correct bits. We should call `@f` twice in
>   ; one unswitch and `@f` and then `@g` in the other.
> @@ -3064,7 +3078,8 @@ define i32 @test29(i32 %arg) {
>   entry:
>     br label %header
>   ; CHECK-NEXT:  entry:
> -; CHECK-NEXT:    switch i32 %arg, label %[[ENTRY_SPLIT_C:.*]] [
> +; CHECK-NEXT:    %arg.fr = freeze i32 %arg
> +; CHECK-NEXT:    switch i32 %arg.fr, label %[[ENTRY_SPLIT_C:.*]] [
>   ; CHECK-NEXT:      i32 0, label %[[ENTRY_SPLIT_A:.*]]
>   ; CHECK-NEXT:      i32 1, label %[[ENTRY_SPLIT_A]]
>   ; CHECK-NEXT:      i32 2, label %[[ENTRY_SPLIT_B:.*]]
> @@ -3242,11 +3257,13 @@ exit:
>   ; a loop exit edge as those can in some cases be special. Among other things,
>   ; this includes an LCSSA phi with multiple entries despite being a dedicated
>   ; exit block.
> -define i32 @test30(i32 %arg) {
> +define i32 @test30(i32 %arg0) {
>   ; CHECK-LABEL: define i32 @test30(
>   entry:
> +  %arg = freeze i32 %arg0
>     br label %header
>   ; CHECK-NEXT:  entry:
> +; CHECK-NEXT:    %arg = freeze i32 %arg0
>   ; CHECK-NEXT:    switch i32 %arg, label %[[ENTRY_SPLIT_EXIT:.*]] [
>   ; CHECK-NEXT:      i32 -1, label %[[ENTRY_SPLIT_EXIT]]
>   ; CHECK-NEXT:      i32 0, label %[[ENTRY_SPLIT_A:.*]]
> @@ -3426,7 +3443,8 @@ b.header:
>     br label %c.header
>   ; CHECK:       b.header:
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[B_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[C_HEADER_US:.*]]
> @@ -3501,7 +3519,8 @@ b.header:
>   ; CHECK:       b.header:
>   ; CHECK-NEXT:    %x.b = load i32, i32* %ptr
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[B_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[C_HEADER_US:.*]]
> @@ -3589,7 +3608,8 @@ b.header:
>   ; CHECK:       b.header:
>   ; CHECK-NEXT:    %x.b = load i32, i32* %ptr
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[B_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[C_HEADER_US:.*]]
> @@ -3669,7 +3689,8 @@ b.header:
>   ; CHECK:       b.header:
>   ; CHECK-NEXT:    %x.b = load i32, i32* %ptr
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[B_HEADER_SPLIT_US:.*]], label %[[B_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[B_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[C_HEADER_US:.*]]
> @@ -3767,7 +3788,8 @@ c.header:
>     br label %d.header
>   ; CHECK:       c.header:
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[C_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[D_HEADER_US:.*]]
> @@ -3880,7 +3902,8 @@ c.header:
>   ; CHECK:       c.header:
>   ; CHECK-NEXT:    %x.c = load i32, i32* %ptr
>   ; CHECK-NEXT:    %v1 = call i1 @cond()
> -; CHECK-NEXT:    br i1 %v1, label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
> +; CHECK-NEXT:    %[[V1_FR:.*]] = freeze i1 %v1
> +; CHECK-NEXT:    br i1 %[[V1_FR]], label %[[C_HEADER_SPLIT_US:.*]], label %[[C_HEADER_SPLIT:.*]]
>   ;
>   ; CHECK:       [[C_HEADER_SPLIT_US]]:
>   ; CHECK-NEXT:    br label %[[D_HEADER_US:.*]]
> @@ -3962,7 +3985,8 @@ b.header:
>   ; CHECK:       b.header:
>   ; CHECK-NEXT:    %x.b = load i32, i32* %ptr
>   ; CHECK-NEXT:    %v1 = call i32 @cond.i32()
> -; CHECK-NEXT:    switch i32 %v1, label %[[B_HEADER_SPLIT:.*]] [
> +; CHECK-NEXT:    %[[V1_FR]] = freeze i32 %v1
> +; CHECK-NEXT:    switch i32 %[[V1_FR]], label %[[B_HEADER_SPLIT:.*]] [
>   ; CHECK-NEXT:      i32 1, label %[[B_HEADER_SPLIT_US:.*]]
>   ; CHECK-NEXT:      i32 2, label %[[B_HEADER_SPLIT_US]]
>   ; CHECK-NEXT:      i32 3, label %[[B_HEADER_SPLIT_US]]
>
>
>          
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list