Index: llvm/lib/Transforms/Scalar/GuardWidening.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -178,7 +178,11 @@ /// Helper to hoist \p V to \p InsertPos. Guaranteed to succeed if \c /// isAvailableAt returned true. - void makeAvailableAt(Value *V, Instruction *InsertPos) const; + void makeAvailableAtImpl(Value *V, Instruction *InsertPos) const; + + /// Helper to hoist \p V to \p InsertPos. Guaranteed to succeed if \c + /// isAvailableAt returned true. Return frozen value if it may be poison. + Value *makeAvailableAt(Value *V, Instruction *InsertPos) const; /// Common helper used by \c widenGuard and \c isWideningCondProfitable. Try /// to generate an expression computing the logical AND of \p Cond0 and (\p @@ -483,7 +487,7 @@ [&](Value *Op) { return isAvailableAt(Op, Loc, Visited); }); } -void GuardWideningImpl::makeAvailableAt(Value *V, Instruction *Loc) const { +void GuardWideningImpl::makeAvailableAtImpl(Value *V, Instruction *Loc) const { auto *Inst = dyn_cast(V); if (!Inst || DT.dominates(Inst, Loc)) return; @@ -495,8 +499,13 @@ makeAvailableAt(Op, Loc); Inst->moveBefore(Loc); - // If we moved instruction before guard we must clean poison generating flags. - Inst->dropPoisonGeneratingFlags(); +} + +Value *GuardWideningImpl::makeAvailableAt(Value *V, Instruction *Loc) const { + makeAvailableAtImpl(V, Loc); + if (isGuaranteedNotToBeUndefOrPoison(V, nullptr, Loc, &DT)) + return V; + return new FreezeInst(V, "freeze.widen.check", Loc); } bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1, @@ -546,12 +555,11 @@ if (InsertPt) { Result = nullptr; for (auto &RC : CombinedChecks) { - makeAvailableAt(RC.getCheckInst(), InsertPt); + Value *CheckInst = makeAvailableAt(RC.getCheckInst(), InsertPt); if (Result) - Result = BinaryOperator::CreateAnd(RC.getCheckInst(), Result, "", - InsertPt); + Result = BinaryOperator::CreateAnd(CheckInst, Result, "", InsertPt); else - Result = RC.getCheckInst(); + Result = CheckInst; } assert(Result && "Failed to find result value"); Result->setName("wide.chk"); @@ -563,8 +571,8 @@ // Base case -- just logical-and the two conditions together. if (InsertPt) { - makeAvailableAt(Cond0, InsertPt); - makeAvailableAt(Cond1, InsertPt); + Cond0 = makeAvailableAt(Cond0, InsertPt); + Cond1 = makeAvailableAt(Cond1, InsertPt); if (InvertCondition) Cond1 = BinaryOperator::CreateNot(Cond1, "inverted", 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 @@ -12,13 +12,16 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: store i32 0, i32* @G -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ] -; CHECK-NEXT: store i32 1, i32* @G -; CHECK-NEXT: store i32 2, i32* @G -; CHECK-NEXT: store i32 3, i32* @G +; CHECK-NEXT: store i32 0, i32* @G, align 4 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_2:%.*]] +; CHECK-NEXT: [[WIDE_CHK3:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK3]]) [ "deopt"(i32 0) ] +; CHECK-NEXT: store i32 1, i32* @G, align 4 +; CHECK-NEXT: store i32 2, i32* @G, align 4 +; CHECK-NEXT: store i32 3, i32* @G, align 4 ; CHECK-NEXT: br label [[LOOP]] ; entry: @@ -38,15 +41,18 @@ define void @widen_into_preheader(i1 %cond_0, i1 %cond_1, i1 %cond_2) { ; CHECK-LABEL: @widen_into_preheader( ; CHECK-NEXT: entry: -; CHECK-NEXT: store i32 0, i32* @G -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[COND_2:%.*]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "deopt"(i32 0) ] +; CHECK-NEXT: store i32 0, i32* @G, align 4 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_2:%.*]] +; CHECK-NEXT: [[WIDE_CHK3:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK3]]) [ "deopt"(i32 0) ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: store i32 1, i32* @G -; CHECK-NEXT: store i32 2, i32* @G -; CHECK-NEXT: store i32 3, i32* @G +; CHECK-NEXT: store i32 1, i32* @G, align 4 +; CHECK-NEXT: store i32 2, i32* @G, align 4 +; CHECK-NEXT: store i32 3, i32* @G, align 4 ; CHECK-NEXT: br label [[LOOP]] ; entry: @@ -68,14 +74,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: store i32 0, i32* @G +; CHECK-NEXT: store i32 0, i32* @G, align 4 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"(i32 0) ] -; CHECK-NEXT: store i32 1, i32* @G +; CHECK-NEXT: store i32 1, i32* @G, align 4 ; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]] ; CHECK: backedge: -; CHECK-NEXT: store i32 2, i32* @G +; CHECK-NEXT: store i32 2, i32* @G, align 4 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2:%.*]]) [ "deopt"(i32 2) ] -; CHECK-NEXT: store i32 3, i32* @G +; CHECK-NEXT: store i32 3, i32* @G, align 4 ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -102,16 +108,18 @@ 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: store i32 0, i32* @G -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_2:%.*]] +; CHECK-NEXT: store i32 0, i32* @G, align 4 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_2:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"(i32 0) ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: store i32 1, i32* @G +; CHECK-NEXT: store i32 1, i32* @G, align 4 ; CHECK-NEXT: br i1 [[COND_1:%.*]], label [[BACKEDGE:%.*]], label [[EXIT:%.*]] ; CHECK: backedge: -; CHECK-NEXT: store i32 2, i32* @G -; CHECK-NEXT: store i32 3, i32* @G +; CHECK-NEXT: store i32 2, i32* @G, align 4 +; CHECK-NEXT: store i32 3, i32* @G, align 4 ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: ret void Index: llvm/test/Transforms/GuardWidening/basic.ll =================================================================== --- llvm/test/Transforms/GuardWidening/basic.ll +++ llvm/test/Transforms/GuardWidening/basic.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -guard-widening < %s | FileCheck %s ; RUN: opt -S -passes=guard-widening < %s | FileCheck %s @@ -7,10 +8,14 @@ ; conditions. define void @f_0(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; entry: -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: ret void call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] @@ -20,10 +25,20 @@ ; Same as @f_0, but with using a more general notion of postdominance. define void @f_1(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: right: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: ret void +; entry: -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %left, label %right @@ -35,9 +50,6 @@ br label %merge merge: -; CHECK: merge: -; CHECK-NOT: call void (i1, ...) @llvm.experimental.guard( -; CHECK: ret void call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] ret void } @@ -46,12 +58,23 @@ ; widen a dominanting check. define void @f_2(i32 %a, i32 %b) { ; CHECK-LABEL: @f_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: right: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: ret void +; entry: -; CHECK: %cond_0 = icmp ult i32 %a, 10 -; CHECK: %cond_1 = icmp ult i32 %b, 10 -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_0 = icmp ult i32 %a, 10 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] @@ -73,20 +96,24 @@ ; indiscriminately, since that can make us do more work than needed. define void @f_3(i32 %a, i32 %b) { ; CHECK-LABEL: @f_3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: ret void +; entry: -; CHECK: %cond_0 = icmp ult i32 %a, 10 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_0 = icmp ult i32 %a, 10 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %left, label %right left: -; CHECK: left: -; CHECK: %cond_1 = icmp ult i32 %b, 10 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] -; CHECK: ret void %cond_1 = icmp ult i32 %b, 10 call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] @@ -101,12 +128,21 @@ ; the future. define void @f_4(i32 %a, i32 %b) { ; CHECK-LABEL: @f_4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]] +; CHECK: loop: +; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE]] +; CHECK: leave: +; CHECK-NEXT: ret void +; entry: -; CHECK: %cond_0 = icmp ult i32 %a, 10 -; CHECK: %cond_1 = icmp ult i32 %b, 10 -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %loop, label %leave %cond_0 = icmp ult i32 %a, 10 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] @@ -125,10 +161,18 @@ ; dominating check without doing any extra work. define void @f_5(i32 %a) { ; CHECK-LABEL: @f_5( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10 +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: ret void +; entry: -; CHECK: %wide.chk = icmp uge i32 %a, 11 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_0 = icmp ugt i32 %a, 7 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] @@ -148,9 +192,14 @@ ; same value. define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) { ; CHECK-LABEL: @f_6( -; CHECK: call void (i1, ...) @llvm.experimental.guard( -; CHECK: call void (i1, ...) @llvm.experimental.guard( -; CHECK: ret void +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = load i1, i1* [[A:%.*]], align 1 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ] +; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]], align 1 +; CHECK-NEXT: [[COND_1:%.*]] = load i1, i1* [[A]], align 1 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; entry: %cond_0 = load i1, i1* %a call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] @@ -164,14 +213,23 @@ ; heuristic can use some tuning. define void @f_7(i32 %a, i1* %cond_buf) { ; CHECK-LABEL: @f_7( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]], align 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A]], 7 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_3]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]], align 1 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: br label [[LEFT]] +; CHECK: right: +; CHECK-NEXT: ret void +; entry: -; CHECK: %cond_1 = load volatile i1, i1* %cond_buf -; CHECK: %cond_3 = icmp ult i32 %a, 7 -; CHECK: %wide.chk = and i1 %cond_1, %cond_3 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: %cond_2 = load volatile i1, i1* %cond_buf -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_1 = load volatile i1, i1* %cond_buf call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] @@ -193,6 +251,24 @@ ; tuning. define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) { ; CHECK-LABEL: @f_8( +; CHECK-NEXT: entry: +; 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: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_2:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A]], 7 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_3]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]] +; CHECK: loop2: +; CHECK-NEXT: br label [[LOOP2]] +; CHECK: leave2: +; CHECK-NEXT: ret void +; entry: br label %loop @@ -201,11 +277,6 @@ br i1 undef, label %loop, label %leave leave: -; CHECK: leave: -; CHECK: %cond_3 = icmp ult i32 %a, 7 -; CHECK: %wide.chk = and i1 %cond_2, %cond_3 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %loop2, label %leave2 call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ] br i1 undef, label %loop2, label %leave2 @@ -223,21 +294,24 @@ ; widening sites, we refuse to do anything. define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_9( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FIRST_LOOP:%.*]] +; CHECK: first_loop: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]] +; CHECK: second_loop: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ] +; CHECK-NEXT: br label [[SECOND_LOOP]] +; entry: br label %first_loop first_loop: -; CHECK: first_loop: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: br i1 undef, label %first_loop, label %second_loop call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %first_loop, label %second_loop second_loop: -; CHECK: second_loop: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] -; CHECK: br label %second_loop call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] br label %second_loop @@ -247,21 +321,24 @@ ; so we refuse to do anything. define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_10( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[NO_LOOP:%.*]] +; CHECK: no_loop: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; entry: br label %loop loop: -; CHECK: loop: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: br i1 undef, label %loop, label %no_loop call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %loop, label %no_loop no_loop: -; CHECK: no_loop: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] -; CHECK: ret void call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] ret void } @@ -270,14 +347,21 @@ ; containing loop. define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_11( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[INNER:%.*]] +; CHECK: inner: +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[INNER]], label [[OUTER:%.*]] +; CHECK: outer: +; CHECK-NEXT: br label [[INNER]] +; entry: br label %inner inner: -; CHECK: inner: -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %inner, label %outer call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %inner, label %outer @@ -290,14 +374,107 @@ ; Checks that we are adequately guarded against exponential-time ; behavior when hoisting code. define void @f_12(i32 %a0) { -; CHECK-LABEL: @f_12 +; CHECK-LABEL: @f_12( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i32 [[A0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A0]] +; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0]], [[A0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[A1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[A1]] +; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i32 [[A2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[A2]] +; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[A3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[A3]] +; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i32 [[A4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK9:%.*]] = freeze i32 [[A4]] +; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[A5]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[A5]] +; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[A6]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i32 [[A6]] +; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK14:%.*]] = freeze i32 [[A7]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK15:%.*]] = freeze i32 [[A7]] +; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK16:%.*]] = freeze i32 [[A8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK17:%.*]] = freeze i32 [[A8]] +; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK18:%.*]] = freeze i32 [[A9]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK19:%.*]] = freeze i32 [[A9]] +; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK20:%.*]] = freeze i32 [[A10]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK21:%.*]] = freeze i32 [[A10]] +; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK22:%.*]] = freeze i32 [[A11]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK23:%.*]] = freeze i32 [[A11]] +; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK24:%.*]] = freeze i32 [[A12]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK25:%.*]] = freeze i32 [[A12]] +; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK26:%.*]] = freeze i32 [[A13]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK27:%.*]] = freeze i32 [[A13]] +; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK28:%.*]] = freeze i32 [[A14]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK29:%.*]] = freeze i32 [[A14]] +; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK30:%.*]] = freeze i32 [[A15]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK31:%.*]] = freeze i32 [[A15]] +; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK32:%.*]] = freeze i32 [[A16]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK33:%.*]] = freeze i32 [[A16]] +; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK34:%.*]] = freeze i32 [[A17]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK35:%.*]] = freeze i32 [[A17]] +; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK36:%.*]] = freeze i32 [[A18]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK37:%.*]] = freeze i32 [[A18]] +; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK38:%.*]] = freeze i32 [[A19]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK39:%.*]] = freeze i32 [[A19]] +; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK40:%.*]] = freeze i32 [[A20]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK41:%.*]] = freeze i32 [[A20]] +; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK42:%.*]] = freeze i32 [[A21]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK43:%.*]] = freeze i32 [[A21]] +; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK44:%.*]] = freeze i32 [[A22]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK45:%.*]] = freeze i32 [[A22]] +; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK46:%.*]] = freeze i32 [[A23]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK47:%.*]] = freeze i32 [[A23]] +; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK48:%.*]] = freeze i32 [[A24]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK49:%.*]] = freeze i32 [[A24]] +; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK50:%.*]] = freeze i32 [[A25]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK51:%.*]] = freeze i32 [[A25]] +; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK52:%.*]] = freeze i32 [[A26]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK53:%.*]] = freeze i32 [[A26]] +; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK54:%.*]] = freeze i32 [[A27]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK55:%.*]] = freeze i32 [[A27]] +; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK56:%.*]] = freeze i32 [[A28]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK57:%.*]] = freeze i32 [[A28]] +; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK58:%.*]] = freeze i32 [[A29]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK59:%.*]] = freeze i32 [[A29]] +; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK60:%.*]] = freeze i32 [[A30]] +; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK61:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[FREEZE_WIDEN_CHECK61]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; ; Eliding the earlier 29 multiplications for brevity -; CHECK: %a30 = mul i32 %a29, %a29 -; CHECK-NEXT: %cond = trunc i32 %a30 to i1 -; CHECK-NEXT: %wide.chk = and i1 true, %cond -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK-NEXT: ret void entry: call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] @@ -338,10 +515,18 @@ define void @f_13(i32 %a) { ; CHECK-LABEL: @f_13( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10 +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: ret void +; entry: -; CHECK: %wide.chk = icmp ult i32 %a, 10 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_0 = icmp ult i32 %a, 14 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] @@ -358,19 +543,24 @@ define void @f_14(i32 %a) { ; CHECK-LABEL: @f_14( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ] +; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ] +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: ret void +; entry: -; CHECK: %cond_0 = icmp ult i32 %a, 14 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: br i1 undef, label %left, label %right %cond_0 = icmp ult i32 %a, 14 call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] br i1 undef, label %left, label %right left: -; CHECK: left: -; CHECK: %cond_1 = icmp sgt i32 %a, 10 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] %cond_1 = icmp sgt i32 %a, 10 call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ] @@ -383,10 +573,12 @@ ; Make sure we do not widen guard by trivial true conditions into something. define void @f_15(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_15( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] +; CHECK-NEXT: ret void +; entry: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] -; CHECK: ret void call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ] @@ -396,10 +588,12 @@ ; Make sure we do not widen guard by trivial false conditions into something. define void @f_16(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_16( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] +; CHECK-NEXT: ret void +; entry: -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] -; CHECK: ret void call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ] call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ] 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 @@ -8,16 +8,18 @@ ; CHECK-LABEL: @f_0( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -51,9 +53,11 @@ ; CHECK-LABEL: @f_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -66,7 +70,7 @@ ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -111,10 +115,13 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -127,7 +134,7 @@ ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -175,7 +182,7 @@ ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -185,7 +192,7 @@ ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -232,10 +239,13 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -244,7 +254,7 @@ ; CHECK: loop: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -292,7 +302,7 @@ ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -302,7 +312,7 @@ ; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -347,19 +357,19 @@ define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) { ; CHECK-LABEL: @f_6( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[COND_0:%.*]] = load i1, i1* [[A:%.*]] +; CHECK-NEXT: [[COND_0:%.*]] = load i1, i1* [[A:%.*]], align 1 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void ; CHECK: guarded: -; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]] -; CHECK-NEXT: [[COND_1:%.*]] = load i1, i1* [[A]] +; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]], align 1 +; CHECK-NEXT: [[COND_1:%.*]] = load i1, i1* [[A]], align 1 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -396,20 +406,23 @@ define void @f_7(i32 %a, i1* %cond_buf) { ; CHECK-LABEL: @f_7( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]], align 1 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A]], 7 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_3]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void ; CHECK: guarded: -; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]] +; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]], align 1 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -418,7 +431,7 @@ ; CHECK: left: ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]] -; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]] ; CHECK: deopt6: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -477,7 +490,7 @@ ; CHECK: loop: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -485,10 +498,13 @@ ; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE:%.*]] ; CHECK: leave: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_2:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A:%.*]] +; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A]], 7 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_3]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -497,7 +513,7 @@ ; CHECK: loop2: ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]] -; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]] ; CHECK: deopt6: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -559,7 +575,7 @@ ; CHECK: first_loop: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -568,7 +584,7 @@ ; CHECK: second_loop: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -612,7 +628,7 @@ ; CHECK: loop: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -621,7 +637,7 @@ ; CHECK: no_loop: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -664,9 +680,11 @@ ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer_header: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -675,7 +693,7 @@ ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -726,47 +744,109 @@ ; CHECK-LABEL: @f_12( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i32 [[A0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[A0]] +; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0]], [[A0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[A1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[A1]] ; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i32 [[A2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[A2]] ; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[A3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[A3]] ; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i32 [[A4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK9:%.*]] = freeze i32 [[A4]] ; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[A5]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[A5]] ; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[A6]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i32 [[A6]] ; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK14:%.*]] = freeze i32 [[A7]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK15:%.*]] = freeze i32 [[A7]] ; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK16:%.*]] = freeze i32 [[A8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK17:%.*]] = freeze i32 [[A8]] ; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK18:%.*]] = freeze i32 [[A9]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK19:%.*]] = freeze i32 [[A9]] ; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK20:%.*]] = freeze i32 [[A10]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK21:%.*]] = freeze i32 [[A10]] ; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK22:%.*]] = freeze i32 [[A11]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK23:%.*]] = freeze i32 [[A11]] ; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK24:%.*]] = freeze i32 [[A12]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK25:%.*]] = freeze i32 [[A12]] ; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK26:%.*]] = freeze i32 [[A13]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK27:%.*]] = freeze i32 [[A13]] ; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK28:%.*]] = freeze i32 [[A14]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK29:%.*]] = freeze i32 [[A14]] ; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK30:%.*]] = freeze i32 [[A15]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK31:%.*]] = freeze i32 [[A15]] ; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK32:%.*]] = freeze i32 [[A16]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK33:%.*]] = freeze i32 [[A16]] ; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK34:%.*]] = freeze i32 [[A17]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK35:%.*]] = freeze i32 [[A17]] ; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK36:%.*]] = freeze i32 [[A18]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK37:%.*]] = freeze i32 [[A18]] ; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK38:%.*]] = freeze i32 [[A19]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK39:%.*]] = freeze i32 [[A19]] ; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK40:%.*]] = freeze i32 [[A20]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK41:%.*]] = freeze i32 [[A20]] ; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK42:%.*]] = freeze i32 [[A21]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK43:%.*]] = freeze i32 [[A21]] ; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK44:%.*]] = freeze i32 [[A22]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK45:%.*]] = freeze i32 [[A22]] ; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK46:%.*]] = freeze i32 [[A23]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK47:%.*]] = freeze i32 [[A23]] ; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK48:%.*]] = freeze i32 [[A24]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK49:%.*]] = freeze i32 [[A24]] ; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK50:%.*]] = freeze i32 [[A25]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK51:%.*]] = freeze i32 [[A25]] ; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK52:%.*]] = freeze i32 [[A26]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK53:%.*]] = freeze i32 [[A26]] ; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK54:%.*]] = freeze i32 [[A27]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK55:%.*]] = freeze i32 [[A27]] ; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK56:%.*]] = freeze i32 [[A28]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK57:%.*]] = freeze i32 [[A28]] ; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK58:%.*]] = freeze i32 [[A29]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK59:%.*]] = freeze i32 [[A29]] ; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK60:%.*]] = freeze i32 [[A30]] ; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK61:%.*]] = freeze i1 [[COND]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[FREEZE_WIDEN_CHECK61]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void ; CHECK: guarded: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -833,7 +913,7 @@ ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -843,7 +923,7 @@ ; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -888,7 +968,7 @@ ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -898,7 +978,7 @@ ; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -943,14 +1023,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void ; CHECK: guarded: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 true, [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -985,14 +1065,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void ; CHECK: guarded: ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 false, [[WIDENABLE_COND3]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -1026,16 +1106,18 @@ ; CHECK-LABEL: @swapped_wb( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDENABLE_COND]], [[WIDE_CHK]] -; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -1068,16 +1150,17 @@ ; CHECK-LABEL: @trivial_wb( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[FREEZE_WIDEN_CHECK]] ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void Index: llvm/test/Transforms/GuardWidening/loop-schedule.ll =================================================================== --- llvm/test/Transforms/GuardWidening/loop-schedule.ll +++ llvm/test/Transforms/GuardWidening/loop-schedule.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -passes='licm,guard-widening,licm' -verify-memoryssa -debug-pass-manager < %s 2>&1 | FileCheck %s ; Main point of this test is to check the scheduling -- there should be @@ -10,12 +11,24 @@ declare void @llvm.experimental.guard(i1,...) define void @iter(i32 %a, i32 %b, i1* %c_p) { -; CHECK-LABEL: @iter -; CHECK: %cond_0 = icmp ult i32 %a, 10 -; CHECK: %cond_1 = icmp ult i32 %b, 10 -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK-LABEL: loop: +; CHECK-LABEL: @iter( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: [[CND:%.*]] = load i1, i1* [[C_P:%.*]], align 1 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: br i1 [[CND]], label [[LOOP]], label [[LEAVE_LOOPEXIT:%.*]] +; CHECK: leave.loopexit: +; CHECK-NEXT: br label [[LEAVE:%.*]] +; CHECK: leave: +; CHECK-NEXT: ret void +; entry: %cond_0 = icmp ult i32 %a, 10 @@ -36,12 +49,24 @@ } define void @within_loop(i32 %a, i32 %b, i1* %c_p) { -; CHECK-LABEL: @within_loop -; CHECK: %cond_0 = icmp ult i32 %a, 10 -; CHECK: %cond_1 = icmp ult i32 %b, 10 -; CHECK: %wide.chk = and i1 %cond_0, %cond_1 -; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ] -; CHECK-LABEL: loop: +; CHECK-LABEL: @within_loop( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[B:%.*]] +; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B]], 10 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i1 [[COND_1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] +; CHECK-NEXT: [[CND:%.*]] = load i1, i1* [[C_P:%.*]], align 1 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: br i1 [[CND]], label [[LOOP]], label [[LEAVE_LOOPEXIT:%.*]] +; CHECK: leave.loopexit: +; CHECK-NEXT: br label [[LEAVE:%.*]] +; CHECK: leave: +; CHECK-NEXT: ret void +; entry: br label %loop Index: llvm/test/Transforms/GuardWidening/mixed_guards.ll =================================================================== --- llvm/test/Transforms/GuardWidening/mixed_guards.ll +++ llvm/test/Transforms/GuardWidening/mixed_guards.ll @@ -15,11 +15,13 @@ 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: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] ; 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: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0 +; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0:![0-9]+]] ; CHECK: deopt2: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void @@ -45,9 +47,11 @@ ; CHECK-LABEL: @test_02( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] -; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] -; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[COND_0:%.*]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i1 [[COND_1:%.*]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK1]] +; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] +; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] ; CHECK-NEXT: ret void 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 @@ -8,16 +8,29 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0:![0-9]+]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -44,16 +57,29 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X_INC1]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X_INC2]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -81,16 +107,29 @@ ; CHECK-NEXT: [[X:%.*]] = and i32 [[A:%.*]], -256 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = or i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC2:%.*]] = or i32 [[X]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC3:%.*]] = or i32 [[X]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -119,16 +158,29 @@ ; CHECK-NEXT: [[X:%.*]] = and i32 [[A:%.*]], -256 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X_INC1]] ; CHECK-NEXT: [[X_INC2:%.*]] = or i32 [[X_INC1]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X_INC2]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -156,16 +208,29 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], -1024 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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"() ] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -194,16 +259,29 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X_INC1]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X_INC1]], -200 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X_INC2]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -242,16 +320,29 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], -2147483647 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK9:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X]], 3 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i32 [[LENGTH]] ; 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: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK14:%.*]] = and i1 [[WIDE_CHK9]], [[FREEZE_WIDEN_CHECK13]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK14]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; entry: @@ -282,26 +373,47 @@ ; CHECK-NEXT: [[CHK0_A:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH_A]] ; CHECK-NEXT: [[CHK0_B:%.*]] = icmp ult i32 [[X]], [[LENGTH_B]] ; CHECK-NEXT: [[CHK0:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH_A]] ; CHECK-NEXT: [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1_A]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK5:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK6:%.*]] = freeze i32 [[LENGTH_B]] ; CHECK-NEXT: [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK7:%.*]] = freeze i1 [[CHK1_B]] ; CHECK-NEXT: [[CHK1:%.*]] = and i1 [[CHK1_A]], [[CHK1_B]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK8:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK8]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK9:%.*]] = freeze i32 [[X]] ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK10:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK11:%.*]] = freeze i32 [[LENGTH_A]] ; 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: [[FREEZE_WIDEN_CHECK12:%.*]] = freeze i1 [[CHK2_A]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK13:%.*]] = freeze i32 [[X_INC2]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK14:%.*]] = freeze i32 [[LENGTH_B]] ; CHECK-NEXT: [[CHK2_B:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_B]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[CHK2_B]], [[TMP1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK15:%.*]] = freeze i1 [[CHK2_B]] +; CHECK-NEXT: [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK16:%.*]] = freeze i1 [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK17:%.*]] = and i1 [[WIDE_CHK]], [[FREEZE_WIDEN_CHECK16]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK18:%.*]] = freeze i32 [[X]] ; 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: [[FREEZE_WIDEN_CHECK19:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK20:%.*]] = freeze i32 [[LENGTH_A]] ; 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: [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK21:%.*]] = freeze i1 [[CHK3_A]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK22:%.*]] = freeze i32 [[X_INC3]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK23:%.*]] = freeze i32 [[LENGTH_B]] +; CHECK-NEXT: [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK24:%.*]] = freeze i1 [[CHK3_B]] ; CHECK-NEXT: [[CHK3:%.*]] = and i1 [[CHK3_A]], [[CHK3_B]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK25:%.*]] = freeze i1 [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK26:%.*]] = and i1 [[WIDE_CHK17]], [[FREEZE_WIDEN_CHECK25]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK26]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -340,9 +452,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] -; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK:%.*]] = freeze i1 [[CHK0]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK1:%.*]] = freeze i32 [[X]] +; CHECK-NEXT: [[X_INC1:%.*]] = add nuw nsw i32 [[X]], 1 +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK2:%.*]] = freeze i32 [[X_INC1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK3:%.*]] = freeze i32 [[LENGTH]] ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[FREEZE_WIDEN_CHECK4:%.*]] = freeze i1 [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[FREEZE_WIDEN_CHECK]], [[FREEZE_WIDEN_CHECK4]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] ; CHECK-NEXT: ret void ;