Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -1960,6 +1960,28 @@ } } + // zext(umin(x, y)) -> umin(zext(x), zext(y)) + // zext(umax(x, y)) -> umax(zext(x), zext(y)) + if (isa(Op) || isa(Op)) { + auto *MinMax = cast(Op); + SmallVector Operands; + for (auto *Operand : MinMax->operands()) + Operands.push_back(getZeroExtendExpr(Operand, Ty)); + if (isa(MinMax)) + return getUMinExpr(Operands); + else + return getUMaxExpr(Operands); + } + + // zext(umin_seq(x, y)) -> umin_seq(zext(x), zext(y)) + if (auto *MinMax = dyn_cast(Op)) { + assert(isa(MinMax) && "Not supported!"); + SmallVector Operands; + for (auto *Operand : MinMax->operands()) + Operands.push_back(getZeroExtendExpr(Operand, Ty)); + return getUMinExpr(Operands, /*Sequential*/ true); + } + // The cast wasn't folded; create an explicit cast node. // Recompute the insert position, as it may have been invalidated. if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; @@ -2220,6 +2242,19 @@ if (isKnownNonNegative(Op)) return getZeroExtendExpr(Op, Ty, Depth + 1); + // sext(smin(x, y)) -> smin(sext(x), sext(y)) + // sext(smax(x, y)) -> smax(sext(x), sext(y)) + if (isa(Op) || isa(Op)) { + auto *MinMax = cast(Op); + SmallVector Operands; + for (auto *Operand : MinMax->operands()) + Operands.push_back(getSignExtendExpr(Operand, Ty)); + if (isa(MinMax)) + return getSMinExpr(Operands); + else + return getSMaxExpr(Operands); + } + // The cast wasn't folded; create an explicit cast node. // Recompute the insert position, as it may have been invalidated. if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; Index: llvm/test/Analysis/ScalarEvolution/ext_min_max.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/ext_min_max.ll +++ llvm/test/Analysis/ScalarEvolution/ext_min_max.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py ; RUN: opt -S -disable-output "-passes=print" < %s 2>&1 | FileCheck %s -; TODO: Make sure that zext(umin(x, y)) has same SCEV as umin(zext(x), zext(y)). +; Make sure that zext(umin(x, y)) has same SCEV as umin(zext(x), zext(y)). ; Equality proof: https://alive2.llvm.org/ce/z/vdsvmp define i1 @test_umin(i32 %x, i32 %y) { ; CHECK-LABEL: 'test_umin' @@ -9,7 +9,7 @@ ; CHECK-NEXT: %umin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y ; CHECK-NEXT: --> (%x umin %y) U: full-set S: full-set ; CHECK-NEXT: %zext_umin_x_y = zext i32 %umin_x_y to i64 -; CHECK-NEXT: --> (zext i32 (%x umin %y) to i64) U: [0,4294967296) S: [0,4294967296) +; CHECK-NEXT: --> ((zext i32 %x to i64) umin (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296) ; CHECK-NEXT: %zext_x = zext i32 %x to i64 ; CHECK-NEXT: --> (zext i32 %x to i64) U: [0,4294967296) S: [0,4294967296) ; CHECK-NEXT: %zext_y = zext i32 %y to i64 @@ -31,7 +31,7 @@ ret i1 %they_are_same } -; TODO: Make sure that zext(umax(x, y)) has same SCEV as umax(zext(x), zext(y)). +; Make sure that zext(umax(x, y)) has same SCEV as umax(zext(x), zext(y)). ; Equality proof: https://alive2.llvm.org/ce/z/5JHgxZ define i1 @test_umax(i32 %x, i32 %y) { ; CHECK-LABEL: 'test_umax' @@ -39,7 +39,7 @@ ; CHECK-NEXT: %umax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x ; CHECK-NEXT: --> (%x umax %y) U: full-set S: full-set ; CHECK-NEXT: %zext_umax_x_y = zext i32 %umax_x_y to i64 -; CHECK-NEXT: --> (zext i32 (%x umax %y) to i64) U: [0,4294967296) S: [0,4294967296) +; CHECK-NEXT: --> ((zext i32 %x to i64) umax (zext i32 %y to i64)) U: [0,4294967296) S: [0,4294967296) ; CHECK-NEXT: %zext_x = zext i32 %x to i64 ; CHECK-NEXT: --> (zext i32 %x to i64) U: [0,4294967296) S: [0,4294967296) ; CHECK-NEXT: %zext_y = zext i32 %y to i64 @@ -61,7 +61,7 @@ ret i1 %they_are_same } -; TODO: Make sure that sext(smin(x, y)) has same SCEV as smin(sext(x), sext(y)). +; Make sure that sext(smin(x, y)) has same SCEV as smin(sext(x), sext(y)). ; Equality proof: https://alive2.llvm.org/ce/z/HhYHzR define i1 @test_smin(i32 %x, i32 %y) { ; CHECK-LABEL: 'test_smin' @@ -69,7 +69,7 @@ ; CHECK-NEXT: %smin_x_y = select i1 %cmp_x_y, i32 %x, i32 %y ; CHECK-NEXT: --> (%x smin %y) U: full-set S: full-set ; CHECK-NEXT: %sext_smin_x_y = sext i32 %smin_x_y to i64 -; CHECK-NEXT: --> (sext i32 (%x smin %y) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) +; CHECK-NEXT: --> ((sext i32 %x to i64) smin (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648) ; CHECK-NEXT: %sext_x = sext i32 %x to i64 ; CHECK-NEXT: --> (sext i32 %x to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) ; CHECK-NEXT: %sext_y = sext i32 %y to i64 @@ -91,7 +91,7 @@ ret i1 %they_are_same } -; TODO: Make sure that sext(smax(x, y)) has same SCEV as smax(sext(x), sext(y)). +; Make sure that sext(smax(x, y)) has same SCEV as smax(sext(x), sext(y)). ; Equality proof: https://alive2.llvm.org/ce/z/uou_u- define i1 @test_smax(i32 %x, i32 %y) { ; CHECK-LABEL: 'test_smax' @@ -99,7 +99,7 @@ ; CHECK-NEXT: %smax_x_y = select i1 %cmp_x_y, i32 %y, i32 %x ; CHECK-NEXT: --> (%x smax %y) U: full-set S: full-set ; CHECK-NEXT: %sext_smax_x_y = sext i32 %smax_x_y to i64 -; CHECK-NEXT: --> (sext i32 (%x smax %y) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) +; CHECK-NEXT: --> ((sext i32 %x to i64) smax (sext i32 %y to i64)) U: [-2147483648,2147483648) S: [-2147483648,2147483648) ; CHECK-NEXT: %sext_x = sext i32 %x to i64 ; CHECK-NEXT: --> (sext i32 %x to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) ; CHECK-NEXT: %sext_y = sext i32 %y to i64 @@ -121,7 +121,7 @@ ret i1 %they_are_same } -; TODO: Make sure that zext(umin_seq(x, y)) has same SCEV as umin_seq(zext(x), zext(y)). +; Make sure that zext(umin_seq(x, y)) has same SCEV as umin_seq(zext(x), zext(y)). ; Equality proof: https://alive2.llvm.org/ce/z/X8kaNx define i1 @test_umin_seq(i1 %x, i1 %y) { ; CHECK-LABEL: 'test_umin_seq' @@ -129,7 +129,7 @@ ; CHECK-NEXT: %x_umin_seq_y = select i1 %x, i1 %y, i1 false ; CHECK-NEXT: --> (%x umin_seq %y) U: full-set S: full-set ; CHECK-NEXT: %zext_x_umin_seq_y = zext i1 %x_umin_seq_y to i64 -; CHECK-NEXT: --> (zext i1 (%x umin_seq %y) to i64) U: [0,2) S: [0,2) +; CHECK-NEXT: --> ((zext i1 %x to i64) umin_seq (zext i1 %y to i64)) U: [0,2) S: [0,2) ; CHECK-NEXT: %zext_x = zext i1 %x to i64 ; CHECK-NEXT: --> (zext i1 %x to i64) U: [0,2) S: [0,2) ; CHECK-NEXT: %zext_y = zext i1 %y to i64 Index: llvm/test/Analysis/ScalarEvolution/fold.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/fold.ll +++ llvm/test/Analysis/ScalarEvolution/fold.ll @@ -67,15 +67,15 @@ ; CHECK-NEXT: %D = sext i16 %B to i32 ; CHECK-NEXT: --> ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %E = sext i16 %B to i34 -; CHECK-NEXT: --> (zext i32 ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) to i34) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> ((zext i32 ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>) to i34) umax {0,+,1}<%loop>) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %F = zext i16 %B to i30 -; CHECK-NEXT: --> (trunc i32 ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) to i30) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> (trunc i32 ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) to i30) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %G = zext i16 %B to i32 -; CHECK-NEXT: --> ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %H = zext i16 %B to i34 -; CHECK-NEXT: --> (zext i32 ({0,+,1}<%loop> umax ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>)) to i34) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> ((zext i32 ((zext i2 (trunc i32 %y to i2) to i32) smax {0,+,1}<%loop>) to i34) umax {0,+,1}<%loop>) U: [0,21) S: [0,21) Exits: 20 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %I = add i32 %A, 1 -; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,22) S: [1,22) Exits: 21 LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,22) S: [1,22) Exits: 21 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test4 ; CHECK-NEXT: Loop %loop: backedge-taken count is 20 ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 20 Index: llvm/test/Analysis/ScalarEvolution/logical-operations.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/logical-operations.ll +++ llvm/test/Analysis/ScalarEvolution/logical-operations.ll @@ -707,9 +707,9 @@ ; CHECK-NEXT: %umin.narrow = call i8 @llvm.umin.i8(i8 %y, i8 %x) ; CHECK-NEXT: --> (%x umin %y) U: full-set S: full-set ; CHECK-NEXT: %umin = zext i8 %umin.narrow to i32 -; CHECK-NEXT: --> (zext i8 (%x umin %y) to i32) U: [0,256) S: [0,256) +; CHECK-NEXT: --> ((zext i8 %x to i32) umin (zext i8 %y to i32)) U: [0,256) S: [0,256) ; CHECK-NEXT: %r = select i1 %x.is.zero, i32 0, i32 %umin -; CHECK-NEXT: --> ((zext i8 %x to i32) umin_seq (zext i8 (%x umin %y) to i32)) U: [0,256) S: [0,256) +; CHECK-NEXT: --> ((zext i8 %x to i32) umin_seq (zext i8 %y to i32)) U: [0,256) S: [0,256) ; CHECK-NEXT: Determining loop execution counts for: @umin_seq_x_y_zext_of_umin ; %umin.narrow = call i8 @llvm.umin.i8(i8 %y, i8 %x) Index: llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll +++ llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info-rewrite-expressions.ll @@ -44,26 +44,27 @@ } ; Test case from PR40961. +; TODO: Loop %loop: constant max backedge-taken count is 3 define i32 @rewrite_zext_min_max(i32 %N, ptr %arr) { ; CHECK-LABEL: 'rewrite_zext_min_max' ; CHECK-NEXT: Classifying expressions for: @rewrite_zext_min_max ; CHECK-NEXT: %umin = call i32 @llvm.umin.i32(i32 %N, i32 16) ; CHECK-NEXT: --> (16 umin %N) U: [0,17) S: [0,17) ; CHECK-NEXT: %ext = zext i32 %umin to i64 -; CHECK-NEXT: --> (zext i32 (16 umin %N) to i64) U: [0,17) S: [0,17) +; CHECK-NEXT: --> (16 umin (zext i32 %N to i64)) U: [0,17) S: [0,17) ; CHECK-NEXT: %n.vec = and i64 %ext, 28 -; CHECK-NEXT: --> (4 * ((zext i32 (16 umin %N) to i64) /u 4)) U: [0,17) S: [0,17) +; CHECK-NEXT: --> (4 * ((16 umin (zext i32 %N to i64)) /u 4)) U: [0,17) S: [0,17) ; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ] -; CHECK-NEXT: --> {0,+,4}<%loop> U: [0,13) S: [0,13) Exits: (4 * ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4)) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {0,+,4}<%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4)) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i32, ptr %arr, i64 %index -; CHECK-NEXT: --> {%arr,+,16}<%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4)) + %arr) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {%arr,+,16}<%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4)) + %arr) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %index.next = add nuw i64 %index, 4 -; CHECK-NEXT: --> {4,+,4}<%loop> U: [4,17) S: [4,17) Exits: (4 + (4 * ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4))) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {4,+,4}<%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4))) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_min_max -; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4) -; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 3 -; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4) -; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * ((zext i32 (16 umin %N) to i64) /u 4))) /u 4) +; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4) +; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 4611686018427387903 +; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4) +; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))) /u 4) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; Index: llvm/test/Analysis/ScalarEvolution/ptrtoint.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/ptrtoint.ll +++ llvm/test/Analysis/ScalarEvolution/ptrtoint.ll @@ -288,7 +288,7 @@ ; X32-NEXT: %s = select i1 %c, ptr %in0, ptr %in1 ; X32-NEXT: --> (%in0 umax %in1) U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint ptr %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint ptr %in0 to i32) umax (ptrtoint ptr %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> ((zext i32 (ptrtoint ptr %in0 to i32) to i64) umax (zext i32 (ptrtoint ptr %in1 to i32) to i64)) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_umax ; %c = icmp uge ptr %in0, %in1 @@ -336,7 +336,7 @@ ; X32-NEXT: %s = select i1 %c, ptr %in0, ptr %in1 ; X32-NEXT: --> (%in0 umin %in1) U: full-set S: full-set ; X32-NEXT: %p0 = ptrtoint ptr %s to i64 -; X32-NEXT: --> (zext i32 ((ptrtoint ptr %in0 to i32) umin (ptrtoint ptr %in1 to i32)) to i64) U: [0,4294967296) S: [0,4294967296) +; X32-NEXT: --> ((zext i32 (ptrtoint ptr %in0 to i32) to i64) umin (zext i32 (ptrtoint ptr %in1 to i32) to i64)) U: [0,4294967296) S: [0,4294967296) ; X32-NEXT: Determining loop execution counts for: @ptrtoint_of_umin ; %c = icmp ule ptr %in0, %in1 Index: llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll +++ llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll @@ -86,7 +86,7 @@ ; CHECK-NEXT: %index32 = add nsw i32 %nexti, %max ; CHECK-NEXT: --> {(-1 + (-10 smin %offset)),+,-1}<%loop> U: [-2147483648,-10) S: [-2147483648,-10) Exits: ((-10 smin %offset) + %numIterations) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr = getelementptr inbounds float, ptr %input, i32 %index32 -; CHECK-NEXT: --> {(-4 + (4 * (sext i32 (-10 smin %offset) to i64)) + %input),+,-4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * (sext i32 (-10 smin %offset) to i64)) + (-4 * (zext i32 (-1 + (-1 * %numIterations)) to i64)) + %input) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {(-4 + (4 * (-10 smin (sext i32 %offset to i64))) + %input),+,-4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * (-10 smin (sext i32 %offset to i64))) + (-4 * (zext i32 (-1 + (-1 * %numIterations)) to i64)) + %input) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test-addrec-nsw-start-neg-strip-neg ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %numIterations)) ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1 @@ -124,7 +124,7 @@ ; CHECK-NEXT: %index32 = add nsw i32 %nexti, %max ; CHECK-NEXT: --> {(-1 + (10 smin %offset)),+,-1}<%loop> U: [-2147483648,10) S: [-2147483648,10) Exits: ((10 smin %offset) + %numIterations) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr = getelementptr inbounds float, ptr %input, i32 %index32 -; CHECK-NEXT: --> {(-4 + (4 * (sext i32 (10 smin %offset) to i64)) + %input),+,-4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * (sext i32 (10 smin %offset) to i64)) + (-4 * (zext i32 (-1 + (-1 * %numIterations)) to i64)) + %input) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {(-4 + (4 * (10 smin (sext i32 %offset to i64))) + %input),+,-4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * (10 smin (sext i32 %offset to i64))) + (-4 * (zext i32 (-1 + (-1 * %numIterations)) to i64)) + %input) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test-addrec-nsw-start-pos-strip-neg ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + (-1 * %numIterations)) ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1 @@ -200,7 +200,7 @@ ; CHECK-NEXT: %index32 = add nsw i32 %nexti, %min ; CHECK-NEXT: --> {(1 + (-10 smax %offset)),+,1}<%loop> U: [-9,-2147483648) S: [-9,-2147483648) Exits: ((-10 smax %offset) + %numIterations) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %ptr = getelementptr inbounds float, ptr %input, i32 %index32 -; CHECK-NEXT: --> {(4 + (4 * (sext i32 (-10 smax %offset) to i64)) + %input),+,4}<%loop> U: full-set S: full-set Exits: (4 + (4 * (zext i32 (-1 + %numIterations) to i64)) + (4 * (sext i32 (-10 smax %offset) to i64)) + %input) LoopDispositions: { %loop: Computable } +; CHECK-NEXT: --> {(4 + (4 * (-10 smax (sext i32 %offset to i64))) + %input),+,4}<%loop> U: full-set S: full-set Exits: (4 + (4 * (zext i32 (-1 + %numIterations) to i64)) + (4 * (-10 smax (sext i32 %offset to i64))) + %input) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test-addrec-nsw-start-neg-strip-pos ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %numIterations) ; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1