[llvm] 0b5bb69 - [GuardWidening] Freeze the introduced use. Re-land.

Serguei Katkov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 29 21:36:35 PDT 2023


Author: Serguei Katkov
Date: 2023-03-30T10:59:01+07:00
New Revision: 0b5bb6923f09ebc257ebed4ace1d8b6b113b2bf5

URL: https://github.com/llvm/llvm-project/commit/0b5bb6923f09ebc257ebed4ace1d8b6b113b2bf5
DIFF: https://github.com/llvm/llvm-project/commit/0b5bb6923f09ebc257ebed4ace1d8b6b113b2bf5.diff

LOG: [GuardWidening] Freeze the introduced use. Re-land.

Non-determenism is fixed.

Guard widening optimization is able to move the condition from one
guard to the previous one. As a result if the condition is poison
and orginal second guard is never executed but the first one does,
we introduce undefined behavior which was not observed in original
program.

To resolve the issue we must freeze the condition we are moving.
However optimization itself does not know how to work with freeze.
Additionally optimization is written in incremental way.
For example we have three guards
G1(base + 8 < L)
G2(base + 16 < L)
G3(base + 24 < L)

On the first step GW will combine G1 and G2 as
G1(base + 8 < L && freeze(base + 16 < L))
G2(true)
G3(base + 24 < L)

while combining G1 and G3 base appears to be different.

To keep optimization enabled after freezing the moving condition, the
freeze instruction is pushed as much as possible and later all uses
of freezed values are replaced with frozen version.

This is similar what instruction combining does but more aggressevely.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/GuardWidening.cpp
    llvm/test/Transforms/GuardWidening/basic-loop.ll
    llvm/test/Transforms/GuardWidening/basic.ll
    llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll
    llvm/test/Transforms/GuardWidening/hang.ll
    llvm/test/Transforms/GuardWidening/loop-schedule.ll
    llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll
    llvm/test/Transforms/GuardWidening/mixed_guards.ll
    llvm/test/Transforms/GuardWidening/posion.ll
    llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll
    llvm/test/Transforms/GuardWidening/profile-based-profitability_explicit.ll
    llvm/test/Transforms/GuardWidening/range-check-merging.ll
    llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
index 7100f538f38ad..032ce9ba9b82d 100644
--- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp
+++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp
@@ -69,6 +69,7 @@ using namespace llvm;
 
 STATISTIC(GuardsEliminated, "Number of eliminated guards");
 STATISTIC(CondBranchEliminated, "Number of eliminated conditional branches");
+STATISTIC(FreezeAdded, "Number of freeze instruction introduced");
 
 static cl::opt<bool>
     WidenBranchGuards("guard-widening-widen-branch-guards", cl::Hidden,
@@ -209,6 +210,10 @@ class GuardWideningImpl {
   bool widenCondCommon(Value *Cond0, Value *Cond1, Instruction *InsertPt,
                        Value *&Result, bool InvertCondition);
 
+  /// Adds freeze to Orig and push it as far as possible very aggressively.
+  /// Also replaces all uses of frozen instruction with frozen version.
+  Value *freezeAndPush(Value *Orig, Instruction *InsertPt);
+
   /// Represents a range check of the form \c Base + \c Offset u< \c Length,
   /// with the constraint that \c Length is not negative.  \c CheckInst is the
   /// pre-existing instruction in the IR that computes the result of this range
@@ -558,8 +563,80 @@ void GuardWideningImpl::makeAvailableAt(Value *V, Instruction *Loc) const {
     makeAvailableAt(Op, Loc);
 
   Inst->moveBefore(Loc);
-  // If we moved instruction before guard we must clean poison generating flags.
-  Inst->dropPoisonGeneratingFlags();
+}
+
+// Return Instruction before which we can insert freeze for the value V as close
+// to def as possible. If there is no place to add freeze, return nullptr.
+static Instruction *getFreezeInsertPt(Value *V, const DominatorTree &DT) {
+  auto *I = dyn_cast<Instruction>(V);
+  if (!I)
+    return &*DT.getRoot()->getFirstNonPHIOrDbgOrAlloca();
+
+  auto *Res = I->getInsertionPointAfterDef();
+  // If there is no place to add freeze - return nullptr.
+  if (!Res || !DT.dominates(I, Res))
+    return nullptr;
+
+  // If there is a User dominated by original I, then it should be dominated
+  // by Freeze instruction as well.
+  if (any_of(I->users(), [&](User *U) {
+        Instruction *User = cast<Instruction>(U);
+        return Res != User && DT.dominates(I, User) && !DT.dominates(Res, User);
+      }))
+    return nullptr;
+  return Res;
+}
+
+Value *GuardWideningImpl::freezeAndPush(Value *Orig, Instruction *InsertPt) {
+  if (isGuaranteedNotToBePoison(Orig, nullptr, InsertPt, &DT))
+    return Orig;
+  Instruction *InsertPtAtDef = getFreezeInsertPt(Orig, DT);
+  if (!InsertPtAtDef)
+    return new FreezeInst(Orig, "gw.freeze", InsertPt);
+  SmallSet<Value *, 16> Visited;
+  SmallVector<Value *, 16> Worklist;
+  SmallSet<Instruction *, 16> DropPoisonFlags;
+  SmallVector<Value *, 16> NeedFreeze;
+  Worklist.push_back(Orig);
+  while (!Worklist.empty()) {
+    Value *V = Worklist.pop_back_val();
+    if (!Visited.insert(V).second)
+      continue;
+
+    if (isGuaranteedNotToBePoison(V, nullptr, InsertPt, &DT))
+      continue;
+
+    Instruction *I = dyn_cast<Instruction>(V);
+    if (!I || canCreateUndefOrPoison(cast<Operator>(I),
+                                     /*ConsiderFlagsAndMetadata*/ false)) {
+      NeedFreeze.push_back(V);
+      continue;
+    }
+    // Check all operands. If for any of them we cannot insert Freeze,
+    // stop here. Otherwise, iterate.
+    if (any_of(I->operands(), [&](Value *Op) {
+          return isa<Instruction>(Op) && !getFreezeInsertPt(Op, DT);
+        })) {
+      NeedFreeze.push_back(I);
+      continue;
+    }
+    DropPoisonFlags.insert(I);
+    append_range(Worklist, I->operands());
+  }
+  for (Instruction *I : DropPoisonFlags)
+    I->dropPoisonGeneratingFlagsAndMetadata();
+
+  Value *Result = Orig;
+  for (Value *V : NeedFreeze) {
+    auto *FreezeInsertPt = getFreezeInsertPt(V, DT);
+    FreezeInst *FI = new FreezeInst(V, V->getName() + ".gw.fr", FreezeInsertPt);
+    ++FreezeAdded;
+    if (V == Orig)
+      Result = FI;
+    V->replaceUsesWithIf(FI, [&](Use & U)->bool { return U.getUser() != FI; });
+  }
+
+  return Result;
 }
 
 bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1,
@@ -621,6 +698,7 @@ bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1,
         }
         assert(Result && "Failed to find result value");
         Result->setName("wide.chk");
+        Result = freezeAndPush(Result, InsertPt);
       }
       return true;
     }
