Index: llvm/lib/Transforms/Scalar/GuardWidening.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -209,6 +209,10 @@ 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 +562,63 @@ makeAvailableAt(Op, Loc); Inst->moveBefore(Loc); - // If we moved instruction before guard we must clean poison generating flags. - Inst->dropPoisonGeneratingFlags(); +} + +static Instruction *getFreezeInsertPt(Value *V, Instruction *I) { + if (auto *I = dyn_cast(V)) + return I->getInsertionPointAfterDef(); + return &*I->getFunction()->getEntryBlock().getFirstNonPHIOrDbgOrAlloca(); +} + +Value *GuardWideningImpl::freezeAndPush(Value *Orig, Instruction *InsertPt) { + if (isGuaranteedNotToBePoison(Orig, nullptr, InsertPt, &DT)) + return Orig; + Instruction *InsertPtAtDef = getFreezeInsertPt(Orig, InsertPt); + if (!InsertPtAtDef) + return new FreezeInst(Orig, "gw.freeze", InsertPt); + SmallSet Visited; + SmallVector Worklist; + SmallSet DropPoisonFlags; + SmallSet 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(V); + if (!I || canCreateUndefOrPoison(cast(I), + /*ConsiderFlagsAndMetadata*/ false)) { + NeedFreeze.insert(V); + continue; + } + // Check all operands. If for any of them we cannot insert Freeze, + // stop here. Otherwise, iterate. + if (any_of(I->operands(), [InsertPt](Value *Op) { + return isa(Op) && !getFreezeInsertPt(Op, InsertPt); + })) { + NeedFreeze.insert(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, InsertPt); + FreezeInst *FI = new FreezeInst(V, V->getName() + ".gw.fr", FreezeInsertPt); + 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 +680,7 @@ } assert(Result && "Failed to find result value"); Result->setName("wide.chk"); + Result = freezeAndPush(Result, InsertPt); } return true; } @@ -633,6 +693,7 @@ makeAvailableAt(Cond1, InsertPt); if (InvertCondition) Cond1 = BinaryOperator::CreateNot(Cond1, "inverted", InsertPt); + Cond1 = freezeAndPush(Cond1, InsertPt); Result = BinaryOperator::CreateAnd(Cond0, Cond1, "wide.chk", InsertPt); } Index: llvm/test/Transforms/GuardWidening/basic-loop.ll =================================================================== --- llvm/test/Transforms/GuardWidening/basic-loop.ll +++ llvm/test/Transforms/GuardWidening/basic-loop.ll @@ -10,11 +10,13 @@ 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 @@ 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 @@ 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: Index: llvm/test/Transforms/GuardWidening/basic.ll =================================================================== --- llvm/test/Transforms/GuardWidening/basic.ll +++ llvm/test/Transforms/GuardWidening/basic.ll @@ -9,7 +9,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: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -24,7 +25,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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]] Index: llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll =================================================================== --- llvm/test/Transforms/GuardWidening/basic_widenable_condition_guards.ll +++ 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 @@ ; 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 @@ 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 @@ ; 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ ; 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 @@ 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 @@ ; 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 @@ 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 @@ 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 @@ ; 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 @@ 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 @@ ; 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"() ] Index: llvm/test/Transforms/GuardWidening/hang.ll =================================================================== --- llvm/test/Transforms/GuardWidening/hang.ll +++ 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]] Index: llvm/test/Transforms/GuardWidening/loop-schedule.ll =================================================================== --- llvm/test/Transforms/GuardWidening/loop-schedule.ll +++ llvm/test/Transforms/GuardWidening/loop-schedule.ll @@ -13,8 +13,9 @@ 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 @@ 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 Index: llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll =================================================================== --- llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll +++ llvm/test/Transforms/GuardWidening/loop_invariant_widenable_condition.ll @@ -8,12 +8,14 @@ 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 @@ 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 @@ ; 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: Index: llvm/test/Transforms/GuardWidening/mixed_guards.ll =================================================================== --- llvm/test/Transforms/GuardWidening/mixed_guards.ll +++ llvm/test/Transforms/GuardWidening/mixed_guards.ll @@ -15,10 +15,11 @@ 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 @@ 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]] Index: llvm/test/Transforms/GuardWidening/posion.ll =================================================================== --- llvm/test/Transforms/GuardWidening/posion.ll +++ llvm/test/Transforms/GuardWidening/posion.ll @@ -24,11 +24,12 @@ 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 +69,12 @@ 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 +116,15 @@ 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]] Index: llvm/test/Transforms/GuardWidening/range-check-merging.ll =================================================================== --- llvm/test/Transforms/GuardWidening/range-check-merging.ll +++ llvm/test/Transforms/GuardWidening/range-check-merging.ll @@ -6,17 +6,19 @@ define void @f_0(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_0( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] -; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 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: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK0]] +; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 +; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] +; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 +; 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 ; @@ -42,17 +44,19 @@ define void @f_1(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_1( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], 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:%.*]] = add i32 [[X_INC2]], 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 ; @@ -78,18 +82,20 @@ 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,18 +122,20 @@ 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: [[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:%.*]] = add 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_INC1]], 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:%.*]] = add i32 [[X_INC2]], 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 ; @@ -154,17 +162,19 @@ define void @f_4(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_4( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -1024 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] -; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 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: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3]], [[CHK1]] +; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 +; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] +; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 +; 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 ; @@ -192,18 +202,20 @@ define void @f_5(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_5( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], -200 -; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK1]], [[CHK2]] -; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK1]], [[CHK2]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] +; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 -; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] +; 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 ; entry: @@ -240,16 +252,18 @@ define void @f_6(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_6( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], -2147483647 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] -; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 -; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] +; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 +; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] -; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X]], 3 -; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] +; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 +; 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 @@ -277,31 +291,30 @@ define void @f_7(i32 %x, ptr %length_buf) { ; CHECK-LABEL: @f_7( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; CHECK-NEXT: [[LENGTH_A:%.*]] = load volatile i32, ptr [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] +; CHECK-NEXT: [[LENGTH_A_GW_FR:%.*]] = freeze i32 [[LENGTH_A]] ; 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: [[LENGTH_B_GW_FR:%.*]] = freeze i32 [[LENGTH_B]] +; CHECK-NEXT: [[CHK0_A:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_A_GW_FR]] +; CHECK-NEXT: [[CHK0_B:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_B_GW_FR]] ; CHECK-NEXT: [[CHK0:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]] -; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 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: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 +; CHECK-NEXT: [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A_GW_FR]] +; CHECK-NEXT: [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B_GW_FR]] ; 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: [[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: [[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]] -; CHECK-NEXT: [[CHK3_A:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_A]] -; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[CHK3_A]], [[TMP3]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] +; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_GW_FR]], 2 +; CHECK-NEXT: [[CHK2_A:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_A_GW_FR]] +; CHECK-NEXT: [[CHK2_B:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_B_GW_FR]] ; CHECK-NEXT: [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] +; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_GW_FR]], 3 +; CHECK-NEXT: [[CHK3_A:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_A_GW_FR]] +; CHECK-NEXT: [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B_GW_FR]] ; CHECK-NEXT: [[CHK3:%.*]] = and i1 [[CHK3_A]], [[CHK3_B]] +; 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 ; @@ -338,10 +351,12 @@ ; Check that we clean nuw nsw flags ; CHECK-LABEL: @f_8( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]] ; 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: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] +; CHECK-NEXT: [[LENGTH_GW_FR:%.*]] = freeze i32 [[LENGTH]] +; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X_GW_FR]], [[LENGTH_GW_FR]] +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X_GW_FR]], 1 +; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_GW_FR]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] ; CHECK-NEXT: ret void Index: llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll =================================================================== --- llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll +++ llvm/test/Transforms/GuardWidening/two_forms_behavior_consistency.ll @@ -14,16 +14,19 @@ ; 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 @@ ; 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 @@ ; 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]]