[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / IndVarSimplify / lftr-pr31181.ll
blob6032b1d13cef023297b1936e2d0914dfdeb7cbf2
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -indvars -S | FileCheck %s
4 ; PR31181: It may be necessary to drop nuw/nsw flags when moving from a
5 ; pre-increment comparison to a post-increment comparison.
7 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
9 @a = global i32 0
11 define i32 @test_drop_nuw() {
12 ; CHECK-LABEL: @test_drop_nuw(
13 ; CHECK-NEXT:  entry:
14 ; CHECK-NEXT:    br label [[LOOP:%.*]]
15 ; CHECK:       loop:
16 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
17 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
18 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[STOREMERGE]], 1
19 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 0
20 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
21 ; CHECK:       exit:
22 ; CHECK-NEXT:    ret i32 0
24 entry:
25   br label %loop
27 loop:
28   %storemerge = phi i32 [ -2, %entry ], [ %inc, %loop ]
29   store i32 %storemerge, i32* @a
30   %cmp = icmp slt i32 %storemerge, -1
31   %inc = add nuw nsw i32 %storemerge, 1
32   br i1 %cmp, label %loop, label %exit
34 exit:
35   ret i32 0
38 define i32 @test_drop_nsw() {
39 ; CHECK-LABEL: @test_drop_nsw(
40 ; CHECK-NEXT:  entry:
41 ; CHECK-NEXT:    br label [[LOOP:%.*]]
42 ; CHECK:       loop:
43 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
44 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
45 ; CHECK-NEXT:    [[INC]] = add nuw i32 [[STOREMERGE]], 1
46 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], -2147483648
47 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
48 ; CHECK:       exit:
49 ; CHECK-NEXT:    ret i32 0
51 entry:
52   br label %loop
54 loop:
55   %storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
56   store i32 %storemerge, i32* @a
57   %cmp = icmp ult i32 %storemerge, 2147483647
58   %inc = add nuw nsw i32 %storemerge, 1
59   br i1 %cmp, label %loop, label %exit
61 exit:
62   ret i32 0
65 define i32 @test_no_drop_nuw() {
66 ; CHECK-LABEL: @test_no_drop_nuw(
67 ; CHECK-NEXT:  entry:
68 ; CHECK-NEXT:    br label [[LOOP:%.*]]
69 ; CHECK:       loop:
70 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -3, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
71 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
72 ; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
73 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], -1
74 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
75 ; CHECK:       exit:
76 ; CHECK-NEXT:    ret i32 0
78 entry:
79   br label %loop
81 loop:
82   %storemerge = phi i32 [ -3, %entry ], [ %inc, %loop ]
83   store i32 %storemerge, i32* @a
84   %cmp = icmp slt i32 %storemerge, -2
85   %inc = add nuw nsw i32 %storemerge, 1
86   br i1 %cmp, label %loop, label %exit
88 exit:
89   ret i32 0
93 define i32 @test_no_drop_nsw() {
94 ; CHECK-LABEL: @test_no_drop_nsw(
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    br label [[LOOP:%.*]]
97 ; CHECK:       loop:
98 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
99 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
100 ; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
101 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 2147483647
102 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
103 ; CHECK:       exit:
104 ; CHECK-NEXT:    ret i32 0
106 entry:
107   br label %loop
109 loop:
110   %storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
111   store i32 %storemerge, i32* @a
112   %cmp = icmp ult i32 %storemerge, 2147483646
113   %inc = add nuw nsw i32 %storemerge, 1
114   br i1 %cmp, label %loop, label %exit
116 exit:
117   ret i32 0
120 define i32 @test_no_add_nuw() {
121 ; CHECK-LABEL: @test_no_add_nuw(
122 ; CHECK-NEXT:  entry:
123 ; CHECK-NEXT:    br label [[LOOP:%.*]]
124 ; CHECK:       loop:
125 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
126 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
127 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[STOREMERGE]], 1
128 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 10
129 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
130 ; CHECK:       exit:
131 ; CHECK-NEXT:    ret i32 0
133 entry:
134   br label %loop
136 loop:
137   %storemerge = phi i32 [ -1, %entry ], [ %inc, %loop ]
138   store i32 %storemerge, i32* @a
139   %cmp = icmp slt i32 %storemerge, 9
140   %inc = add i32 %storemerge, 1
141   br i1 %cmp, label %loop, label %exit
143 exit:
144   ret i32 0
147 define i32 @test_drop_nsw_var_lim(i32 %lim) {
148 ; CHECK-LABEL: @test_drop_nsw_var_lim(
149 ; CHECK-NEXT:  entry:
150 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[LIM:%.*]], -1
151 ; CHECK-NEXT:    br i1 [[C]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
152 ; CHECK:       loop.preheader:
153 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LIM]], 1
154 ; CHECK-NEXT:    br label [[LOOP:%.*]]
155 ; CHECK:       loop:
156 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ [[INC:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
157 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
158 ; CHECK-NEXT:    [[INC]] = add nuw i32 [[STOREMERGE]], 1
159 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], [[TMP0]]
160 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
161 ; CHECK:       exit.loopexit:
162 ; CHECK-NEXT:    br label [[EXIT]]
163 ; CHECK:       exit:
164 ; CHECK-NEXT:    ret i32 0
166 entry:
167   %c = icmp ult i32 %lim, -1
168   br i1 %c, label %loop, label %exit
170 loop:
171   %storemerge = phi i32 [ 0, %entry ], [ %inc, %loop ]
172   store i32 %storemerge, i32* @a
173   %cmp = icmp ult i32 %storemerge, %lim
174   %inc = add nuw nsw i32 %storemerge, 1
175   br i1 %cmp, label %loop, label %exit
177 exit:
178   ret i32 0
181 ; Adopted from D30446.
182 ; We switch from %iv to %iv2 and need to change nsw to nuw in the process.
183 define i32 @switch_to_different_iv_post_inc(i32* %ptr, i1 %always_false) {
184 ; CHECK-LABEL: @switch_to_different_iv_post_inc(
185 ; CHECK-NEXT:  entry:
186 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
187 ; CHECK:       for.cond:
188 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
189 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN]] ]
190 ; CHECK-NEXT:    store i32 [[IV]], i32* [[PTR:%.*]]
191 ; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
192 ; CHECK:       never_taken:
193 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* [[PTR]]
194 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
195 ; CHECK:       always_taken:
196 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
197 ; CHECK-NEXT:    [[IV2_INC]] = add nuw i32 [[IV2]], 1
198 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483627
199 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
200 ; CHECK:       for.end:
201 ; CHECK-NEXT:    ret i32 0
203 entry:
204   br label %for.cond
206 for.cond:
207   %iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
208   %iv2 = phi i32 [ 0, %entry ], [ %iv2.inc, %always_taken ]
209   store i32 %iv, i32* %ptr
210   br i1 %always_false, label %never_taken, label %always_taken
212 never_taken:
213   store volatile i32 %iv2, i32* %ptr
214   br label %always_taken
216 always_taken:
217   %iv.inc = add nsw i32 %iv, 1
218   %iv2.inc = add nuw nsw i32 %iv2, 1
219   %cmp = icmp slt i32 %iv, 20
220   br i1 %cmp, label %for.cond, label %for.end
222 for.end:
223   ret i32 0
226 ; Same as previous test case, but with exit block and loop latch being distinct
227 ; blocks requiring the use of pre-increment.
228 define i32 @switch_to_different_iv_pre_inc(i32* %ptr, i1 %always_false) {
229 ; CHECK-LABEL: @switch_to_different_iv_pre_inc(
230 ; CHECK-NEXT:  entry:
231 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
232 ; CHECK:       for.cond:
233 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
234 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN]] ]
235 ; CHECK-NEXT:    store i32 [[IV]], i32* [[PTR:%.*]]
236 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2]], -2147483628
237 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
238 ; CHECK:       for.body:
239 ; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
240 ; CHECK:       never_taken:
241 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* [[PTR]]
242 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
243 ; CHECK:       always_taken:
244 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
245 ; CHECK-NEXT:    [[IV2_INC]] = add nuw i32 [[IV2]], 1
246 ; CHECK-NEXT:    br label [[FOR_COND]]
247 ; CHECK:       for.end:
248 ; CHECK-NEXT:    ret i32 0
250 entry:
251   br label %for.cond
253 for.cond:
254   %iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
255   %iv2 = phi i32 [ 0, %entry ], [ %iv2.inc, %always_taken ]
256   store i32 %iv, i32* %ptr
257   %cmp = icmp slt i32 %iv, 20
258   br i1 %cmp, label %for.body, label %for.end
260 for.body:
261   br i1 %always_false, label %never_taken, label %always_taken
263 never_taken:
264   store volatile i32 %iv2, i32* %ptr
265   br label %always_taken
267 always_taken:
268   %iv.inc = add nsw i32 %iv, 1
269   %iv2.inc = add nuw nsw i32 %iv2, 1
270   br label %for.cond
272 for.end:
273   ret i32 0
276 define i32 @switch_to_different_iv_first_poison(i32* %ptr, i1 %always_false) {
277 ; CHECK-LABEL: @switch_to_different_iv_first_poison(
278 ; CHECK-NEXT:  entry:
279 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
280 ; CHECK:       for.cond:
281 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
282 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN]] ]
283 ; CHECK-NEXT:    store i32 [[IV]], i32* [[PTR:%.*]]
284 ; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
285 ; CHECK:       never_taken:
286 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* [[PTR]]
287 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
288 ; CHECK:       always_taken:
289 ; CHECK-NEXT:    [[IV2_INC]] = add nuw nsw i32 [[IV2]], 1
290 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
291 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483628
292 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
293 ; CHECK:       for.end:
294 ; CHECK-NEXT:    ret i32 0
296 entry:
297   br label %for.cond
299 for.cond:
300   %iv2 = phi i32 [ -1, %entry ], [ %iv2.inc, %always_taken ]
301   %iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
302   store i32 %iv, i32* %ptr
303   br i1 %always_false, label %never_taken, label %always_taken
305 never_taken:
306   store volatile i32 %iv2, i32* %ptr
307   br label %always_taken
309 always_taken:
310   %iv2.inc = add nuw nsw i32 %iv2, 1
311   %iv.inc = add nsw i32 %iv, 1
312   %cmp = icmp slt i32 %iv, 20
313   br i1 %cmp, label %for.cond, label %for.end
315 for.end:
316   ret i32 0
319 define i32 @switch_to_different_iv_second_poison(i32* %ptr, i1 %always_false) {
320 ; CHECK-LABEL: @switch_to_different_iv_second_poison(
321 ; CHECK-NEXT:  entry:
322 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
323 ; CHECK:       for.cond:
324 ; CHECK-NEXT:    [[IV2:%.*]] = phi i32 [ -2, [[ENTRY:%.*]] ], [ [[IV2_INC:%.*]], [[ALWAYS_TAKEN:%.*]] ]
325 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ -2147483648, [[ENTRY]] ], [ [[IV_INC:%.*]], [[ALWAYS_TAKEN]] ]
326 ; CHECK-NEXT:    store i32 [[IV]], i32* [[PTR:%.*]]
327 ; CHECK-NEXT:    br i1 [[ALWAYS_FALSE:%.*]], label [[NEVER_TAKEN:%.*]], label [[ALWAYS_TAKEN]]
328 ; CHECK:       never_taken:
329 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* [[PTR]]
330 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
331 ; CHECK:       always_taken:
332 ; CHECK-NEXT:    [[IV2_INC]] = add nsw i32 [[IV2]], 1
333 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
334 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483629
335 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
336 ; CHECK:       for.end:
337 ; CHECK-NEXT:    ret i32 0
339 entry:
340   br label %for.cond
342 for.cond:
343   %iv2 = phi i32 [ -2, %entry ], [ %iv2.inc, %always_taken ]
344   %iv = phi i32 [ -2147483648, %entry ], [ %iv.inc, %always_taken ]
345   store i32 %iv, i32* %ptr
346   br i1 %always_false, label %never_taken, label %always_taken
348 never_taken:
349   store volatile i32 %iv2, i32* %ptr
350   br label %always_taken
352 always_taken:
353   %iv2.inc = add nuw nsw i32 %iv2, 1
354   %iv.inc = add nsw i32 %iv, 1
355   %cmp = icmp slt i32 %iv, 20
356   br i1 %cmp, label %for.cond, label %for.end
358 for.end:
359   ret i32 0