@@ -633,6 +711,7 @@ bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1,
     makeAvailableAt(Cond1, InsertPt);
     if (InvertCondition)
       Cond1 = BinaryOperator::CreateNot(Cond1, "inverted", InsertPt);
+    Cond1 = freezeAndPush(Cond1, InsertPt);
     Result = BinaryOperator::CreateAnd(Cond0, Cond1, "wide.chk", InsertPt);
   }
 

diff  --git a/llvm/test/Transforms/GuardWidening/basic-loop.ll b/llvm/test/Transforms/GuardWidening/basic-loop.ll
index 1626cca93cad3..956d920501c2c 100644
--- a/llvm/test/Transforms/GuardWidening/basic-loop.ll
+++ b/llvm/test/Transforms/GuardWidening/basic-loop.ll
@@ -10,11 +10,13 @@ declare void @llvm.experimental.guard(i1,...)
 define void @widen_within_loop(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
 ; CHECK-LABEL: @widen_within_loop(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
+; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
 ; CHECK-NEXT:    store i32 1, ptr @G, align 4
 ; CHECK-NEXT:    store i32 2, ptr @G, align 4
@@ -38,9 +40,11 @@ loop:
 define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
 ; CHECK-LABEL: @widen_into_preheader(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
-; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
+; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
@@ -102,8 +106,9 @@ exit:
 define void @widen_over_common_exit_to_ph(i1 %cond_0, i1 %cond_1, i1 %cond_2) {
 ; CHECK-LABEL: @widen_over_common_exit_to_ph(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2:%.*]]
 ; CHECK-NEXT:    store i32 0, ptr @G, align 4
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:

diff  --git a/llvm/test/Transforms/GuardWidening/basic.ll b/llvm/test/Transforms/GuardWidening/basic.ll
index dd504a4fc5fb3..096ea9057915c 100644
--- a/llvm/test/Transforms/GuardWidening/basic.ll
+++ b/llvm/test/Transforms/GuardWidening/basic.ll
@@ -9,7 +9,8 @@ declare void @llvm.experimental.guard(i1,...)
 define void @f_0(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_0(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
@@ -24,7 +25,8 @@ entry:
 define void @f_1(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_1(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
 ; CHECK:       left:
@@ -55,8 +57,9 @@ merge:
 define void @f_2(i32 %a, i32 %b) {
 ; CHECK-LABEL: @f_2(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
@@ -122,8 +125,9 @@ right:
 define void @f_4(i32 %a, i32 %b) {
 ; CHECK-LABEL: @f_4(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]]
@@ -204,8 +208,9 @@ entry:
 define void @f_7(i32 %a, ptr %cond_buf) {
 ; CHECK-LABEL: @f_7(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
 ; CHECK-NEXT:    [[COND_1:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1
-; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[COND_2:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
@@ -239,12 +244,13 @@ right:
 define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
 ; CHECK-LABEL: @f_8(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
 ; CHECK:       leave:
-; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]
@@ -332,9 +338,10 @@ no_loop:
 define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_11(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
 ; CHECK-NEXT:    br label [[INNER:%.*]]
 ; CHECK:       inner:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br i1 undef, label [[INNER]], label [[OUTER:%.*]]
 ; CHECK:       outer:
@@ -358,7 +365,8 @@ outer:
 define void @f_12(i32 %a0) {
 ; CHECK-LABEL: @f_12(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
+; CHECK-NEXT:    [[A0_GW_FR:%.*]] = freeze i32 [[A0:%.*]]
+; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0_GW_FR]], [[A0_GW_FR]]
 ; CHECK-NEXT:    [[A2:%.*]] = mul i32 [[A1]], [[A1]]
 ; CHECK-NEXT:    [[A3:%.*]] = mul i32 [[A2]], [[A2]]
 ; CHECK-NEXT:    [[A4:%.*]] = mul i32 [[A3]], [[A3]]

diff  --git a/llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll b/llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll
index e2a97bc4a3137..b972814676a1e 100644
--- a/llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll
+++ b/llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll
@@ -7,7 +7,8 @@
 define void @f_0(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_0(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
@@ -16,7 +17,7 @@ define void @f_0(i1 %cond_0, i1 %cond_1) {
 ; CHECK-NEXT:    ret void
 ; CHECK:       guarded:
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
@@ -50,7 +51,8 @@ guarded1:                                         ; preds = %guarded
 define void @f_1(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_1(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -65,7 +67,7 @@ define void @f_1(i1 %cond_0, i1 %cond_1) {
 ; CHECK-NEXT:    br label [[MERGE]]
 ; CHECK:       merge:
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
@@ -109,8 +111,9 @@ guarded1:                                         ; preds = %merge
 define void @f_2(i32 %a, i32 %b) {
 ; CHECK-LABEL: @f_2(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
@@ -230,8 +233,9 @@ right:                                            ; preds = %guarded
 define void @f_4(i32 %a, i32 %b) {
 ; CHECK-LABEL: @f_4(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
@@ -396,8 +400,9 @@ guarded1:                                         ; preds = %guarded
 define void @f_7(i32 %a, ptr %cond_buf) {
 ; CHECK-LABEL: @f_7(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
 ; CHECK-NEXT:    [[COND_1:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1
-; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
@@ -473,6 +478,7 @@ right:                                            ; preds = %guarded1
 define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
 ; CHECK-LABEL: @f_8(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
@@ -484,7 +490,7 @@ define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
 ; CHECK:       guarded:
 ; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
 ; CHECK:       leave:
-; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
+; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]]
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]]
@@ -661,9 +667,10 @@ guarded1:                                         ; preds = %no_loop
 define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @f_11(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
 ; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
 ; CHECK:       outer_header:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -674,7 +681,7 @@ define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
 ; CHECK-NEXT:    br label [[INNER:%.*]]
 ; CHECK:       inner:
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
@@ -725,7 +732,8 @@ exit:                                             ; preds = %outer_latch
 define void @f_12(i32 %a0) {
 ; CHECK-LABEL: @f_12(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
+; CHECK-NEXT:    [[A0_GW_FR:%.*]] = freeze i32 [[A0:%.*]]
+; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0_GW_FR]], [[A0_GW_FR]]
 ; CHECK-NEXT:    [[A2:%.*]] = mul i32 [[A1]], [[A1]]
 ; CHECK-NEXT:    [[A3:%.*]] = mul i32 [[A2]], [[A2]]
 ; CHECK-NEXT:    [[A4:%.*]] = mul i32 [[A3]], [[A3]]
@@ -1025,7 +1033,8 @@ guarded1:                                         ; preds = %guarded
 define void @swapped_wb(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @swapped_wb(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDENABLE_COND]], [[WIDE_CHK]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -1034,7 +1043,7 @@ define void @swapped_wb(i1 %cond_0, i1 %cond_1) {
 ; CHECK-NEXT:    ret void
 ; CHECK:       guarded:
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
@@ -1067,7 +1076,8 @@ guarded1:                                         ; preds = %guarded
 define void @trivial_wb(i1 %cond_0) {
 ; CHECK-LABEL: @trivial_wb(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND_0:%.*]]
+; CHECK-NEXT:    [[COND_0_GW_FR:%.*]] = freeze i1 [[COND_0:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND_0_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -1076,7 +1086,7 @@ define void @trivial_wb(i1 %cond_0) {
 ; CHECK-NEXT:    ret void
 ; CHECK:       guarded:
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_0_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]

diff  --git a/llvm/test/Transforms/GuardWidening/hang.ll b/llvm/test/Transforms/GuardWidening/hang.ll
index 071a201ab6079..6123d5d69bab7 100644
--- a/llvm/test/Transforms/GuardWidening/hang.ll
+++ b/llvm/test/Transforms/GuardWidening/hang.ll
@@ -5,11 +5,12 @@
 define i64 @test() {
 ; CHECK-LABEL: define i64 @test() {
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 poison, poison
+; CHECK-NEXT:    [[DOTGW_FR:%.*]] = freeze i1 poison
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 poison, [[DOTGW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br label [[BB2:%.*]]
 ; CHECK:       bb2:
-; CHECK-NEXT:    br i1 poison, label [[BB3:%.*]], label [[BB2]]
+; CHECK-NEXT:    br i1 [[DOTGW_FR]], label [[BB3:%.*]], label [[BB2]]
 ; CHECK:       bb3:
 ; CHECK-NEXT:    [[CALL:%.*]] = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
 ; CHECK-NEXT:    ret i64 [[CALL]]

diff  --git a/llvm/test/Transforms/GuardWidening/loop-schedule.ll b/llvm/test/Transforms/GuardWidening/loop-schedule.ll
index 2abdf6c0bb7a4..79fe6193ac49d 100644
--- a/llvm/test/Transforms/GuardWidening/loop-schedule.ll
+++ b/llvm/test/Transforms/GuardWidening/loop-schedule.ll
@@ -13,8 +13,9 @@ declare void @llvm.experimental.guard(i1,...)
 define void @iter(i32 %a, i32 %b, ptr %c_p) {
 ; CHECK-LABEL: @iter(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[CND:%.*]] = load i1, ptr [[C_P:%.*]], align 1
@@ -48,8 +49,9 @@ leave:                                            ; preds = %leave.loopexit, %en
 define void @within_loop(i32 %a, i32 %b, ptr %c_p) {
 ; CHECK-LABEL: @within_loop(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[CND:%.*]] = load i1, ptr [[C_P:%.*]], align 1

diff  --git a/llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll b/llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll
index 28a92281703f2..b528cf021ab6d 100644
--- a/llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll
+++ b/llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll
@@ -8,12 +8,14 @@ declare i32 @llvm.experimental.deoptimize.i32(...)
 define i32 @test_01(i32 %start, i32 %x) {
 ; CHECK-LABEL: @test_01(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
 ; CHECK-NEXT:    [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
 ; CHECK-NEXT:    br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
 ; CHECK:       exit_by_wc:
@@ -127,12 +129,14 @@ failure:
 define i32 @test_03(i32 %start, i32 %x, i1 %c) {
 ; CHECK-LABEL: @test_03(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]]
 ; CHECK-NEXT:    [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
 ; CHECK-NEXT:    [[INVARIANT:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
 ; CHECK-NEXT:    br i1 [[INVARIANT]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
 ; CHECK:       exit_by_wc:
@@ -152,7 +156,7 @@ define i32 @test_03(i32 %start, i32 %x, i1 %c) {
 ; CHECK-NEXT:    [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
 ; CHECK-NEXT:    ret i32 [[RVAL2]]
 ; CHECK:       early_failure:
-; CHECK-NEXT:    [[RVAL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[X]]) ]
+; CHECK-NEXT:    [[RVAL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[X_GW_FR]]) ]
 ; CHECK-NEXT:    ret i32 [[RVAL3]]
 ;
 entry:

diff  --git a/llvm/test/Transforms/GuardWidening/mixed_guards.ll b/llvm/test/Transforms/GuardWidening/mixed_guards.ll
index 92d42b346e644..e778eccf27e7c 100644
--- a/llvm/test/Transforms/GuardWidening/mixed_guards.ll
+++ b/llvm/test/Transforms/GuardWidening/mixed_guards.ll
@@ -15,10 +15,11 @@ declare i1 @llvm.experimental.widenable.condition() #0
 define void @test_01(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @test_01(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0:![0-9]+]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
@@ -44,7 +45,8 @@ guarded1:                                         ; preds = %guarded
 define void @test_02(i1 %cond_0, i1 %cond_1) {
 ; CHECK-LABEL: @test_02(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
+; CHECK-NEXT:    [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]

diff  --git a/llvm/test/Transforms/GuardWidening/posion.ll b/llvm/test/Transforms/GuardWidening/posion.ll
index 3568f1daf895d..d55a36774be20 100644
--- a/llvm/test/Transforms/GuardWidening/posion.ll
+++ b/llvm/test/Transforms/GuardWidening/posion.ll
@@ -1,9 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt -S -passes=guard-widening,dce < %s | FileCheck %s
 
-; FIXME: All the tests below must be fixed.
-
 declare void @llvm.experimental.guard(i1,...)
+declare i1 @dummy()
 
 ; This tests shows the incorrect behavior of guard widening in terms of
 ; interaction with poison values.
@@ -24,11 +23,12 @@ declare void @llvm.experimental.guard(i1,...)
 define void @combine_range_checks(i32 %x) {
 ; CHECK-LABEL: @combine_range_checks(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[X2:%.*]] = add i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[X2:%.*]] = add i32 [[X_GW_FR]], 0
 ; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[X2]], 200
-; CHECK-NEXT:    [[X3:%.*]] = add nuw nsw i32 [[X]], 3
+; CHECK-NEXT:    [[X3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[C3:%.*]] = icmp ult i32 [[X3]], 100
-; CHECK-NEXT:    [[X4:%.*]] = add nuw nsw i32 [[X]], 20
+; CHECK-NEXT:    [[X4:%.*]] = add i32 [[X_GW_FR]], 20
 ; CHECK-NEXT:    [[C4:%.*]] = icmp ult i32 [[X4]], 100
 ; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[C4]], [[C3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"(i64 1) ]
@@ -68,11 +68,12 @@ out:
 define void @combine_range_checks_with_side_effect(i32 %x, ptr %p) {
 ; CHECK-LABEL: @combine_range_checks_with_side_effect(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[X2:%.*]] = add i32 [[X:%.*]], 0
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[X2:%.*]] = add i32 [[X_GW_FR]], 0
 ; CHECK-NEXT:    [[C2:%.*]] = icmp ult i32 [[X2]], 200
-; CHECK-NEXT:    [[X3:%.*]] = add nuw nsw i32 [[X]], 3
+; CHECK-NEXT:    [[X3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[C3:%.*]] = icmp ult i32 [[X3]], 100
-; CHECK-NEXT:    [[X4:%.*]] = add nuw nsw i32 [[X]], 20
+; CHECK-NEXT:    [[X4:%.*]] = add i32 [[X_GW_FR]], 20
 ; CHECK-NEXT:    [[C4:%.*]] = icmp ult i32 [[X4]], 100
 ; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[C4]], [[C3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"(i64 1) ]
@@ -114,14 +115,15 @@ out:
 define void @simple_case(i32 %a, i32 %b, i1 %cnd) {
 ; CHECK-LABEL: @simple_case(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
 ; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
-; CHECK-NEXT:    [[B_SHIFT:%.*]] = add nuw nsw i32 [[B:%.*]], 5
+; CHECK-NEXT:    [[B_SHIFT:%.*]] = add i32 [[B_GW_FR]], 5
 ; CHECK-NEXT:    [[COND_2:%.*]] = icmp ult i32 [[B_SHIFT]], 10
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_2]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B]], 10
+; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
 ; CHECK-NEXT:    br i1 [[COND_1]], label [[OK:%.*]], label [[LEAVE_LOOPEXIT:%.*]]
 ; CHECK:       ok:
 ; CHECK-NEXT:    br i1 [[CND:%.*]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
@@ -150,3 +152,70 @@ leave.loopexit:
 leave:
   ret void
 }
+
+declare ptr @fake_personality_function()
+
+define void @case_with_invoke(i1 %c, i1 %gc) personality ptr @fake_personality_function {
+; CHECK-LABEL: @case_with_invoke(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[NORMAL:%.*]], label [[INVOK:%.*]]
+; CHECK:       invok:
+; CHECK-NEXT:    [[INVOKE_RESULT:%.*]] = invoke i1 @dummy()
+; CHECK-NEXT:    to label [[NORMAL]] unwind label [[EXCEPTION:%.*]]
+; CHECK:       normal:
+; CHECK-NEXT:    [[PHI_C:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[INVOKE_RESULT]], [[INVOK]] ]
+; CHECK-NEXT:    [[PHI_C_GW_FR:%.*]] = freeze i1 [[PHI_C]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[GC:%.*]], [[PHI_C_GW_FR]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    ret void
+; CHECK:       exception:
+; CHECK-NEXT:    [[LANDING_PAD:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 %c, label %normal, label %invok
+
+invok:
+  %invoke.result = invoke i1 @dummy() to label %normal unwind label %exception
+
+normal:
+  %phi.c = phi i1 [true, %entry], [%invoke.result, %invok]
+  call void (i1, ...) @llvm.experimental.guard(i1 %gc) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %phi.c) [ "deopt"() ]
+  ret void
+
+exception:
+  %landing_pad = landingpad { ptr, i32 } cleanup
+  ret void
+}
+
+define void @case_with_invoke_in_latch(i1 %c, i1 %gc) personality ptr @fake_personality_function {
+; CHECK-LABEL: @case_with_invoke_in_latch(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[HEADER:%.*]]
+; CHECK:       header:
+; CHECK-NEXT:    [[PHI_C:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[INVOKE_RESULT:%.*]], [[HEADER]] ]
+; CHECK-NEXT:    [[PHI_C_GW_FR:%.*]] = freeze i1 [[PHI_C]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[GC:%.*]], [[PHI_C_GW_FR]]
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
+; CHECK-NEXT:    [[INVOKE_RESULT]] = invoke i1 @dummy()
+; CHECK-NEXT:    to label [[HEADER]] unwind label [[EXCEPTION:%.*]]
+; CHECK:       exception:
+; CHECK-NEXT:    [[LANDING_PAD:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:    cleanup
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %header
+
+header:
+  %phi.c = phi i1 [false, %entry], [%invoke.result, %header]
+  call void (i1, ...) @llvm.experimental.guard(i1 %gc) [ "deopt"() ]
+  call void (i1, ...) @llvm.experimental.guard(i1 %phi.c) [ "deopt"() ]
+  %invoke.result = invoke i1 @dummy() to label %header unwind label %exception
+
+exception:
+  %landing_pad = landingpad { ptr, i32 } cleanup
+  ret void
+}

diff  --git a/llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll b/llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll
index 73b29573c781c..a194a99d09214 100644
--- a/llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll
+++ b/llvm/test/Transforms/GuardWidening/profile-based-profitability-intrinsics.ll
@@ -9,7 +9,8 @@ define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_very_profitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
 ; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF0:![0-9]+]]
@@ -48,7 +49,8 @@ define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_profitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
 ; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF2:![0-9]+]]
@@ -87,7 +89,8 @@ define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_neutral
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
 ; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF3:![0-9]+]]
@@ -125,7 +128,8 @@ define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
 ; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF4:![0-9]+]]
@@ -163,7 +167,8 @@ define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_unprofitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    [[LOOP_PRECONDITION:%.*]] = icmp uge i32 [[N]], 100
 ; CHECK-NEXT:    br i1 [[LOOP_PRECONDITION]], label [[LOOP:%.*]], label [[FAILED:%.*]], !prof [[PROF5:![0-9]+]]

diff  --git a/llvm/test/Transforms/GuardWidening/profile-based-profitability_explicit.ll b/llvm/test/Transforms/GuardWidening/profile-based-profitability_explicit.ll
index 89aeb62f5d5c3..0114a6e64a8c5 100644
--- a/llvm/test/Transforms/GuardWidening/profile-based-profitability_explicit.ll
+++ b/llvm/test/Transforms/GuardWidening/profile-based-profitability_explicit.ll
@@ -6,7 +6,8 @@ define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_very_profitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
@@ -19,7 +20,7 @@ define i32 @test_intrinsic_very_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
 ; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND4]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
@@ -74,7 +75,8 @@ define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_profitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -87,7 +89,7 @@ define i32 @test_intrinsic_profitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
 ; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND4]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
@@ -142,7 +144,8 @@ define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_neutral
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -155,7 +158,7 @@ define i32 @test_intrinsic_neutral(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
 ; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND4]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
@@ -209,7 +212,8 @@ define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_very_unprofitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -222,7 +226,7 @@ define i32 @test_intrinsic_very_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
 ; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND4]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]
@@ -276,7 +280,8 @@ define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK-LABEL: define i32 @test_intrinsic_unprofitable
 ; CHECK-SAME: (i32 [[N:%.*]], i1 [[COND_1:%.*]], i1 [[COND_2:%.*]]) {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2]]
+; CHECK-NEXT:    [[COND_2_GW_FR:%.*]] = freeze i1 [[COND_2]]
+; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_2_GW_FR]]
 ; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
 ; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
@@ -289,7 +294,7 @@ define i32 @test_intrinsic_unprofitable(i32 %n, i1 %cond.1, i1 %cond.2) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[GUARDED]] ], [ [[IV_NEXT:%.*]], [[GUARDED1:%.*]] ]
 ; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
-; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND4]]
+; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND5:%.*]] = and i1 [[COND_2_GW_FR]], [[WIDENABLE_COND4]]
 ; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
 ; CHECK:       deopt2:
 ; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ]

diff  --git a/llvm/test/Transforms/GuardWidening/range-check-merging.ll b/llvm/test/Transforms/GuardWidening/range-check-merging.ll
index e591b1ab2ad62..1f498565d07eb 100644
--- a/llvm/test/Transforms/GuardWidening/range-check-merging.ll
+++ b/llvm/test/Transforms/GuardWidening/range-check-merging.ll
@@ -6,22 +6,23 @@ declare void @llvm.experimental.guard(i1,...)
 define void @f_0(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_0(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0:![0-9]+]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
-; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X]], 2
+; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
 ; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]]
-; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X]], 3
+; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -42,9 +43,10 @@ entry:
 define void @f_1(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_1(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
 ; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_INC1]], 2
@@ -57,7 +59,7 @@ define void @f_1(i32 %x, ptr %length_buf) {
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -78,18 +80,20 @@ entry:
 define void @f_2(i32 %a, ptr %length_buf) {
 ; CHECK-LABEL: @f_2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[X:%.*]] = and i32 [[A:%.*]], -256
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
+; CHECK-NEXT:    [[X:%.*]] = and i32 [[A_GW_FR]], -256
 ; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]]
+; CHECK-NEXT:    [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]]
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH_GW_FR]]
 ; CHECK-NEXT:    [[X_INC1:%.*]] = or i32 [[X]], 1
-; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
+; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
 ; CHECK-NEXT:    [[X_INC2:%.*]] = or i32 [[X]], 2
-; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
-; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]]
+; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]]
+; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]]
 ; CHECK-NEXT:    [[X_INC3:%.*]] = or i32 [[X]], 3
-; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
-; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]]
+; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_GW_FR]]
+; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
@@ -116,8 +120,9 @@ entry:
 define void @f_3(i32 %a, ptr %length_buf) {
 ; CHECK-LABEL: @f_3(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[X:%.*]] = and i32 [[A:%.*]], -256
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
+; CHECK-NEXT:    [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
+; CHECK-NEXT:    [[X:%.*]] = and i32 [[A_GW_FR]], -256
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
 ; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]]
 ; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
@@ -133,7 +138,7 @@ define void @f_3(i32 %a, ptr %length_buf) {
 ;
 entry:
   %x = and i32 %a, 4294967040 ;; 4294967040 == 0xffffff00
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -154,15 +159,16 @@ entry:
 define void @f_4(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_4(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], -1024
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -1024
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
-; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X]], 2
+; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
 ; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK1]]
-; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X]], 3
+; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
@@ -171,7 +177,7 @@ define void @f_4(i32 %x, ptr %length_buf) {
 
 ; Note: we NOT guarding on "and i1 %chk3, %chk0", that would be incorrect.
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -192,9 +198,10 @@ entry:
 define void @f_5(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_5(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
 ; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_INC1]], -200
@@ -207,7 +214,7 @@ define void @f_5(i32 %x, ptr %length_buf) {
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -240,22 +247,23 @@ entry:
 define void @f_6(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_6(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], -2147483647
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -2147483647
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
-; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X]], 2
+; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
 ; CHECK-NEXT:    [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]]
-; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X]], 3
+; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 
@@ -277,23 +285,24 @@ entry:
 define void @f_7(i32 %x, ptr %length_buf) {
 ; CHECK-LABEL: @f_7(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH_A:%.*]] = load volatile i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[LENGTH_B:%.*]] = load volatile i32, ptr [[LENGTH_BUF]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0_A:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH_A]]
-; CHECK-NEXT:    [[CHK0_B:%.*]] = icmp ult i32 [[X]], [[LENGTH_B]]
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH_A:%.*]] = load volatile i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[LENGTH_B:%.*]] = load volatile i32, ptr [[LENGTH_BUF]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0_A:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_A]]
+; CHECK-NEXT:    [[CHK0_B:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_B]]
 ; CHECK-NEXT:    [[CHK0:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
 ; CHECK-NEXT:    [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A]]
 ; CHECK-NEXT:    [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B]]
 ; CHECK-NEXT:    [[CHK1:%.*]] = and i1 [[CHK1_A]], [[CHK1_B]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
-; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X]], 2
+; CHECK-NEXT:    [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2
 ; CHECK-NEXT:    [[CHK2_A:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_A]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[CHK2_A]], [[CHK0_A]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[CHK0_B]], [[TMP0]]
 ; CHECK-NEXT:    [[CHK2_B:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_B]]
 ; CHECK-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[CHK2_B]], [[TMP1]]
-; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X]], 3
+; CHECK-NEXT:    [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3
 ; CHECK-NEXT:    [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[CHK3_B]], [[CHK0_B]]
 ; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[CHK0_A]], [[TMP2]]
@@ -307,8 +316,8 @@ define void @f_7(i32 %x, ptr %length_buf) {
 
 
 entry:
-  %length_a = load volatile i32, ptr %length_buf, !range !0
-  %length_b = load volatile i32, ptr %length_buf, !range !0
+  %length_a = load volatile i32, ptr %length_buf, !range !0, !noundef !{}
+  %length_b = load volatile i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0.a = icmp ult i32 %x, %length_a
   %chk0.b = icmp ult i32 %x, %length_b
   %chk0 = and i1 %chk0.a, %chk0.b
@@ -338,16 +347,17 @@ define void @f_8(i32 %x, ptr %length_buf) {
 ; Check that we clean nuw nsw flags
 ; CHECK-LABEL: @f_8(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]]
-; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
-; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X]], 1
+; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]], !noundef !1
+; CHECK-NEXT:    [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH]]
+; CHECK-NEXT:    [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1
 ; CHECK-NEXT:    [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]]
 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]]
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %length = load i32, ptr %length_buf, !range !0
+  %length = load i32, ptr %length_buf, !range !0, !noundef !{}
   %chk0 = icmp ult i32 %x, %length
   call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
 

