1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -indvars -S < %s | FileCheck %s
3 ; RUN: opt -passes=indvars -S < %s | FileCheck %s
5 ; Monotonic decrementing iv. we should be able to prove that %iv.next <s len
6 ; basing on its nsw and the fact that its starting value <s len.
7 define i32 @test_01(i32* %p) {
8 ; CHECK-LABEL: @test_01(
10 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0:!range !.*]]
11 ; CHECK-NEXT: br label [[LOOP:%.*]]
13 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
14 ; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], -1
15 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
17 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 0
18 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
20 ; CHECK-NEXT: ret i32 -1
22 ; CHECK-NEXT: ret i32 0
25 %len = load i32, i32* %p, !range !0
29 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
30 %iv.next = add i32 %iv, -1
31 %rc = icmp slt i32 %iv.next, %len
32 br i1 %rc, label %backedge, label %fail
35 %loop.cond = icmp ne i32 %iv, 0
36 br i1 %loop.cond, label %loop, label %exit
45 ; We should not remove this range check because signed overflow is possible here (start at len = 0).
46 define i32 @test_01_neg(i32* %p) {
47 ; CHECK-LABEL: @test_01_neg(
49 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0]]
50 ; CHECK-NEXT: br label [[LOOP:%.*]]
52 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
53 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], -1
54 ; CHECK-NEXT: [[RC:%.*]] = icmp slt i32 [[IV_NEXT]], [[LEN]]
55 ; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[FAIL:%.*]]
57 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 1
58 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
60 ; CHECK-NEXT: ret i32 -1
62 ; CHECK-NEXT: ret i32 0
65 %len = load i32, i32* %p, !range !0
69 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
70 %iv.next = add i32 %iv, -1
71 %rc = icmp slt i32 %iv.next, %len
72 br i1 %rc, label %backedge, label %fail
75 %loop.cond = icmp ne i32 %iv, 1
76 br i1 %loop.cond, label %loop, label %exit
85 ; Monotonic incrementing iv. we should be able to prove that %iv.next >s len
86 ; basing on its nsw and the fact that its starting value >s len.
87 define i32 @test_02(i32* %p) {
88 ; CHECK-LABEL: @test_02(
90 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG1:!range !.*]]
91 ; CHECK-NEXT: br label [[LOOP:%.*]]
93 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
94 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
95 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
97 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 0
98 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
100 ; CHECK-NEXT: ret i32 -1
102 ; CHECK-NEXT: ret i32 0
105 %len = load i32, i32* %p, !range !1
109 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
110 %iv.next = add i32 %iv, 1
111 %rc = icmp sgt i32 %iv.next, %len
112 br i1 %rc, label %backedge, label %fail
115 %loop.cond = icmp ne i32 %iv, 0
116 br i1 %loop.cond, label %loop, label %exit
125 ; We should not remove this range check because signed overflow is possible here (start at len = -1).
126 define i32 @test_02_neg(i32* %p) {
127 ; CHECK-LABEL: @test_02_neg(
129 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG1]]
130 ; CHECK-NEXT: br label [[LOOP:%.*]]
132 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
133 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
134 ; CHECK-NEXT: [[RC:%.*]] = icmp sgt i32 [[IV_NEXT]], [[LEN]]
135 ; CHECK-NEXT: br i1 [[RC]], label [[BACKEDGE]], label [[FAIL:%.*]]
137 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], -2
138 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
140 ; CHECK-NEXT: ret i32 -1
142 ; CHECK-NEXT: ret i32 0
145 %len = load i32, i32* %p, !range !1
149 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
150 %iv.next = add i32 %iv, 1
151 %rc = icmp sgt i32 %iv.next, %len
152 br i1 %rc, label %backedge, label %fail
155 %loop.cond = icmp ne i32 %iv, -2
156 br i1 %loop.cond, label %loop, label %exit
165 define i32 @test_03(i32* %p) {
166 ; CHECK-LABEL: @test_03(
168 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG2:!range !.*]]
169 ; CHECK-NEXT: br label [[LOOP:%.*]]
171 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
172 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
173 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
175 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 1000
176 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
178 ; CHECK-NEXT: ret i32 -1
180 ; CHECK-NEXT: ret i32 0
183 %len = load i32, i32* %p, !range !2
187 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
188 %iv.next = add i32 %iv, 1
189 %rc = icmp sgt i32 %iv.next, %len
190 br i1 %rc, label %backedge, label %fail
193 %loop.cond = icmp ne i32 %iv, 1000
194 br i1 %loop.cond, label %loop, label %exit
203 define i32 @test_04(i32* %p) {
204 ; CHECK-LABEL: @test_04(
206 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG2]]
207 ; CHECK-NEXT: br label [[LOOP:%.*]]
209 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LEN]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
210 ; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], -1
211 ; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAIL:%.*]]
213 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[IV]], 0
214 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
216 ; CHECK-NEXT: ret i32 -1
218 ; CHECK-NEXT: ret i32 0
221 %len = load i32, i32* %p, !range !2
225 %iv = phi i32 [%len, %entry], [%iv.next, %backedge]
226 %iv.next = add i32 %iv, -1
227 %rc = icmp slt i32 %iv.next, %len
228 br i1 %rc, label %backedge, label %fail
231 %loop.cond = icmp ne i32 %iv, 0
232 br i1 %loop.cond, label %loop, label %exit
241 !0 = !{i32 0, i32 2147483647}
242 !1 = !{i32 -2147483648, i32 0}
243 !2 = !{i32 0, i32 1000}