Index: llvm/lib/Transforms/Scalar/GuardWidening.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -51,6 +51,7 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/PatternMatch.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" @@ -199,11 +200,13 @@ const ConstantInt *Offset; const Value *Length; ICmpInst *CheckInst; + bool ToWiden; public: explicit RangeCheck(const Value *Base, const ConstantInt *Offset, - const Value *Length, ICmpInst *CheckInst) - : Base(Base), Offset(Offset), Length(Length), CheckInst(CheckInst) {} + const Value *Length, ICmpInst *CheckInst, bool ToWiden) + : Base(Base), Offset(Offset), Length(Length), CheckInst(CheckInst), + ToWiden(ToWiden) {} void setBase(const Value *NewBase) { Base = NewBase; } void setOffset(const ConstantInt *NewOffset) { Offset = NewOffset; } @@ -213,6 +216,7 @@ const APInt &getOffsetValue() const { return getOffset()->getValue(); } const Value *getLength() const { return Length; }; ICmpInst *getCheckInst() const { return CheckInst; } + bool getToWiden() const { return ToWiden; } void print(raw_ostream &OS, bool PrintTypes = false) { OS << "Base: "; @@ -232,13 +236,14 @@ /// Parse \p CheckCond into a conjunction (logical-and) of range checks; and /// append them to \p Checks. Returns true on success, may clobber \c Checks /// on failure. - bool parseRangeChecks(Value *CheckCond, SmallVectorImpl &Checks) { + bool parseRangeChecks(Value *CheckCond, SmallVectorImpl &Checks, + bool ToWiden) { SmallPtrSet Visited; - return parseRangeChecks(CheckCond, Checks, Visited); + return parseRangeChecks(CheckCond, Checks, Visited, ToWiden); } bool parseRangeChecks(Value *CheckCond, SmallVectorImpl &Checks, - SmallPtrSetImpl &Visited); + SmallPtrSetImpl &Visited, bool ToWiden); /// Combine the checks in \p Checks into a smaller set of checks and append /// them into \p CombinedChecks. Return true on success (i.e. all of checks @@ -540,16 +545,46 @@ { SmallVector Checks, CombinedChecks; // TODO: Support InvertCondition case? - if (!InvertCondition && - parseRangeChecks(Cond0, Checks) && parseRangeChecks(Cond1, Checks) && + if (!InvertCondition && parseRangeChecks(Cond0, Checks, true) && + parseRangeChecks(Cond1, Checks, false) && combineRangeChecks(Checks, CombinedChecks)) { if (InsertPt) { Result = nullptr; + DenseMap NotAPoisonCache; + auto GetNotAPoisonCached = [&](Value *V) { + auto It = NotAPoisonCache.find(V); + if (It != NotAPoisonCache.end()) + return It->second; + bool R = isGuaranteedNotToBeUndefOrPoison(V, nullptr, InsertPt, &DT); + NotAPoisonCache[V] = R; + return R; + }; + // Handle first ToWiden range checks. + llvm::sort(CombinedChecks, + [&](const GuardWideningImpl::RangeCheck &LHS, + const GuardWideningImpl::RangeCheck &RHS) { + if (LHS.getToWiden()) + return true; + if (RHS.getToWiden()) + return false; + if(GetNotAPoisonCached(LHS.getCheckInst())) + return true; + if(GetNotAPoisonCached(RHS.getCheckInst())) + return false; + return true; + }); + IRBuilder<> B(InsertPt); for (auto &RC : CombinedChecks) { - makeAvailableAt(RC.getCheckInst(), InsertPt); + if (RC.getToWiden()) + assert(DT.dominates(RC.getCheckInst(), InsertPt) && + "Range check must be available"); + else + makeAvailableAt(RC.getCheckInst(), InsertPt); if (Result) - Result = BinaryOperator::CreateAnd(RC.getCheckInst(), Result, "", - InsertPt); + if (RC.getToWiden() || GetNotAPoisonCached(RC.getCheckInst())) + Result = B.CreateAnd(Result, RC.getCheckInst()); + else + Result = B.CreateLogicalAnd(Result, RC.getCheckInst()); else Result = RC.getCheckInst(); } @@ -563,11 +598,15 @@ // Base case -- just logical-and the two conditions together. if (InsertPt) { - makeAvailableAt(Cond0, InsertPt); + assert(DT.dominates(Cond0, InsertPt) && "Cond0 must be available"); makeAvailableAt(Cond1, InsertPt); + IRBuilder<> B(InsertPt); if (InvertCondition) - Cond1 = BinaryOperator::CreateNot(Cond1, "inverted", InsertPt); - Result = BinaryOperator::CreateAnd(Cond0, Cond1, "wide.chk", InsertPt); + Cond1 = B.CreateNot(Cond1, "inverted"); + if (isGuaranteedNotToBeUndefOrPoison(Cond1, nullptr, InsertPt, &DT)) + Result = B.CreateAnd(Cond0, Cond1, "wide.chk"); + else + Result = B.CreateLogicalAnd(Cond0, Cond1, "wide.chk"); } // We were not able to compute Cond0 AND Cond1 for the price of one. @@ -576,7 +615,7 @@ bool GuardWideningImpl::parseRangeChecks( Value *CheckCond, SmallVectorImpl &Checks, - SmallPtrSetImpl &Visited) { + SmallPtrSetImpl &Visited, bool ToWiden) { if (!Visited.insert(CheckCond).second) return true; @@ -585,8 +624,16 @@ { Value *AndLHS, *AndRHS; if (match(CheckCond, m_And(m_Value(AndLHS), m_Value(AndRHS)))) - return parseRangeChecks(AndLHS, Checks) && - parseRangeChecks(AndRHS, Checks); + return parseRangeChecks(AndLHS, Checks, ToWiden) && + parseRangeChecks(AndRHS, Checks, ToWiden); + } + + { + Value *AndLHS, *AndRHS; + if (match(CheckCond, m_LogicalAnd(m_Value(AndLHS), m_Value(AndRHS)))) { + return parseRangeChecks(AndLHS, Checks, ToWiden) && + parseRangeChecks(AndRHS, Checks, false); + } } auto *IC = dyn_cast(CheckCond); @@ -603,7 +650,7 @@ GuardWideningImpl::RangeCheck Check( CmpLHS, cast(ConstantInt::getNullValue(CmpRHS->getType())), - CmpRHS, IC); + CmpRHS, IC, ToWiden); if (!isKnownNonNegative(Check.getLength(), DL)) return false; 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,13 @@ ; 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: store i32 0, i32* @G, align 4 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = select i1 [[WIDE_CHK]], i1 [[COND_2:%.*]], i1 false ; 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 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 +38,15 @@ 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: store i32 0, i32* @G, align 4 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = select i1 [[WIDE_CHK]], i1 [[COND_2:%.*]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK1]]) [ "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 +68,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 +102,16 @@ 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_2:%.*]], i1 false ; 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,12 @@ ; conditions. define void @f_0(i1 %cond_0, i1 %cond_1) { ; CHECK-LABEL: @f_0( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; 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 +23,18 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; 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 +46,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 +54,20 @@ ; 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: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false +; 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 +89,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 +121,18 @@ ; 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: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false +; 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 +151,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 +182,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 +203,20 @@ ; 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: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_1]], i1 [[COND_3]], i1 false +; 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 +238,21 @@ ; 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: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_2:%.*]], i1 [[COND_3]], i1 false +; 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 +261,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 +278,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 +305,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 +331,19 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; 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 +356,45 @@ ; 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: [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]] +; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]] +; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]] +; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]] +; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]] +; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]] +; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]] +; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]] +; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]] +; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]] +; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]] +; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]] +; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]] +; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]] +; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]] +; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]] +; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]] +; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]] +; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]] +; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]] +; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]] +; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]] +; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]] +; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]] +; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]] +; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]] +; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]] +; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]] +; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]] +; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]] +; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 true, i1 [[COND]], i1 false +; 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 +435,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 +463,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 +493,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 +508,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,16 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false ; 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 +51,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false ; 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 +66,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 @@ -112,9 +112,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false ; 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 +127,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 +175,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 +185,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 @@ -233,9 +233,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false ; 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 +244,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 +292,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 +302,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 +347,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 +396,20 @@ 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: [[WIDE_CHK:%.*]] = select i1 [[COND_1]], i1 [[COND_3]], i1 false ; 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 +418,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 +477,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 @@ -486,9 +486,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_2:%.*]], i1 [[COND_3]], i1 false ; 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 +497,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 +559,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 +568,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 +612,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 +621,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 +664,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false ; 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 +675,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 @@ -757,16 +757,16 @@ ; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]] ; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]] ; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1 -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 true, i1 [[COND]], i1 false ; 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 +833,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 +843,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 +888,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 +898,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 +943,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 +985,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 +1026,16 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false ; 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 +1068,16 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 true, i1 [[COND_0:%.*]], i1 false ; 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,21 @@ 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: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false +; 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 +46,21 @@ } 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: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[COND_0]], i1 [[COND_1]], i1 false +; 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,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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false ; 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 +45,9 @@ ; 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: [[WIDE_CHK:%.*]] = select i1 [[COND_0:%.*]], i1 [[COND_1:%.*]], i1 false +; 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 @@ -10,13 +10,13 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK0]], i1 [[CHK2]], i1 false ; 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: [[WIDE_CHK2:%.*]] = select i1 [[CHK0]], i1 [[CHK3]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -46,13 +46,13 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK0]], i1 [[CHK2]], i1 false ; 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: [[WIDE_CHK2:%.*]] = select i1 [[CHK0]], i1 [[CHK3]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -83,13 +83,13 @@ ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X]], [[LENGTH]] ; CHECK-NEXT: [[X_INC1:%.*]] = or i32 [[X]], 1 ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK0]], i1 [[CHK2]], i1 false ; 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: [[WIDE_CHK2:%.*]] = select i1 [[CHK0]], i1 [[CHK3]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -121,13 +121,13 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK0]], i1 [[CHK2]], i1 false ; 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: [[WIDE_CHK2:%.*]] = select i1 [[CHK0]], i1 [[CHK3]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -158,13 +158,13 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK2]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK2:%.*]] = select i1 [[CHK3]], i1 [[CHK1]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -196,11 +196,11 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; 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: [[WIDE_CHK1:%.*]] = select i1 [[CHK1]], i1 [[CHK2]], i1 false +; CHECK-NEXT: [[WIDE_CHK2:%.*]] = select i1 [[CHK1]], i1 [[CHK2]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X_INC2]], 3 ; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] @@ -244,13 +244,13 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; CHECK-NEXT: [[X_INC2:%.*]] = add i32 [[X]], 2 ; CHECK-NEXT: [[CHK2:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK1:%.*]] = and i1 [[WIDE_CHK]], [[CHK2]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = select i1 [[WIDE_CHK]], i1 [[CHK2]], i1 false ; CHECK-NEXT: [[X_INC3:%.*]] = add i32 [[X]], 3 ; CHECK-NEXT: [[CHK3:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH]] -; CHECK-NEXT: [[WIDE_CHK2:%.*]] = and i1 [[WIDE_CHK1]], [[CHK3]] +; CHECK-NEXT: [[WIDE_CHK2:%.*]] = select i1 [[WIDE_CHK1]], i1 [[CHK3]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: ret void ; @@ -286,19 +286,19 @@ ; CHECK-NEXT: [[CHK1_A:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_A]] ; CHECK-NEXT: [[CHK1_B:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH_B]] ; CHECK-NEXT: [[CHK1:%.*]] = and i1 [[CHK1_A]], [[CHK1_B]] -; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CHK0_B]], [[CHK0_A]] ; 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: [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[CHK2_B]], i1 false +; CHECK-NEXT: [[CHK2_A:%.*]] = icmp ult i32 [[X_INC2]], [[LENGTH_A]] +; CHECK-NEXT: [[WIDE_CHK1:%.*]] = select i1 [[TMP1]], i1 [[CHK2_A]], i1 false +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CHK0_A]], [[CHK0_B]] ; 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: [[TMP3:%.*]] = select i1 [[TMP2]], i1 [[CHK3_A]], i1 false +; CHECK-NEXT: [[CHK3_B:%.*]] = icmp ult i32 [[X_INC3]], [[LENGTH_B]] +; CHECK-NEXT: [[WIDE_CHK2:%.*]] = select i1 [[TMP3]], i1 [[CHK3_B]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK2]]) [ "deopt"() ] ; CHECK-NEXT: [[CHK2:%.*]] = and i1 [[CHK2_A]], [[CHK2_B]] ; CHECK-NEXT: [[CHK3:%.*]] = and i1 [[CHK3_A]], [[CHK3_B]] @@ -342,7 +342,7 @@ ; 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: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = select i1 [[CHK0]], i1 [[CHK1]], i1 false ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ] ; CHECK-NEXT: ret void ;