diff  --git a/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll b/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll
index 9b60f4e3e62b7..1a9ff304837e3 100644
--- a/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll
+++ b/llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll
@@ -14,16 +14,19 @@ define void @test_01(i32 %a, i32 %b, i32 %c, i32 %d) {
 ; INTRINSIC_FORM-LABEL: define void @test_01
 ; INTRINSIC_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
 ; INTRINSIC_FORM-NEXT:  entry:
+; INTRINSIC_FORM-NEXT:    [[D_GW_FR:%.*]] = freeze i32 [[D]]
+; INTRINSIC_FORM-NEXT:    [[C_GW_FR:%.*]] = freeze i32 [[C]]
+; INTRINSIC_FORM-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B]]
 ; INTRINSIC_FORM-NEXT:    br label [[LOOP:%.*]]
 ; INTRINSIC_FORM:       loop:
 ; INTRINSIC_FORM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
 ; INTRINSIC_FORM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
 ; INTRINSIC_FORM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
-; INTRINSIC_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; INTRINSIC_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]]
 ; INTRINSIC_FORM-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
-; INTRINSIC_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; INTRINSIC_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]]
 ; INTRINSIC_FORM-NEXT:    [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[C3]]
-; INTRINSIC_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; INTRINSIC_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]]
 ; INTRINSIC_FORM-NEXT:    [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[C4]]
 ; INTRINSIC_FORM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; INTRINSIC_FORM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK2]], [[WIDENABLE_COND]]
