Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp +++ lib/Analysis/ScalarEvolution.cpp @@ -9369,10 +9369,7 @@ Optional ScalarEvolution::computeConstantDifference(const SCEV *More, const SCEV *Less) { - // We avoid subtracting expressions here because this function is usually - // fairly deep in the call stack (i.e. is called many times). - - if (isa(Less) && isa(More)) { + while (isa(Less) && isa(More)) { const auto *LAR = cast(Less); const auto *MAR = cast(More); @@ -9393,24 +9390,11 @@ // fall through } - if (isa(Less) && isa(More)) { - const auto &M = cast(More)->getAPInt(); - const auto &L = cast(Less)->getAPInt(); - return M - L; - } - - const SCEV *L, *R; - SCEV::NoWrapFlags Flags; - if (splitBinaryAdd(Less, L, R, Flags)) - if (const auto *LC = dyn_cast(L)) - if (R == More) - return -(LC->getAPInt()); - - if (splitBinaryAdd(More, L, R, Flags)) - if (const auto *LC = dyn_cast(L)) - if (R == Less) - return LC->getAPInt(); - + // We limit recursion depth here because this function is usually + // fairly deep in the call stack (i.e. is called many times). + if (auto *Difference = dyn_cast( + getMinusSCEV(More, Less, SCEV::FlagAnyWrap, MaxArithDepth - 1))) + return Difference->getAPInt(); return None; } Index: test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll =================================================================== --- test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll +++ test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll @@ -101,3 +101,34 @@ return: ; preds = %bb ret void } + +define void @promote_latch_condition_decrementing_loop_01(i32* %p, i32* %a) { + +; CHECK-LABEL: @promote_latch_condition_decrementing_loop_01( +; CHECK-NOT: trunc + +entry: + %len = load i32, i32* %p, align 4, !range !0 + %len.minus.1 = add nsw i32 %len, -1 + %zero_check = icmp eq i32 %len, 0 + br i1 %zero_check, label %loopexit, label %preheader + +preheader: + br label %loop + +loopexit: + ret void + +loop: + %iv = phi i32 [ %iv.next, %loop ], [ %len.minus.1, %preheader ] + ; CHECK: %indvars.iv = phi i64 + %iv.wide = zext i32 %iv to i64 + %el = getelementptr inbounds i32, i32* %a, i64 %iv.wide + store atomic i32 0, i32* %el unordered, align 4 + %iv.next = add nsw i32 %iv, -1 + ; CHECK: %loopcond = icmp slt i64 %indvars.iv, 1 + %loopcond = icmp slt i32 %iv, 1 + br i1 %loopcond, label %loopexit, label %loop +} + +!0 = !{i32 0, i32 2147483647}