Index: llvm/lib/Transforms/Scalar/LoopPredication.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPredication.cpp +++ llvm/lib/Transforms/Scalar/LoopPredication.cpp @@ -179,15 +179,19 @@ #include "llvm/Transforms/Scalar/LoopPredication.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/GuardUtils.h" +#include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" @@ -195,6 +199,7 @@ #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/KnownBits.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/GuardUtils.h" #include "llvm/Transforms/Utils/Local.h" @@ -240,6 +245,18 @@ "predicated guards"), cl::init(true)); +static cl::opt WidenChecksUsingConstantRange( + "loop-predication-widen-checks-using-contants-range", cl::Hidden, + cl::desc( + "Whether or not we should widen checks using constant range analysis"), + cl::init(true)); + +static cl::opt MaxConstantRangeValue( + "loop-predication-max-constant-range-value", cl::Hidden, + cl::desc("The maximum value of constant range for a value in check when " + "widening using constant range analysis"), + cl::init(4096)); + namespace { /// Represents an induction variable check: /// icmp Pred, , @@ -263,6 +280,8 @@ ScalarEvolution *SE; LoopInfo *LI; MemorySSAUpdater *MSSAU; + AssumptionCache *AC; + LazyValueInfo *LVI; Loop *L; const DataLayout *DL; @@ -296,6 +315,8 @@ Optional widenICmpRangeCheck(ICmpInst *ICI, SCEVExpander &Expander, Instruction *Guard); + Optional widenRangeCheckUsingConstantRange(ICmpInst *ICI, + Instruction *Guard); Optional widenICmpRangeCheckIncrementingLoop(LoopICmp LatchCheck, LoopICmp RangeCheck, SCEVExpander &Expander, @@ -318,8 +339,9 @@ public: LoopPredication(AliasAnalysis *AA, DominatorTree *DT, ScalarEvolution *SE, - LoopInfo *LI, MemorySSAUpdater *MSSAU) - : AA(AA), DT(DT), SE(SE), LI(LI), MSSAU(MSSAU){}; + LoopInfo *LI, MemorySSAUpdater *MSSAU, AssumptionCache *AC, + LazyValueInfo *LVI) + : AA(AA), DT(DT), SE(SE), LI(LI), MSSAU(MSSAU), AC(AC), LVI(LVI) {}; bool runOnLoop(Loop *L); }; @@ -332,6 +354,8 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); + AU.addRequired(); + AU.addRequired(); getLoopAnalysisUsage(AU); AU.addPreserved(); } @@ -339,15 +363,19 @@ bool runOnLoop(Loop *L, LPPassManager &LPM) override { if (skipLoop(L)) return false; + Function &F = *L->getHeader()->getParent(); + auto *SE = &getAnalysis().getSE(); auto *LI = &getAnalysis().getLoopInfo(); auto *DT = &getAnalysis().getDomTree(); auto *MSSAWP = getAnalysisIfAvailable(); + auto *AC = &getAnalysis().getAssumptionCache(F); + auto *LVI = &getAnalysis().getLVI(); std::unique_ptr MSSAU; if (MSSAWP) MSSAU = std::make_unique(&MSSAWP->getMSSA()); auto *AA = &getAnalysis().getAAResults(); - LoopPredication LP(AA, DT, SE, LI, MSSAU ? MSSAU.get() : nullptr); + LoopPredication LP(AA, DT, SE, LI, MSSAU ? MSSAU.get() : nullptr, AC, LVI); return LP.runOnLoop(L); } }; @@ -372,8 +400,12 @@ std::unique_ptr MSSAU; if (AR.MSSA) MSSAU = std::make_unique(AR.MSSA); + + auto &DL = L.getHeader()->getModule()->getDataLayout(); + LazyValueInfo LVI(&AR.AC, &DL, &AR.TLI); + LoopPredication LP(&AR.AA, &AR.DT, &AR.SE, &AR.LI, - MSSAU ? MSSAU.get() : nullptr); + MSSAU ? MSSAU.get() : nullptr, &AR.AC, &LVI); if (!LP.runOnLoop(&L)) return PreservedAnalyses::all(); @@ -751,6 +783,87 @@ } } +Optional +LoopPredication::widenRangeCheckUsingConstantRange(ICmpInst *ICI, + Instruction *Guard) { + if (!WidenChecksUsingConstantRange || LI->getLoopFor(Guard->getParent()) != L) + return None; + LLVM_DEBUG(dbgs() << "Analyzing ICmpInst condition using constant range:\n"); + LLVM_DEBUG(ICI->dump()); + + // We are looking for the range checks of the form: + // x < guardLimit, + // where x and guardLimit have known constant ranges (meaning they are not + // full-set). If they are reasonably small and max(x) <= max(guardLimit), we + // can predicate the loop with the condition max(x) <= guardLimit. + auto Pred = ICI->getPredicate(); + auto *LHS = ICI->getOperand(0); + auto *RHS = ICI->getOperand(1); + + // Both operands are loop variant, bail out. + if (!L->isLoopInvariant(LHS) && !L->isLoopInvariant(RHS)) { + LLVM_DEBUG(dbgs() << "LHS and RHS are loop variant\n"); + return None; + } + + auto ComputeRange = [&](Value *V, bool IsSigned, Instruction *CtxI) { + auto Range = ConstantRange::fromKnownBits( + computeKnownBits(V, *DL, 0, AC, CtxI, DT), IsSigned); + Range = Range.intersectWith( + computeConstantRange(V, IsSigned, true, AC, CtxI, DT)); + return Range.intersectWith(LVI->getConstantRange(V, CtxI)); + }; + + switch (Pred) { + case CmpInst::ICMP_EQ: + case CmpInst::ICMP_NE: + LLVM_DEBUG(dbgs() << "Unsupported predicate\n"); + return None; + case CmpInst::ICMP_UGT: + case CmpInst::ICMP_UGE: + case CmpInst::ICMP_SGT: + case CmpInst::ICMP_SGE: + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + break; + default: + break; + } + + bool IsSigned = ICmpInst::isSigned(Pred); + + auto LHSRange = ComputeRange(LHS, IsSigned, Guard); + auto RHSRange = ComputeRange(RHS, IsSigned, Guard); + + ICmpInst::Predicate NewPred = ICmpInst::getNonStrictPredicate(Pred); + + if (RHSRange.isFullSet()) { + LLVM_DEBUG(dbgs() << "RHS range is full-set\n"); + return None; + } + + auto LHSMaxValue = + IsSigned ? LHSRange.getSignedMax() : LHSRange.getUnsignedMax(); + auto RHSMaxValue = + IsSigned ? RHSRange.getSignedMax() : RHSRange.getUnsignedMax(); + + bool LHSMaxIsGreaterThanRHSMax = LHSMaxValue.ugt(RHSMaxValue); + if (IsSigned) + LHSMaxIsGreaterThanRHSMax = LHSMaxValue.sgt(RHSMaxValue); + if (LHSMaxIsGreaterThanRHSMax) { + LLVM_DEBUG(dbgs() << "LHS max value is not greater than RHS maximum\n"); + return None; + } + + LLVM_DEBUG(dbgs() << "LHS: " << LHSMaxValue << "\n"); + LLVM_DEBUG(dbgs() << "RHS: " << *RHS << "\n"); + LLVM_DEBUG(dbgs() << "Pred: " << ICmpInst::getPredicateName(NewPred) << "\n"); + auto *MaxCI = ConstantInt::get(LHS->getType(), LHSMaxValue); + IRBuilder<> Builder(findInsertPt(Guard, {RHS})); + auto *NewICI = Builder.CreateICmp(NewPred, MaxCI, RHS); + return NewICI; +} + unsigned LoopPredication::collectChecks(SmallVectorImpl &Checks, Value *Condition, SCEVExpander &Expander, @@ -791,6 +904,11 @@ NumWidened++; continue; } + if (auto RC = widenRangeCheckUsingConstantRange(ICI, Guard)) { + Checks.push_back(*RC); + NumWidened++; + continue; + } } // Save the condition as is if we can't widen it Index: llvm/test/Transforms/LoopPredication/constant-ranges.ll =================================================================== --- llvm/test/Transforms/LoopPredication/constant-ranges.ll +++ llvm/test/Transforms/LoopPredication/constant-ranges.ll @@ -1,10 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -passes='loop-mssa(loop-predication)' -loop-predication-insert-assumes-of-predicated-guards-conditions=false < %s 2>&1 | FileCheck %s +; RUN: opt -S -passes='loop-mssa(loop-predication)' -loop-predication-widen-checks-using-contants-range=true -loop-predication-insert-assumes-of-predicated-guards-conditions=false < %s 2>&1 | FileCheck %s define i32 @test_ult(ptr noundef %p, i32 noundef %n, ptr noundef %arr, ptr noundef %len_p, i32 noundef %c) { ; CHECK-LABEL: @test_ult( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0:![0-9]+]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -13,10 +14,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_ULT:%.*]] = icmp ult i32 [[EL]], [[LEN]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULT]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -70,6 +70,7 @@ ; CHECK-LABEL: @test_slt( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -78,10 +79,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLT:%.*]] = icmp slt i32 [[EL]], [[LEN]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLT]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -135,6 +135,7 @@ ; CHECK-LABEL: @test_ule( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -143,10 +144,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_ULE:%.*]] = icmp ule i32 [[EL]], [[LEN]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_ULE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -200,6 +200,7 @@ ; CHECK-LABEL: @test_sle( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -208,10 +209,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sle i32 [[EL]], [[LEN]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -265,6 +265,7 @@ ; CHECK-LABEL: @test_ugt( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -273,10 +274,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp ugt i32 [[LEN]], [[EL]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -330,6 +330,7 @@ ; CHECK-LABEL: @test_uge( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -338,10 +339,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp ult i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp uge i32 [[LEN]], [[EL]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -395,6 +395,7 @@ ; CHECK-LABEL: @test_sgt( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -403,10 +404,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sgt i32 [[LEN]], [[EL]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4 @@ -460,6 +460,7 @@ ; CHECK-LABEL: @test_sge( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_P:%.*]], align 4, !range [[RNG0]], !noundef !1 +; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 127, [[LEN]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] @@ -468,10 +469,9 @@ ; CHECK-NEXT: [[BOUND_CHECK:%.*]] = icmp slt i32 [[EL]], 128 ; CHECK-NEXT: br i1 [[BOUND_CHECK]], label [[DO_RANGE_CHECK:%.*]], label [[BOUND_CHECK_FAILED:%.*]] ; CHECK: do_range_check: -; CHECK-NEXT: [[RANGE_CHECK_SLE:%.*]] = icmp sge i32 [[LEN]], [[EL]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() -; CHECK-NEXT: [[EXPLICIT_GUARD_COND:%.*]] = and i1 [[RANGE_CHECK_SLE]], [[WC]] -; CHECK-NEXT: br i1 [[EXPLICIT_GUARD_COND]], label [[BACKEDGE]], label [[DEOPT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], [[WC]] +; CHECK-NEXT: br i1 [[TMP1]], label [[BACKEDGE]], label [[DEOPT:%.*]] ; CHECK: backedge: ; CHECK-NEXT: [[ARR_PTR:%.*]] = getelementptr i32, ptr [[ARR:%.*]], i32 [[EL]] ; CHECK-NEXT: store i32 [[IV]], ptr [[ARR_PTR]], align 4