xref: /llvm-project/llvm/test/Transforms/IndVarSimplify/iv-poison.ll (revision da437330beca0411912ca46f2d5ef1e46403acbd)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=indvars -S < %s | FileCheck %s
3
4; PR59777
5define i2 @iv_hoist_nsw_poison(i2 %arg) {
6; CHECK-LABEL: @iv_hoist_nsw_poison(
7; CHECK-NEXT:  bb:
8; CHECK-NEXT:    br label [[BB1:%.*]]
9; CHECK:       bb1:
10; CHECK-NEXT:    [[DOT07:%.*]] = phi i2 [ 1, [[BB:%.*]] ], [ [[I:%.*]], [[BB1]] ]
11; CHECK-NEXT:    [[I]] = add nuw i2 [[DOT07]], 1
12; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i2 1, [[ARG:%.*]]
13; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[COMMON_RET:%.*]], label [[BB1]]
14; CHECK:       common.ret:
15; CHECK-NEXT:    [[I2_LCSSA:%.*]] = phi i2 [ [[I]], [[BB1]] ]
16; CHECK-NEXT:    ret i2 [[I2_LCSSA]]
17;
18bb:
19  br label %bb1
20
21bb1:                                              ; preds = %bb1, %bb
22  %.07 = phi i2 [ 1, %bb ], [ %i, %bb1 ]
23  %.0 = phi i2 [ 1, %bb ], [ %i2, %bb1 ]
24  %i = add nsw i2 %.07, 1
25  %i2 = add i2 %.0, 1
26  %.not.not = icmp ult i2 %.07, %arg
27  br i1 %.not.not, label %common.ret, label %bb1
28
29common.ret:                                       ; preds = %bb1
30  ret i2 %i2
31}
32
33define i4 @iv_hoist_nsw_poison2(i4 %0, i4 %end, i4 %start) {
34; CHECK-LABEL: @iv_hoist_nsw_poison2(
35; CHECK-NEXT:  entry:
36; CHECK-NEXT:    br label [[LOOP:%.*]]
37; CHECK:       loop:
38; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
39; CHECK-NEXT:    [[IV_0_NEXT]] = add i4 [[IV_0]], 1
40; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[IV_0]], [[END:%.*]]
41; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
42; CHECK:       exit:
43; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
44; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
45;
46entry:
47  br label %loop
48
49loop:
50  %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ]
51  %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ]
52  %iv.0.next = add i4 %iv.0, 1
53  %iv.1.next = add nsw i4 %iv.1, 1
54  %.not.not = icmp ult i4 %iv.0, %end
55  br i1 %.not.not, label %exit, label %loop
56
57exit:
58  ret i4 %iv.1.next
59}
60
61define i2 @iv_hoist_both_adds_nsw(i2 %arg) {
62; CHECK-LABEL: @iv_hoist_both_adds_nsw(
63; CHECK-NEXT:  bb:
64; CHECK-NEXT:    br label [[LOOP:%.*]]
65; CHECK:       loop:
66; CHECK-NEXT:    [[IV_0:%.*]] = phi i2 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
67; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw nsw i2 [[IV_0]], 1
68; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i2 1, [[ARG:%.*]]
69; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
70; CHECK:       exit:
71; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i2 [ [[IV_0_NEXT]], [[LOOP]] ]
72; CHECK-NEXT:    ret i2 [[IV_1_NEXT_LCSSA]]
73;
74bb:
75  br label %loop
76
77loop:
78  %iv.0 = phi i2 [ 1, %bb ], [ %iv.0.next, %loop ]
79  %iv.1 = phi i2 [ 1, %bb ], [ %iv.1.next, %loop ]
80  %iv.0.next = add nsw i2 %iv.0, 1
81  %iv.1.next = add nsw i2 %iv.1, 1
82  %.not.not = icmp ult i2 %iv.0, %arg
83  br i1 %.not.not, label %exit, label %loop
84
85exit:
86  ret i2 %iv.1.next
87}
88
89define i4 @iv_hoist_both_adds_nsw_extra_use(i4 %arg) {
90; CHECK-LABEL: @iv_hoist_both_adds_nsw_extra_use(
91; CHECK-NEXT:  bb:
92; CHECK-NEXT:    br label [[LOOP:%.*]]
93; CHECK:       loop:
94; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
95; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1
96; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
97; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
98; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]]
99; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
100; CHECK:       exit:
101; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
102; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
103;
104bb:
105  br label %loop
106
107loop:
108  %iv.0 = phi i4 [ 1, %bb ], [ %iv.0.next, %loop ]
109  %iv.1 = phi i4 [ 1, %bb ], [ %iv.1.next, %loop ]
110  %iv.0.next = add nsw i4 %iv.0, 1
111  call void @use(i4 %iv.0.next)
112  %iv.1.next = add nsw i4 %iv.1, 1
113  call void @use(i4 %iv.1.next)
114  %.not.not = icmp ult i4 %iv.0, %arg
115  br i1 %.not.not, label %exit, label %loop
116
117exit:
118  ret i4 %iv.1.next
119}
120
121define i4 @iv_hoist_both_adds_nsw_extra_use_incs_reordered(i4 %arg) {
122; CHECK-LABEL: @iv_hoist_both_adds_nsw_extra_use_incs_reordered(
123; CHECK-NEXT:  bb:
124; CHECK-NEXT:    br label [[LOOP:%.*]]
125; CHECK:       loop:
126; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
127; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1
128; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
129; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
130; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]]
131; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
132; CHECK:       exit:
133; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
134; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
135;
136bb:
137  br label %loop
138
139loop:
140  %iv.0 = phi i4 [ 1, %bb ], [ %iv.0.next, %loop ]
141  %iv.1 = phi i4 [ 1, %bb ], [ %iv.1.next, %loop ]
142  %iv.1.next = add nsw i4 %iv.1, 1
143  call void @use(i4 %iv.1.next)
144  %iv.0.next = add nsw i4 %iv.0, 1
145  call void @use(i4 %iv.0.next)
146  %.not.not = icmp ult i4 %iv.0, %arg
147  br i1 %.not.not, label %exit, label %loop
148
149exit:
150  ret i4 %iv.1.next
151}
152
153define i4 @iv_hoist_nsw_poison_extra_use(i4 %0, i4 %end, i4 %start) {
154; CHECK-LABEL: @iv_hoist_nsw_poison_extra_use(
155; CHECK-NEXT:  entry:
156; CHECK-NEXT:    br label [[LOOP:%.*]]
157; CHECK:       loop:
158; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
159; CHECK-NEXT:    [[IV_0_NEXT]] = add i4 [[IV_0]], 1
160; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
161; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[IV_0]], [[END:%.*]]
162; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
163; CHECK:       exit:
164; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
165; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
166;
167entry:
168  br label %loop
169
170loop:
171  %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ]
172  %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ]
173  %iv.0.next = add i4 %iv.0, 1
174  call void @use(i4 %iv.0.next)
175  %iv.1.next = add nsw i4 %iv.1, 1
176  %.not.not = icmp ult i4 %iv.0, %end
177  br i1 %.not.not, label %exit, label %loop
178
179exit:
180  ret i4 %iv.1.next
181}
182
183declare void @use(i4)
184
185define i2 @iv_hoist_nuw_poison(i2 %arg, i2 %start) {
186; CHECK-LABEL: @iv_hoist_nuw_poison(
187; CHECK-NEXT:  bb:
188; CHECK-NEXT:    br label [[BB1:%.*]]
189; CHECK:       bb1:
190; CHECK-NEXT:    [[DOT07:%.*]] = phi i2 [ [[START:%.*]], [[BB:%.*]] ], [ [[I:%.*]], [[BB1]] ]
191; CHECK-NEXT:    [[I]] = add i2 [[DOT07]], 1
192; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i2 [[START]], [[ARG:%.*]]
193; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[COMMON_RET:%.*]], label [[BB1]]
194; CHECK:       common.ret:
195; CHECK-NEXT:    [[I2_LCSSA:%.*]] = phi i2 [ [[I]], [[BB1]] ]
196; CHECK-NEXT:    ret i2 [[I2_LCSSA]]
197;
198bb:
199  br label %bb1
200
201bb1:                                              ; preds = %bb1, %bb
202  %.07 = phi i2 [ %start, %bb ], [ %i, %bb1 ]
203  %.0 = phi i2 [ %start, %bb ], [ %i2, %bb1 ]
204  %i = add nuw i2 %.07, 1
205  %i2 = add i2 %.0, 1
206  %.not.not = icmp ult i2 %.07, %arg
207  br i1 %.not.not, label %common.ret, label %bb1
208
209common.ret:                                       ; preds = %bb1
210  ret i2 %i2
211}
212
213define i4 @iv_hoist_nuw_poison2(i4 %0, i4 %end, i4 %start) {
214; CHECK-LABEL: @iv_hoist_nuw_poison2(
215; CHECK-NEXT:  entry:
216; CHECK-NEXT:    br label [[LOOP:%.*]]
217; CHECK:       loop:
218; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
219; CHECK-NEXT:    [[IV_0_NEXT]] = add i4 [[IV_0]], 1
220; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[END:%.*]]
221; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
222; CHECK:       exit:
223; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
224; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
225;
226entry:
227  br label %loop
228
229loop:
230  %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ]
231  %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ]
232  %iv.0.next = add i4 %iv.0, 1
233  %iv.1.next = add nuw i4 %iv.1, 1
234  %.not.not = icmp ult i4 %iv.0, %end
235  br i1 %.not.not, label %exit, label %loop
236
237exit:
238  ret i4 %iv.1.next
239}
240
241define i2 @iv_hoist_both_adds_nuw(i2 %arg, i2 %start) {
242; CHECK-LABEL: @iv_hoist_both_adds_nuw(
243; CHECK-NEXT:  bb:
244; CHECK-NEXT:    br label [[LOOP:%.*]]
245; CHECK:       loop:
246; CHECK-NEXT:    [[IV_0:%.*]] = phi i2 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
247; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw i2 [[IV_0]], 1
248; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i2 [[START]], [[ARG:%.*]]
249; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
250; CHECK:       exit:
251; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i2 [ [[IV_0_NEXT]], [[LOOP]] ]
252; CHECK-NEXT:    ret i2 [[IV_1_NEXT_LCSSA]]
253;
254bb:
255  br label %loop
256
257loop:
258  %iv.0 = phi i2 [ %start, %bb ], [ %iv.0.next, %loop ]
259  %iv.1 = phi i2 [ %start, %bb ], [ %iv.1.next, %loop ]
260  %iv.0.next = add nuw i2 %iv.0, 1
261  %iv.1.next = add nuw i2 %iv.1, 1
262  %.not.not = icmp ult i2 %iv.0, %arg
263  br i1 %.not.not, label %exit, label %loop
264
265exit:
266  ret i2 %iv.1.next
267}
268
269define i4 @iv_hoist_both_adds_nuw_extra_use(i4 %arg, i4 %start) {
270; CHECK-LABEL: @iv_hoist_both_adds_nuw_extra_use(
271; CHECK-NEXT:  bb:
272; CHECK-NEXT:    br label [[LOOP:%.*]]
273; CHECK:       loop:
274; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
275; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
276; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
277; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
278; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]]
279; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
280; CHECK:       exit:
281; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
282; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
283;
284bb:
285  br label %loop
286
287loop:
288  %iv.0 = phi i4 [ %start, %bb ], [ %iv.0.next, %loop ]
289  %iv.1 = phi i4 [ %start, %bb ], [ %iv.1.next, %loop ]
290  %iv.0.next = add nuw i4 %iv.0, 1
291  call void @use(i4 %iv.0.next)
292  %iv.1.next = add nuw i4 %iv.1, 1
293  call void @use(i4 %iv.1.next)
294  %.not.not = icmp ult i4 %iv.0, %arg
295  br i1 %.not.not, label %exit, label %loop
296
297exit:
298  ret i4 %iv.1.next
299}
300
301define i4 @iv_hoist_both_adds_nuw_extra_use_incs_reordered(i4 %arg, i4 %start) {
302; CHECK-LABEL: @iv_hoist_both_adds_nuw_extra_use_incs_reordered(
303; CHECK-NEXT:  bb:
304; CHECK-NEXT:    br label [[LOOP:%.*]]
305; CHECK:       loop:
306; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
307; CHECK-NEXT:    [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1
308; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
309; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
310; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]]
311; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
312; CHECK:       exit:
313; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
314; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
315;
316bb:
317  br label %loop
318
319loop:
320  %iv.0 = phi i4 [ %start, %bb ], [ %iv.0.next, %loop ]
321  %iv.1 = phi i4 [ %start, %bb ], [ %iv.1.next, %loop ]
322  %iv.1.next = add nuw i4 %iv.1, 1
323  call void @use(i4 %iv.1.next)
324  %iv.0.next = add nuw i4 %iv.0, 1
325  call void @use(i4 %iv.0.next)
326  %.not.not = icmp ult i4 %iv.0, %arg
327  br i1 %.not.not, label %exit, label %loop
328
329exit:
330  ret i4 %iv.1.next
331}
332
333define i4 @iv_hoist_nuw_poison_extra_use(i4 %0, i4 %end, i4 %start) {
334; CHECK-LABEL: @iv_hoist_nuw_poison_extra_use(
335; CHECK-NEXT:  entry:
336; CHECK-NEXT:    br label [[LOOP:%.*]]
337; CHECK:       loop:
338; CHECK-NEXT:    [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ]
339; CHECK-NEXT:    [[IV_0_NEXT]] = add i4 [[IV_0]], 1
340; CHECK-NEXT:    call void @use(i4 [[IV_0_NEXT]])
341; CHECK-NEXT:    [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[END:%.*]]
342; CHECK-NEXT:    br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]]
343; CHECK:       exit:
344; CHECK-NEXT:    [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ]
345; CHECK-NEXT:    ret i4 [[IV_1_NEXT_LCSSA]]
346;
347entry:
348  br label %loop
349
350loop:
351  %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ]
352  %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ]
353  %iv.0.next = add i4 %iv.0, 1
354  call void @use(i4 %iv.0.next)
355  %iv.1.next = add nuw i4 %iv.1, 1
356  %.not.not = icmp ult i4 %iv.0, %end
357  br i1 %.not.not, label %exit, label %loop
358
359exit:
360  ret i4 %iv.1.next
361}
362