@@ -40,16 +43,19 @@ define void @test_01(i32 %a, i32 %b, i32 %c, i32 %d) {
 ; BRANCH_FORM-LABEL: define void @test_01
 ; BRANCH_FORM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
 ; BRANCH_FORM-NEXT:  entry:
+; BRANCH_FORM-NEXT:    [[D_GW_FR:%.*]] = freeze i32 [[D]]
+; BRANCH_FORM-NEXT:    [[C_GW_FR:%.*]] = freeze i32 [[C]]
+; BRANCH_FORM-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B]]
 ; BRANCH_FORM-NEXT:    br label [[LOOP:%.*]]
 ; BRANCH_FORM:       loop:
 ; BRANCH_FORM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
 ; BRANCH_FORM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
 ; BRANCH_FORM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
-; BRANCH_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; BRANCH_FORM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]]
 ; BRANCH_FORM-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
-; BRANCH_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; BRANCH_FORM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]]
 ; BRANCH_FORM-NEXT:    [[WIDE_CHK13:%.*]] = and i1 [[WIDE_CHK]], [[C3]]
-; BRANCH_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; BRANCH_FORM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]]
 ; BRANCH_FORM-NEXT:    [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK13]], [[C4]]
 ; BRANCH_FORM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; BRANCH_FORM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK14]], [[WIDENABLE_COND]]
