[ConstraintElim] Add extra tests and split up test file.
authorFlorian Hahn <flo@fhahn.com>
Fri, 30 Jun 2023 14:16:23 +0000 (15:16 +0100)
committerFlorian Hahn <flo@fhahn.com>
Fri, 30 Jun 2023 14:16:23 +0000 (15:16 +0100)
Extra tests for D152730, including more tests where the step GEP doesn't
use the phi and inbounds are missing.

Also split up test file to make it easier to verify for Alive2.

llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll [new file with mode: 0644]
llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll

diff --git a/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll b/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll
new file mode 100644 (file)
index 0000000..df4ed11
--- /dev/null
@@ -0,0 +1,914 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+
+declare void @use(ptr)
+declare void @use.i1(i1)
+declare void @llvm.assume(i1)
+declare i1 @cond()
+
+define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i8, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
+; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %start.ult.end = icmp uge ptr %start, %end
+  br i1 %start.ult.end, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %end
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %end
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
+; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %start.ult.end = icmp uge ptr %start, %end
+  br i1 %start.ult.end, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %end
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %end
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[START_ULT_END]])
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %end, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  %start.ult.end = icmp ult ptr %start, %upper
+  call void @llvm.assume(i1 %start.ult.end)
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %step.pos = icmp sge i16 %step, 0
+  call void @llvm.assume(i1 %step.pos)
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %then, label %exit
+
+then:
+  %c.2 = icmp uge ptr %ptr.iv, %start
+  %c.3 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.2, %c.3
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
+; CHECK:       then:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %for.body
+
+for.body:
+  %c.1 = icmp ne ptr %ptr.iv, %upper
+  br i1 %c.1, label %then, label %loop.latch
+
+then:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  call void @use.i1(i1 %and)
+  br label %loop.latch
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]]
+; CHECK:       then:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.1 = icmp ne ptr %ptr.iv, %upper
+  br i1 %c.1, label %then, label %for.body
+
+for.body:
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %loop.latch
+
+then:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  call void @use.i1(i1 %and)
+  br label %loop.latch
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
+; CHECK:       then:
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %for.body
+
+for.body:
+  %c.1 = icmp ne ptr %ptr.iv, %upper
+  br i1 %c.1, label %then, label %loop.latch
+
+then:
+  br label %loop.latch
+
+loop.latch:
+  %c.2 = icmp uge ptr %ptr.iv, %start
+  %c.3 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.2, %c.3
+  call void @use.i1(i1 %and)
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.1 = icmp eq ptr %ptr.iv, %upper
+  br i1 %c.1, label %exit, label %for.body
+
+for.body:
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %then
+
+then:
+  %c.2 = icmp uge ptr %ptr.iv, %start
+  %c.3 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.2, %c.3
+  call void @use.i1(i1 %and)
+  br label %loop.latch
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    br label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %for.body
+
+for.body:
+  %c.1 = icmp ne ptr %ptr.iv, %upper
+  br i1 %c.1, label %then, label %loop.latch
+
+then:
+  %c.2 = icmp uge ptr %ptr.iv, %start
+  %c.3 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.2, %c.3
+  call void @use.i1(i1 %and)
+  br label %loop.latch
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+
+define void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NEG]])
+; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
+; CHECK-NEXT:    br label [[EXIT_2]]
+; CHECK:       exit.2:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp sge i16 %len, 0
+  call void @llvm.assume(i1 %len.neg)
+  br label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c.0 = call i1 @cond()
+  br i1 %c.0, label %exit, label %loop.latch
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  %c.1 = icmp ne ptr %ptr.iv, %upper
+  br i1 %c.1, label %then, label %exit.2
+
+then:
+  %c.2 = icmp uge ptr %ptr.iv, %start
+  %c.3 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.2, %c.3
+  call void @use.i1(i1 %and)
+  br label %exit.2
+
+exit.2:
+  ret void
+}
+
+define void @test_step_gep_doesnt_use_ptr_iv_phi(ptr %start, ptr %other, i16 %len) {
+; CHECK-LABEL: @test_step_gep_doesnt_use_ptr_iv_phi(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[OTHER:%.*]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds float, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds float, ptr %other, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_step_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
+; CHECK-LABEL: @test_step_gep_not_inbounds(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr float, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr inbounds float, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr float, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @test_upper_gep_not_inbounds(ptr %start, ptr %end, i16 %len) {
+; CHECK-LABEL: @test_upper_gep_not_inbounds(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr float, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK:       for.body:
+; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK:       loop.next:
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %upper = getelementptr float, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
+  br label %loop.header
+
+loop.header:
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
+  br i1 %c, label %exit, label %for.body
+
+for.body:
+  %c.1 = call i1 @cond()
+  br i1 %c.1, label %loop.next, label %exit
+
+loop.next:
+  %t.1 = icmp uge ptr %ptr.iv, %start
+  %t.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %t.1, %t.2
+  br i1 %and, label %loop.latch, label %exit
+
+loop.latch:
+  call void @use(ptr %ptr.iv)
+  %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i16 1
+  br label %loop.header
+
+exit:
+  ret void
+}
index aedfad6..e6603ec 100644 (file)
@@ -264,124 +264,6 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
-; CHECK:       loop.next:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
-; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %loop.next, label %exit
-
-loop.next:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %t.1, %t.2
-  br i1 %and, label %loop.latch, label %exit
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-define void @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_different_element_types_1_with_early_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
-; CHECK:       loop.next:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
-; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i8, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %loop.next, label %exit
-
-loop.next:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %t.1, %t.2
-  br i1 %and, label %loop.latch, label %exit
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
 define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(ptr %start, ptr %end) {
 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr(
 ; CHECK-NEXT:  entry:
@@ -482,137 +364,116 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i8_unknown_end_ptr_with_early_exit(
+define void @test_ptr_iv_upper_may_be_less_than_start(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_ptr_iv_upper_may_be_less_than_start(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
-; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
 ; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
-; CHECK:       loop.next:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %start.ult.end = icmp uge ptr %start, %end
-  br i1 %start.ult.end, label %exit, label %loop.ph
-
-loop.ph:
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
   br label %loop.header
 
 loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %end
+  %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
+  %c = icmp eq ptr %ptr.iv, %upper
   br i1 %c, label %exit, label %for.body
 
 for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %loop.next, label %exit
-
-loop.next:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %end
-  %and = and i1 %t.1, %t.2
+  %c.1 = icmp uge ptr %ptr.iv, %start
+  %c.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.1, %c.2
   br i1 %and, label %loop.latch, label %exit
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i16 1
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(ptr %start, ptr %end) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_gep_step_size_i32_unknown_end_ptr_with_early_exit(
+define void @test_no_ptr_iv_step_inst_doesnt_use_phi(ptr %start, ptr %p, i16 %len) {
+; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp uge ptr [[START:%.*]], [[END:%.*]]
-; CHECK-NEXT:    br i1 [[START_ULT_END]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
 ; CHECK:       loop.ph:
 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
 ; CHECK:       loop.header:
 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
-; CHECK:       loop.next:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[END]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[P:%.*]], i16 1
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %start.ult.end = icmp uge ptr %start, %end
-  br i1 %start.ult.end, label %exit, label %loop.ph
+  %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
 
 loop.ph:
   br label %loop.header
 
 loop.header:
   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %end
+  %c = icmp eq ptr %ptr.iv, %upper
   br i1 %c, label %exit, label %for.body
 
 for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %loop.next, label %exit
-
-loop.next:
   %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %end
+  %t.2 = icmp ult ptr %ptr.iv, %upper
   %and = and i1 %t.1, %t.2
   br i1 %and, label %loop.latch, label %exit
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  %ptr.iv.next = getelementptr inbounds i32, ptr %p, i16 1
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(ptr %start, ptr %end, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_exit_and_different_upper(
+define void @test_no_ptr_iv_step_inst_doesnt_use_phi_2(ptr %start, ptr %end, i16 %len) {
+; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi_2(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[END:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds float, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
 ; CHECK:       loop.ph:
-; CHECK-NEXT:    [[START_ULT_END:%.*]] = icmp ult ptr [[START:%.*]], [[UPPER]]
-; CHECK-NEXT:    call void @llvm.assume(i1 [[START_ULT_END]])
 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
 ; CHECK:       loop.header:
 ; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[PTR_IV_2:%.*]] = phi ptr [ [[END:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT]], [[LOOP_LATCH]] ]
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_NEXT:%.*]], label [[EXIT]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[LOOP_NEXT:%.*]]
 ; CHECK:       loop.next:
 ; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
 ; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
@@ -620,29 +481,24 @@ define void @test_monotonic_ptr_iv_inc_1_different_element_types_1_with_early_ex
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds float, ptr [[PTR_IV_2]], i16 1
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
 ;
 entry:
-  %upper = getelementptr inbounds i32, ptr %end, i16 %len
+  %upper = getelementptr inbounds float, ptr %start, i16 %len
   %len.neg = icmp slt i16 %len, 0
   br i1 %len.neg, label %exit, label %loop.ph
 
 loop.ph:
-  %start.ult.end = icmp ult ptr %start, %upper
-  call void @llvm.assume(i1 %start.ult.end)
   br label %loop.header
 
 loop.header:
   %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %ptr.iv.2 = phi ptr [ %end, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
   %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %loop.next, label %exit
+  br i1 %c, label %exit, label %loop.next
 
 loop.next:
   %t.1 = icmp uge ptr %ptr.iv, %start
@@ -652,22 +508,25 @@ loop.next:
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  %ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv.2, i16 1
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_ptr_iv_upper_may_be_less_than_start(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_ptr_iv_upper_may_be_less_than_start(
+define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
+; CHECK-LABEL: @test_no_ptr_iv_different_start(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
+; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
+; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
+; CHECK:       loop.ph:
 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
 ; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[P:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT:%.*]], label [[FOR_BODY:%.*]]
+; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
@@ -682,10 +541,14 @@ define void @test_ptr_iv_upper_may_be_less_than_start(ptr %start, i16 %len) {
 ;
 entry:
   %upper = getelementptr inbounds i32, ptr %start, i16 %len
+  %len.neg = icmp slt i16 %len, 0
+  br i1 %len.neg, label %exit, label %loop.ph
+
+loop.ph:
   br label %loop.header
 
 loop.header:
-  %ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop.latch ]
+  %ptr.iv = phi ptr [ %p, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
   %c = icmp eq ptr %ptr.iv, %upper
   br i1 %c, label %exit, label %for.body
 
@@ -704,8 +567,8 @@ exit:
   ret void
 }
 
-define void @test_no_ptr_iv_step_inst_doesnt_use_phi(ptr %start, ptr %p, i16 %len) {
-; CHECK-LABEL: @test_no_ptr_iv_step_inst_doesnt_use_phi(
+define void @test_ptr_iv_not_inbounds(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_ptr_iv_not_inbounds(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
@@ -717,13 +580,13 @@ define void @test_no_ptr_iv_step_inst_doesnt_use_phi(ptr %start, ptr %p, i16 %le
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[P:%.*]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -742,22 +605,22 @@ loop.header:
   br i1 %c, label %exit, label %for.body
 
 for.body:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %t.1, %t.2
+  %c.1 = icmp uge ptr %ptr.iv, %start
+  %c.2 = icmp ult ptr %ptr.iv, %upper
+  %and = and i1 %c.1, %c.2
   br i1 %and, label %loop.latch, label %exit
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %p, i16 1
+  %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
-; CHECK-LABEL: @test_no_ptr_iv_different_start(
+define void @test_var_step_not_monotonic(ptr %start, i16 %len, i16 %step) {
+; CHECK-LABEL: @test_var_step_not_monotonic(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
@@ -765,7 +628,7 @@ define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
 ; CHECK:       loop.ph:
 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
 ; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[P:%.*]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
@@ -775,7 +638,7 @@ define void @test_no_ptr_iv_different_start(ptr %start, ptr %p, i16 %len) {
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -789,7 +652,7 @@ loop.ph:
   br label %loop.header
 
 loop.header:
-  %ptr.iv = phi ptr [ %p, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
+  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
   %c = icmp eq ptr %ptr.iv, %upper
   br i1 %c, label %exit, label %for.body
 
@@ -801,15 +664,15 @@ for.body:
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_ptr_iv_not_inbounds(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_ptr_iv_not_inbounds(
+define void @test_monotonic_ptr_iv_step_neg_1(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_neg_1(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
@@ -827,7 +690,7 @@ define void @test_ptr_iv_not_inbounds(ptr %start, i16 %len) {
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr i32, ptr [[PTR_IV]], i16 1
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 -1
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -853,15 +716,15 @@ for.body:
 
 loop.latch:
   call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i16 1
+  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 -1
   br label %loop.header
 
 exit:
   ret void
 }
 
-define void @test_var_step_not_monotonic(ptr %start, i16 %len, i16 %step) {
-; CHECK-LABEL: @test_var_step_not_monotonic(
+define void @test_monotonic_ptr_iv_step_sign_unknown(ptr %start, i16 %len, i16 %step) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_unknown(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
@@ -912,9 +775,11 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_step_neg_1(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_neg_1(
+define void @test_monotonic_ptr_iv_step_sign_positive_through_assume(ptr %start, i16 %len, i16 %step) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
 ; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
 ; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
 ; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
@@ -925,119 +790,13 @@ define void @test_monotonic_ptr_iv_step_neg_1(ptr %start, i16 %len) {
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
 ; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
+; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
+; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
 ; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
 ; CHECK:       loop.latch:
 ; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 -1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = icmp uge ptr %ptr.iv, %start
-  %c.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.1, %c.2
-  br i1 %and, label %loop.latch, label %exit
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 -1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-define void @test_monotonic_ptr_iv_step_sign_unknown(ptr %start, i16 %len, i16 %step) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_unknown(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], [[C_2]]
-; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP:%.*]]
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = icmp uge ptr %ptr.iv, %start
-  %c.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.1, %c.2
-  br i1 %and, label %loop.latch, label %exit
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-define void @test_monotonic_ptr_iv_step_sign_positive_through_assume(ptr %start, i16 %len, i16 %step) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
-; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
-; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
+; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
 ; CHECK:       exit:
 ; CHECK-NEXT:    ret void
@@ -1072,69 +831,6 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(ptr %start, i16 %len, i16 %step) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_positive_through_assume_multi_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[STEP_POS:%.*]] = icmp sge i16 [[STEP:%.*]], 0
-; CHECK-NEXT:    call void @llvm.assume(i1 [[STEP_POS]])
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT]]
-; CHECK:       then:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
-; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 [[STEP]]
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %step.pos = icmp sge i16 %step, 0
-  call void @llvm.assume(i1 %step.pos)
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c = icmp eq ptr %ptr.iv, %upper
-  br i1 %c, label %exit, label %for.body
-
-for.body:
-  %c.1 = call i1 @cond()
-  br i1 %c.1, label %then, label %exit
-
-then:
-  %c.2 = icmp uge ptr %ptr.iv, %start
-  %c.3 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.2, %c.3
-  br i1 %and, label %loop.latch, label %exit
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 %step
-  br label %loop.header
-
-exit:
-  ret void
-}
-
 define void @test_monotonic_ptr_iv_step_sign_negative_through_assume(ptr %start, i16 %len, i16 %step) {
 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_sign_negative_through_assume(
 ; CHECK-NEXT:  entry:
@@ -1191,189 +887,6 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_cond_doesnt_control_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
-; CHECK:       then:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    br label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %for.body
-
-for.body:
-  %c.1 = icmp ne ptr %ptr.iv, %upper
-  br i1 %c.1, label %then, label %loop.latch
-
-then:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %t.1, %t.2
-  call void @use.i1(i1 %and)
-  br label %loop.latch
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-define void @test_monotonic_ptr_iv_cond_doesnt_control_exit2(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_control_exit2(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[LOOP_LATCH]]
-; CHECK:       then:
-; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    br label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.1 = icmp ne ptr %ptr.iv, %upper
-  br i1 %c.1, label %then, label %for.body
-
-for.body:
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %loop.latch
-
-then:
-  %t.1 = icmp uge ptr %ptr.iv, %start
-  %t.2 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %t.1, %t.2
-  call void @use.i1(i1 %and)
-  br label %loop.latch
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-define void @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_cond_doesnt_dominate_checks(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
-; CHECK:       then:
-; CHECK-NEXT:    br label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %for.body
-
-for.body:
-  %c.1 = icmp ne ptr %ptr.iv, %upper
-  br i1 %c.1, label %then, label %loop.latch
-
-then:
-  br label %loop.latch
-
-loop.latch:
-  %c.2 = icmp uge ptr %ptr.iv, %start
-  %c.3 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.2, %c.3
-  call void @use.i1(i1 %and)
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  ret void
-}
-
 define void @test_monotonic_ptr_iv_inc_2(ptr %start, i16 %len) {
 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2(
 ; CHECK-NEXT:  entry:
@@ -1426,67 +939,6 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_step_2_multi_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_multi_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_1:%.*]] = icmp eq ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[THEN:%.*]]
-; CHECK:       then:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    br label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.1 = icmp eq ptr %ptr.iv, %upper
-  br i1 %c.1, label %exit, label %for.body
-
-for.body:
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %then
-
-then:
-  %c.2 = icmp uge ptr %ptr.iv, %start
-  %c.3 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.2, %c.3
-  call void @use.i1(i1 %and)
-  br label %loop.latch
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
-  br label %loop.header
-
-exit:
-  ret void
-}
-
 define void @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(ptr %start, i16 %len) {
 ; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_controls_single_exit(
 ; CHECK-NEXT:  entry:
@@ -1541,131 +993,6 @@ exit:
   ret void
 }
 
-define void @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_step_2_cond_doesnt_control_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp slt i16 [[LEN]], 0
-; CHECK-NEXT:    br i1 [[LEN_NEG]], label [[EXIT:%.*]], label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT]], label [[FOR_BODY:%.*]]
-; CHECK:       for.body:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[LOOP_LATCH]]
-; CHECK:       then:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    br label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 2
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp slt i16 %len, 0
-  br i1 %len.neg, label %exit, label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %for.body
-
-for.body:
-  %c.1 = icmp ne ptr %ptr.iv, %upper
-  br i1 %c.1, label %then, label %loop.latch
-
-then:
-  %c.2 = icmp uge ptr %ptr.iv, %start
-  %c.3 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.2, %c.3
-  call void @use.i1(i1 %and)
-  br label %loop.latch
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 2
-  br label %loop.header
-
-exit:
-  ret void
-}
-
-
-define void @test_monotonic_ptr_iv_inc_1_check_outside_loop(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_check_outside_loop(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
-; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sge i16 [[LEN]], 0
-; CHECK-NEXT:    call void @llvm.assume(i1 [[LEN_NEG]])
-; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
-; CHECK:       loop.ph:
-; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
-; CHECK:       loop.header:
-; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
-; CHECK-NEXT:    [[C_0:%.*]] = call i1 @cond()
-; CHECK-NEXT:    br i1 [[C_0]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
-; CHECK:       loop.latch:
-; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
-; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
-; CHECK-NEXT:    br label [[LOOP_HEADER]]
-; CHECK:       exit:
-; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
-; CHECK:       then:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
-; CHECK-NEXT:    call void @use.i1(i1 [[AND]])
-; CHECK-NEXT:    br label [[EXIT_2]]
-; CHECK:       exit.2:
-; CHECK-NEXT:    ret void
-;
-entry:
-  %upper = getelementptr inbounds i32, ptr %start, i16 %len
-  %len.neg = icmp sge i16 %len, 0
-  call void @llvm.assume(i1 %len.neg)
-  br label %loop.ph
-
-loop.ph:
-  br label %loop.header
-
-loop.header:
-  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
-  %c.0 = call i1 @cond()
-  br i1 %c.0, label %exit, label %loop.latch
-
-loop.latch:
-  call void @use(ptr %ptr.iv)
-  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
-  br label %loop.header
-
-exit:
-  %c.1 = icmp ne ptr %ptr.iv, %upper
-  br i1 %c.1, label %then, label %exit.2
-
-then:
-  %c.2 = icmp uge ptr %ptr.iv, %start
-  %c.3 = icmp ult ptr %ptr.iv, %upper
-  %and = and i1 %c.2, %c.3
-  call void @use.i1(i1 %and)
-  br label %exit.2
-
-exit.2:
-  ret void
-}
-
 define void @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(ptr %start, i16 %len) {
 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_loop_exits_on_ne(
 ; CHECK-NEXT:  entry: