diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -13652,11 +13652,35 @@ } } - if (!isa(LHS)) { + if (!isa(LHS) && isa(RHS)) { std::swap(LHS, RHS); Predicate = CmpInst::getSwappedPredicate(Predicate); } + // Check if (LHS Predicate RHS) represent a compare for a range check with a + // single condition, as InstCombine may create. A check of the form + // (-1 + X) u< C where C in [1, unsigned max) can be de-composed into 2 + // separate checks: + // * X u< (1 + C) + // * X u> 0. + if (auto *AddExpr = dyn_cast(LHS)) { + auto *C1 = dyn_cast(AddExpr->getOperand(0)); + auto *C2 = dyn_cast(RHS); + if (AddExpr->getNumOperands() == 2 && C1 && + C1->getValue()->isMinusOne() && Predicate == CmpInst::ICMP_ULT && + C2 && !C2->getAPInt().isMaxValue() && !C2->getAPInt().isNullValue()) { + auto *LHSUnknown = dyn_cast(AddExpr->getOperand(1)); + if (LHSUnknown) { + auto I = RewriteMap.find(LHSUnknown->getValue()); + const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : LHS; + RewriteMap[LHSUnknown->getValue()] = + getUMaxExpr(getOne(RHS->getType()), + getUMinExpr(RewrittenLHS, + getAddExpr(RHS, getOne(RHS->getType())))); + return; + } + } + } // For now, limit to conditions that provide information about unknown // expressions. RHS also cannot contain add recurrences. auto *LHSUnknown = dyn_cast(LHS); diff --git a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll --- a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll +++ b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll @@ -1260,14 +1260,14 @@ ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] -; CHECK-NEXT: --> {0,+,1}<%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {0,+,1}<%loop> U: [0,8) S: [0,8) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64)) + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 -; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %N LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,9) S: [1,9) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @optimized_range_check_unsigned ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) -; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 +; CHECK-NEXT: Loop %loop: max backedge-taken count is 7 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1