@@ -72,16 +78,19 @@ define void @test_01(i32 %a, i32 %b, i32 %c, i32 %d) {
 ; BRANCH_FORM_LICM-LABEL: define void @test_01
 ; BRANCH_FORM_LICM-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32 [[D:%.*]]) {
 ; BRANCH_FORM_LICM-NEXT:  entry:
+; BRANCH_FORM_LICM-NEXT:    [[D_GW_FR:%.*]] = freeze i32 [[D]]
+; BRANCH_FORM_LICM-NEXT:    [[C_GW_FR:%.*]] = freeze i32 [[C]]
+; BRANCH_FORM_LICM-NEXT:    [[B_GW_FR:%.*]] = freeze i32 [[B]]
 ; BRANCH_FORM_LICM-NEXT:    br label [[LOOP:%.*]]
 ; BRANCH_FORM_LICM:       loop:
 ; BRANCH_FORM_LICM-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ]
 ; BRANCH_FORM_LICM-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
 ; BRANCH_FORM_LICM-NEXT:    [[C1:%.*]] = icmp ult i32 [[IV]], [[A]]
-; BRANCH_FORM_LICM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B]]
+; BRANCH_FORM_LICM-NEXT:    [[C2:%.*]] = icmp ult i32 [[IV]], [[B_GW_FR]]
 ; BRANCH_FORM_LICM-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
-; BRANCH_FORM_LICM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C]]
+; BRANCH_FORM_LICM-NEXT:    [[C3:%.*]] = icmp ult i32 [[IV]], [[C_GW_FR]]
 ; BRANCH_FORM_LICM-NEXT:    [[WIDE_CHK13:%.*]] = and i1 [[WIDE_CHK]], [[C3]]
-; BRANCH_FORM_LICM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D]]
+; BRANCH_FORM_LICM-NEXT:    [[C4:%.*]] = icmp ult i32 [[IV]], [[D_GW_FR]]
 ; BRANCH_FORM_LICM-NEXT:    [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK13]], [[C4]]
 ; BRANCH_FORM_LICM-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
 ; BRANCH_FORM_LICM-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK14]], [[WIDENABLE_COND]]


        


More information about the llvm-commits mailing list