[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / CanonicalizeFreezeInLoops / onephi.ll
blobca7ed4d71133ce1d4026e1782bddb90e99508a61
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -canon-freeze -S | FileCheck %s
3 ; A set of tests that have one phi node
4 declare void @call(i32)
5 declare i32 @get_step()
7 define void @add(i32 %init, i32 %n) {
8 ; CHECK-LABEL: @add(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
11 ; CHECK-NEXT:    br label [[LOOP:%.*]]
12 ; CHECK:       loop:
13 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
14 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
15 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
16 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
17 ; CHECK:       exit:
18 ; CHECK-NEXT:    ret void
20 entry:
21   br label %loop
23 loop:
24   %i = phi i32 [ %init, %entry], [%i.next, %loop ]
25   %i.next = add i32 %i, 1
26   %i.next.fr = freeze i32 %i.next
27   %cond = icmp eq i32 %i.next.fr, %n
28   br i1 %cond, label %loop, label %exit
30 exit:
31   ret void
34 define void @add_comm(i32 %init, i32 %n) {
35 ; CHECK-LABEL: @add_comm(
36 ; CHECK-NEXT:  entry:
37 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
38 ; CHECK-NEXT:    br label [[LOOP:%.*]]
39 ; CHECK:       loop:
40 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
41 ; CHECK-NEXT:    [[I_NEXT]] = add i32 1, [[I]]
42 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
43 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
44 ; CHECK:       exit:
45 ; CHECK-NEXT:    ret void
47 entry:
48   br label %loop
50 loop:
51   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
52   %i.next = add i32 1, %i
53   %i.next.fr = freeze i32 %i.next
54   %cond = icmp eq i32 %i.next.fr, %n
55   br i1 %cond, label %loop, label %exit
57 exit:
58   ret void
61 define void @add_multiuses(i32 %init, i32 %n) {
62 ; CHECK-LABEL: @add_multiuses(
63 ; CHECK-NEXT:  entry:
64 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
65 ; CHECK-NEXT:    br label [[LOOP:%.*]]
66 ; CHECK:       loop:
67 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
68 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
69 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
70 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
71 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
72 ; CHECK:       exit:
73 ; CHECK-NEXT:    ret void
75 entry:
76   br label %loop
78 loop:
79   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
80   %i.next = add i32 %i, 1
81   %i.next.fr = freeze i32 %i.next
82   call void @call(i32 %i.next.fr)
83   %cond = icmp eq i32 %i.next.fr, %n
84   br i1 %cond, label %loop, label %exit
86 exit:
87   ret void
90 define void @add_multiuses2(i32 %init, i32 %n) {
91 ; CHECK-LABEL: @add_multiuses2(
92 ; CHECK-NEXT:  entry:
93 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
94 ; CHECK-NEXT:    br label [[LOOP:%.*]]
95 ; CHECK:       loop:
96 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
97 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
98 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
99 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
100 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
101 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
102 ; CHECK:       exit:
103 ; CHECK-NEXT:    ret void
105 entry:
106   br label %loop
108 loop:
109   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
110   %i.next = add i32 %i, 1
111   %i.next.fr = freeze i32 %i.next
112   call void @call(i32 %i.next.fr)
113   %i.next.fr2 = freeze i32 %i.next
114   call void @call(i32 %i.next.fr2)
115   %cond = icmp eq i32 %i.next.fr, %n
116   br i1 %cond, label %loop, label %exit
118 exit:
119   ret void
122 define void @add_flags(i32 %init, i32 %n) {
123 ; CHECK-LABEL: @add_flags(
124 ; CHECK-NEXT:  entry:
125 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
126 ; CHECK-NEXT:    br label [[LOOP:%.*]]
127 ; CHECK:       loop:
128 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
129 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
130 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
131 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
132 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
133 ; CHECK:       exit:
134 ; CHECK-NEXT:    ret void
136 entry:
137   br label %loop
139 loop:
140   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
141   %i.next = add nuw nsw i32 %i, 1
142   %i.next.fr = freeze i32 %i.next
143   call void @call(i32 %i.next.fr)
144   %cond = icmp eq i32 %i.next.fr, %n
145   br i1 %cond, label %loop, label %exit
147 exit:
148   ret void
151 define void @add_ind(i32 %init, i32 %n) {
152 ; CHECK-LABEL: @add_ind(
153 ; CHECK-NEXT:  entry:
154 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
155 ; CHECK-NEXT:    br label [[LOOP:%.*]]
156 ; CHECK:       loop:
157 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
158 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
159 ; CHECK-NEXT:    [[I_FR_NEXT:%.*]] = add nuw nsw i32 [[I]], 1
160 ; CHECK-NEXT:    call void @call(i32 [[I_FR_NEXT]])
161 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_FR_NEXT]], [[N:%.*]]
162 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
163 ; CHECK:       exit:
164 ; CHECK-NEXT:    ret void
166 entry:
167   br label %loop
169 loop:
170   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
171   %i.next = add nuw nsw i32 %i, 1
172   %i.fr = freeze i32 %i
173   %i.fr.next = add nuw nsw i32 %i.fr, 1
174   call void @call(i32 %i.fr.next)
175   %cond = icmp eq i32 %i.fr.next, %n
176   br i1 %cond, label %loop, label %exit
178 exit:
179   ret void
182 ; Negative test
183 define void @add_ind_frozen(i32 %init, i32 %n) {
184 ; CHECK-LABEL: @add_ind_frozen(
185 ; CHECK-NEXT:  entry:
186 ; CHECK-NEXT:    br label [[LOOP:%.*]]
187 ; CHECK:       loop:
188 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ]
189 ; CHECK-NEXT:    [[I_FR:%.*]] = freeze i32 [[I]]
190 ; CHECK-NEXT:    [[I_NEXT_FR]] = add nuw nsw i32 [[I_FR]], 1
191 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT_FR]])
192 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT_FR]], [[N:%.*]]
193 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
194 ; CHECK:       exit:
195 ; CHECK-NEXT:    ret void
197 entry:
198   br label %loop
200 loop:
201   %i = phi i32 [%init, %entry], [%i.next.fr, %loop]
202   %i.fr = freeze i32 %i
203   %i.next.fr = add nuw nsw i32 %i.fr, 1
204   call void @call(i32 %i.next.fr)
205   %cond = icmp eq i32 %i.next.fr, %n
206   br i1 %cond, label %loop, label %exit
208 exit:
209   ret void
212 define void @add_flags_not_compared(i32 %init, i32 %n) {
213 ; CHECK-LABEL: @add_flags_not_compared(
214 ; CHECK-NEXT:  entry:
215 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
216 ; CHECK-NEXT:    br label [[LOOP:%.*]]
217 ; CHECK:       loop:
218 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
219 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
220 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
221 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
222 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
223 ; CHECK:       exit:
224 ; CHECK-NEXT:    ret void
226 entry:
227   br label %loop
229 loop:
230   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
231   %i.next = add nuw nsw i32 %i, 1
232   %i.next.fr = freeze i32 %i.next
233   call void @call(i32 %i.next.fr)
234   %cond = icmp eq i32 %i.next, %n
235   br i1 %cond, label %loop, label %exit
237 exit:
238   ret void
241 ; Negative test
242 define void @add_flags_not_compared_stepinst(i32 %init, i32 %n) {
243 ; CHECK-LABEL: @add_flags_not_compared_stepinst(
244 ; CHECK-NEXT:  entry:
245 ; CHECK-NEXT:    br label [[LOOP:%.*]]
246 ; CHECK:       loop:
247 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT_FR:%.*]], [[LOOP]] ]
248 ; CHECK-NEXT:    [[I_NEXT:%.*]] = add nuw nsw i32 [[I]], 1
249 ; CHECK-NEXT:    [[I_NEXT_FR]] = freeze i32 [[I_NEXT]]
250 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT_FR]])
251 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
252 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
253 ; CHECK:       exit:
254 ; CHECK-NEXT:    ret void
256 entry:
257   br label %loop
259 loop:
260   %i = phi i32 [ %init, %entry ], [ %i.next.fr, %loop ]
261   %i.next = add nuw nsw i32 %i, 1
262   %i.next.fr = freeze i32 %i.next
263   call void @call(i32 %i.next.fr)
264   %cond = icmp eq i32 %i.next, %n
265   br i1 %cond, label %loop, label %exit
267 exit:
268   ret void
271 ; Negative test
272 ; If pushing freeze through icmp is needed, this should be enabled.
273 ; There is no correctness issue in pushing freeze into icmp here, just it's
274 ; being conservative right now.
275 define void @add_flags_stepinst_frozen(i32 %init, i32 %n) {
276 ; CHECK-LABEL: @add_flags_stepinst_frozen(
277 ; CHECK-NEXT:  entry:
278 ; CHECK-NEXT:    br label [[LOOP:%.*]]
279 ; CHECK:       loop:
280 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
281 ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
282 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
283 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
284 ; CHECK-NEXT:    [[COND_FR:%.*]] = freeze i1 [[COND]]
285 ; CHECK-NEXT:    br i1 [[COND_FR]], label [[LOOP]], label [[EXIT:%.*]]
286 ; CHECK:       exit:
287 ; CHECK-NEXT:    ret void
289 entry:
290   br label %loop
292 loop:
293   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
294   %i.next = add nuw nsw i32 %i, 1
295   call void @call(i32 %i.next)
296   %cond = icmp eq i32 %i.next, %n
297   %cond.fr = freeze i1 %cond
298   br i1 %cond.fr, label %loop, label %exit
300 exit:
301   ret void
304 define void @sub(i32 %init, i32 %n) {
305 ; CHECK-LABEL: @sub(
306 ; CHECK-NEXT:  entry:
307 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
308 ; CHECK-NEXT:    br label [[LOOP:%.*]]
309 ; CHECK:       loop:
310 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
311 ; CHECK-NEXT:    [[I_NEXT]] = sub i32 [[I]], 1
312 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
313 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
314 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
315 ; CHECK:       exit:
316 ; CHECK-NEXT:    ret void
318 entry:
319   br label %loop
321 loop:
322   %i = phi i32 [%init, %entry], [%i.next, %loop]
323   %i.next = sub nuw nsw i32 %i, 1
324   %i.next.fr = freeze i32 %i.next
325   call void @call(i32 %i.next.fr)
326   %cond = icmp eq i32 %i.next.fr, %n
327   br i1 %cond, label %loop, label %exit
329 exit:
330   ret void
333 define void @init_const(i32 %n) {
334 ; CHECK-LABEL: @init_const(
335 ; CHECK-NEXT:  entry:
336 ; CHECK-NEXT:    br label [[LOOP:%.*]]
337 ; CHECK:       loop:
338 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
339 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
340 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
341 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
342 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
343 ; CHECK:       exit:
344 ; CHECK-NEXT:    ret void
346 entry:
347   br label %loop
349 loop:
350   %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
351   %i.next = add nuw nsw i32 %i, 1
352   %i.next.fr = freeze i32 %i.next
353   call void @call(i32 %i.next.fr)
354   %cond = icmp eq i32 %i.next.fr, %n
355   br i1 %cond, label %loop, label %exit
357 exit:
358   ret void
361 define void @step_init_arg(i32 %init, i32 %n, i32 %step) {
362 ; CHECK-LABEL: @step_init_arg(
363 ; CHECK-NEXT:  entry:
364 ; CHECK-NEXT:    [[STEP_FROZEN:%.*]] = freeze i32 [[STEP:%.*]]
365 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
366 ; CHECK-NEXT:    br label [[LOOP:%.*]]
367 ; CHECK:       loop:
368 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
369 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], [[STEP_FROZEN]]
370 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
371 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
372 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
373 ; CHECK:       exit:
374 ; CHECK-NEXT:    ret void
376 entry:
377   br label %loop
379 loop:
380   %i = phi i32 [%init, %entry], [%i.next, %loop]
381   %i.next = add nuw nsw i32 %i, %step
382   %i.next.fr = freeze i32 %i.next
383   call void @call(i32 %i.next.fr)
384   %cond = icmp eq i32 %i.next.fr, %n
385   br i1 %cond, label %loop, label %exit
387 exit:
388   ret void
391 define void @step_init_arg_multiuses(i32 %init, i32 %n, i32 %step) {
392 ; CHECK-LABEL: @step_init_arg_multiuses(
393 ; CHECK-NEXT:  entry:
394 ; CHECK-NEXT:    [[STEP_FROZEN:%.*]] = freeze i32 [[STEP:%.*]]
395 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
396 ; CHECK-NEXT:    br label [[LOOP:%.*]]
397 ; CHECK:       loop:
398 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
399 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], [[STEP_FROZEN]]
400 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
401 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
402 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
403 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
404 ; CHECK:       exit:
405 ; CHECK-NEXT:    ret void
407 entry:
408   br label %loop
410 loop:
411   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
412   %i.next = add nsw nuw i32 %i, %step
413   %i.next.fr1 = freeze i32 %i.next
414   call void @call(i32 %i.next.fr1)
415   %i.next.fr2 = freeze i32 %i.next
416   call void @call(i32 %i.next.fr2)
417   %cond = icmp eq i32 %i.next, %n
418   br i1 %cond, label %loop, label %exit
420 exit:
421   ret void
424 define void @step_init_arg_multiuses2(i32 %init, i32 %n, i32 %step) {
425 ; CHECK-LABEL: @step_init_arg_multiuses2(
426 ; CHECK-NEXT:  entry:
427 ; CHECK-NEXT:    [[STEP_FROZEN:%.*]] = freeze i32 [[STEP:%.*]]
428 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT:%.*]]
429 ; CHECK-NEXT:    br label [[LOOP:%.*]]
430 ; CHECK:       loop:
431 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
432 ; CHECK-NEXT:    call void @call(i32 [[I]])
433 ; CHECK-NEXT:    call void @call(i32 [[I]])
434 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], [[STEP_FROZEN]]
435 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
436 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
437 ; CHECK:       exit:
438 ; CHECK-NEXT:    ret void
440 entry:
441   br label %loop
443 loop:
444   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
445   %i.fr1 = freeze i32 %i
446   call void @call(i32 %i.fr1)
447   %i.fr2 = freeze i32 %i
448   call void @call(i32 %i.fr2)
449   %i.next = add nsw nuw i32 %i, %step
450   %cond = icmp eq i32 %i.next, %n
451   br i1 %cond, label %loop, label %exit
453 exit:
454   ret void
457 define void @step_init_inst(i32 %n) {
458 ; CHECK-LABEL: @step_init_inst(
459 ; CHECK-NEXT:  entry:
460 ; CHECK-NEXT:    [[STEP:%.*]] = call i32 @get_step()
461 ; CHECK-NEXT:    [[INIT:%.*]] = call i32 @get_step()
462 ; CHECK-NEXT:    [[STEP_FROZEN:%.*]] = freeze i32 [[STEP]]
463 ; CHECK-NEXT:    [[INIT_FROZEN:%.*]] = freeze i32 [[INIT]]
464 ; CHECK-NEXT:    br label [[LOOP:%.*]]
465 ; CHECK:       loop:
466 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FROZEN]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
467 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], [[STEP_FROZEN]]
468 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT]])
469 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
470 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
471 ; CHECK:       exit:
472 ; CHECK-NEXT:    ret void
474 entry:
475   %step = call i32 @get_step()
476   %init = call i32 @get_step()
477   br label %loop
479 loop:
480   %i = phi i32 [%init, %entry], [%i.next, %loop]
481   %i.next = add nuw nsw i32 %i, %step
482   %i.next.fr = freeze i32 %i.next
483   call void @call(i32 %i.next.fr)
484   %cond = icmp eq i32 %i.next.fr, %n
485   br i1 %cond, label %loop, label %exit
487 exit:
488   ret void
491 ; Negative test
492 define void @step_inst(i32 %init, i32 %n) {
493 ; CHECK-LABEL: @step_inst(
494 ; CHECK-NEXT:  entry:
495 ; CHECK-NEXT:    br label [[LOOP:%.*]]
496 ; CHECK:       loop:
497 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
498 ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], [[I]]
499 ; CHECK-NEXT:    [[I_NEXT_FR:%.*]] = freeze i32 [[I_NEXT]]
500 ; CHECK-NEXT:    call void @call(i32 [[I_NEXT_FR]])
501 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT_FR]], [[N:%.*]]
502 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
503 ; CHECK:       exit:
504 ; CHECK-NEXT:    ret void
506 entry:
507   br label %loop
509 loop:
510   %i = phi i32 [%init, %entry], [%i.next, %loop]
511   %i.next = add nuw nsw i32 %i, %i
512   %i.next.fr = freeze i32 %i.next
513   call void @call(i32 %i.next.fr)
514   %cond = icmp eq i32 %i.next.fr, %n
515   br i1 %cond, label %loop, label %exit
517 exit:
518   ret void
521 ; Negative test
522 define void @gep(i8* %init, i8* %end) {
523 ; CHECK-LABEL: @gep(
524 ; CHECK-NEXT:  entry:
525 ; CHECK-NEXT:    br label [[LOOP:%.*]]
526 ; CHECK:       loop:
527 ; CHECK-NEXT:    [[I:%.*]] = phi i8* [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
528 ; CHECK-NEXT:    [[I_NEXT]] = getelementptr inbounds i8, i8* [[I]], i64 1
529 ; CHECK-NEXT:    [[I_NEXT_FR:%.*]] = freeze i8* [[I_NEXT]]
530 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i8* [[I_NEXT_FR]], [[END:%.*]]
531 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
532 ; CHECK:       exit:
533 ; CHECK-NEXT:    ret void
535 entry:
536   br label %loop
538 loop:
539   %i = phi i8* [ %init, %entry], [%i.next, %loop ]
540   %i.next = getelementptr inbounds i8, i8* %i, i64 1
541   %i.next.fr = freeze i8* %i.next
542   %cond = icmp eq i8* %i.next.fr, %end
543   br i1 %cond, label %loop, label %exit
545 exit:
546   ret void