Original file line number Diff line number Diff line change
Expand Up @@ -90,53 +90,6 @@ exit:
ret i32 0
}

; TODO: Same as rewrite_zext_min_max, but the loop is guarded by narrow check.
define i32 @rewrite_zext_min_max_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_min_max_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_min_max_narrow_check
; 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: --> (16 umin (zext i32 %N to i64)) U: [0,17) S: [0,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> U: [0,17) S: [0,17)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw> 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 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_min_max_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /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))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%umin = call i32 @llvm.umin.i32(i32 %N, i32 16)
%ext = zext i32 %umin to i64
%min.iters.check = icmp ult i32 %umin, 4
br i1 %min.iters.check, label %exit, label %loop.ph

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16) and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

; This is same as rewrite_zext_min_max, but zext and umin are swapped.
; It should be able to prove the same exit count.
define i32 @rewrite_min_max_zext(i32 %N, ptr %arr) {
Expand Down Expand Up @@ -233,54 +186,6 @@ exit:
ret i32 0
}

; TODO: same as rewrite_sext_min_max, but the loop is guarded by narrow check.
; It should be able to prove the same exit count.
define i32 @rewrite_sext_min_max_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_sext_min_max_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_sext_min_max_narrow_check
; CHECK-NEXT: %smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
; CHECK-NEXT: --> (16 smin %N) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %ext = sext i32 %smin to i64
; CHECK-NEXT: --> (16 smin (sext i32 %N to i64)) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %gep = getelementptr inbounds i32, ptr %arr, i64 %index
; CHECK-NEXT: --> {%arr,+,16}<nuw><%loop> U: full-set S: full-set Exits: ((16 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nsw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><nsw><%loop> U: [4,-9223372036854775808) S: [4,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_sext_min_max_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
%ext = sext i32 %smin to i64
%min.iters.check = icmp slt i32 %smin, 4
br i1 %min.iters.check, label %exit, label %loop.ph

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16) and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nsw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

; This is a signed version of rewrite_min_max_zext.
; It should be able to prove the same exit count.
define i32 @rewrite_min_max_sext(i32 %N, ptr %arr) {
Expand Down Expand Up @@ -560,9 +465,381 @@ loop:
exit:
ret void
}

define i32 @rewrite_sext_slt_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_sext_slt_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_sext_slt_narrow_check
; CHECK-NEXT: %smin = call i32 @llvm.smax.i32(i32 %N, i32 4)
; CHECK-NEXT: --> (4 smax %N) U: [4,-2147483648) S: [4,-2147483648)
; CHECK-NEXT: %ext = sext i32 %smin to i64
; CHECK-NEXT: --> (zext i32 (4 smax %N) to i64) U: [4,2147483648) S: [4,2147483648)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_sext_slt_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%smin = call i32 @llvm.smax.i32(i32 %N, i32 4)
%ext = sext i32 %smin to i64
%min.iters.check = icmp slt i32 %smin, 17
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_zext_ult_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_ult_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_ult_narrow_check
; CHECK-NEXT: %umin = call i32 @llvm.umax.i32(i32 %N, i32 4)
; CHECK-NEXT: --> (4 umax %N) U: [4,0) S: [4,0)
; CHECK-NEXT: %ext = zext i32 %umin to i64
; CHECK-NEXT: --> (4 umax (zext i32 %N to i64)) U: [4,4294967296) S: [4,4294967296)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_ult_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%umin = call i32 @llvm.umax.i32(i32 %N, i32 4)
%ext = zext i32 %umin to i64
%min.iters.check = icmp ult i32 %umin, 17
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_zext_ule_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_ule_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_ule_narrow_check
; CHECK-NEXT: %umin = call i32 @llvm.umax.i32(i32 %N, i32 4)
; CHECK-NEXT: --> (4 umax %N) U: [4,0) S: [4,0)
; CHECK-NEXT: %ext = zext i32 %umin to i64
; CHECK-NEXT: --> (4 umax (zext i32 %N to i64)) U: [4,4294967296) S: [4,4294967296)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_ule_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((4 umax (zext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%umin = call i32 @llvm.umax.i32(i32 %N, i32 4)
%ext = zext i32 %umin to i64
%min.iters.check = icmp ule i32 %umin, 16
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_zext_sle_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_sle_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_sle_narrow_check
; CHECK-NEXT: %smin = call i32 @llvm.smax.i32(i32 %N, i32 4)
; CHECK-NEXT: --> (4 smax %N) U: [4,-2147483648) S: [4,-2147483648)
; CHECK-NEXT: %ext = sext i32 %smin to i64
; CHECK-NEXT: --> (zext i32 (4 smax %N) to i64) U: [4,2147483648) S: [4,2147483648)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_sle_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((zext i32 (4 smax %N) to i64) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%smin = call i32 @llvm.smax.i32(i32 %N, i32 4)
%ext = sext i32 %smin to i64
%min.iters.check = icmp sle i32 %smin, 17
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_zext_uge_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_uge_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_uge_narrow_check
; 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: --> (16 umin (zext i32 %N to i64)) U: [0,17) S: [0,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> U: [0,17) S: [0,17)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw> 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 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_uge_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /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))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%umin = call i32 @llvm.umin.i32(i32 %N, i32 16)
%ext = zext i32 %umin to i64
%min.iters.check = icmp uge i32 %umin, 4
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_sext_sge_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_sext_sge_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_sext_sge_narrow_check
; CHECK-NEXT: %smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
; CHECK-NEXT: --> (16 smin %N) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %ext = sext i32 %smin to i64
; CHECK-NEXT: --> (16 smin (sext i32 %N to i64)) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_sext_sge_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
%ext = sext i32 %smin to i64
%min.iters.check = icmp sge i32 %smin, 4
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_zext_ugt_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_zext_ugt_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_zext_ugt_narrow_check
; 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: --> (16 umin (zext i32 %N to i64)) U: [0,17) S: [0,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw> U: [0,17) S: [0,17)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw> 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 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_zext_ugt_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /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))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * ((16 umin (zext i32 %N to i64)) /u 4))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%umin = call i32 @llvm.umin.i32(i32 %N, i32 16)
%ext = zext i32 %umin to i64
%min.iters.check = icmp ugt i32 %umin, 3
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16] and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

define i32 @rewrite_sext_sgt_narrow_check(i32 %N, ptr %arr) {
; CHECK-LABEL: 'rewrite_sext_sgt_narrow_check'
; CHECK-NEXT: Classifying expressions for: @rewrite_sext_sgt_narrow_check
; CHECK-NEXT: %smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
; CHECK-NEXT: --> (16 smin %N) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %ext = sext i32 %smin to i64
; CHECK-NEXT: --> (16 smin (sext i32 %N to i64)) U: [-2147483648,17) S: [-2147483648,17)
; CHECK-NEXT: %n.vec = and i64 %ext, 28
; CHECK-NEXT: --> (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw> U: [0,29) S: [0,29)
; CHECK-NEXT: %index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw> 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 i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)) + %arr) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %index.next = add nuw i64 %index, 4
; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-9223372036854775808,9223372036854775805) Exits: (4 + (4 * ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4))<nuw>) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @rewrite_sext_sgt_narrow_check
; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /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 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + (4 * (zext i3 (trunc i64 ((16 smin (sext i32 %N to i64)) /u 4) to i3) to i64))<nuw><nsw>)<nsw> /u 4)
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
entry:
%smin = call i32 @llvm.smin.i32(i32 %N, i32 16)
%ext = sext i32 %smin to i64
%min.iters.check = icmp sgt i32 %smin, 3
br i1 %min.iters.check, label %loop.ph, label %exit

loop.ph:
%n.vec = and i64 %ext, 28
br label %loop

; %n.vec is [4, 16) and a multiple of 4.
loop:
%index = phi i64 [ 0, %loop.ph ], [ %index.next, %loop ]
%gep = getelementptr inbounds i32, ptr %arr, i64 %index
store i32 0, ptr %gep
%index.next = add nuw i64 %index, 4
%ec = icmp eq i64 %index.next, %n.vec
br i1 %ec, label %exit, label %loop

exit:
ret i32 0
}

declare void @use(i64)

declare i32 @llvm.umin.i32(i32, i32)
declare i64 @llvm.umin.i64(i64, i64)
declare i32 @llvm.smin.i32(i32, i32)
declare i64 @llvm.smin.i64(i64, i64)

declare i32 @llvm.umax.i32(i32, i32)
declare i32 @llvm.smax.i32(i32, i32)