[llvm] cbacab2 - [ConstraintElim] Add extra tests and split up test file.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 30 07:16:45 PDT 2023
Author: Florian Hahn
Date: 2023-06-30T15:16:23+01:00
New Revision: cbacab26e71707408bd74dbff339ec93fb19a6d5
URL: https://github.com/llvm/llvm-project/commit/cbacab26e71707408bd74dbff339ec93fb19a6d5
DIFF: https://github.com/llvm/llvm-project/commit/cbacab26e71707408bd74dbff339ec93fb19a6d5.diff
LOG: [ConstraintElim] Add extra tests and split up test file.
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.
Added:
llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll
Modified:
llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll
Removed:
################################################################################
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
index 0000000000000..df4ed118abe96
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis-early-exits.ll
@@ -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_
diff erent_element_types_1_with_early_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_
diff erent_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_
diff erent_element_types_1_with_early_exit(ptr %start, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_
diff erent_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_
diff erent_element_types_1_with_early_exit_and_
diff erent_upper(ptr %start, ptr %end, i16 %len) {
+; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_
diff erent_element_types_1_with_early_exit_and_
diff erent_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
+}
diff --git a/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll b/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll
index aedfad6a2703d..e6603ec30946c 100644
--- a/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll
+++ b/llvm/test/Transforms/ConstraintElimination/monotonic-pointer-phis.ll
@@ -264,124 +264,6 @@ exit:
ret void
}
-define void @test_monotonic_ptr_iv_inc_1_
diff erent_element_types_1_with_early_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_
diff erent_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_
diff erent_element_types_1_with_early_exit(ptr %start, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_2_
diff erent_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_
diff erent_element_types_1_with_early_exit_and_
diff erent_upper(ptr %start, ptr %end, i16 %len) {
-; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_
diff erent_element_types_1_with_early_exit_and_
diff erent_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_
diff erent_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_
diff erent_start(ptr %start, ptr %p, i16 %len) {
+; CHECK-LABEL: @test_no_ptr_iv_
diff erent_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_
diff erent_start(ptr %start, ptr %p, i16 %len) {
-; CHECK-LABEL: @test_no_ptr_iv_
diff erent_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_
diff erent_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_
diff erent_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:
More information about the llvm-commits
mailing list