[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Transforms / InstCombine / freeze.ll
blobe97aa28d551bb0bdf97964720c1919811254ca91
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 define i32 @fold(i32 %x) {
5 ; CHECK-LABEL: @fold(
6 ; CHECK-NEXT:    [[Y:%.*]] = freeze i32 [[X:%.*]]
7 ; CHECK-NEXT:    ret i32 [[Y]]
9   %y = freeze i32 %x
10   %z = freeze i32 %y
11   ret i32 %z
14 define i32 @make_const() {
15 ; CHECK-LABEL: @make_const(
16 ; CHECK-NEXT:    ret i32 10
18   %x = freeze i32 10
19   ret i32 %x
22 define i32 @and_freeze_undef(i32 %x) {
23 ; CHECK-LABEL: @and_freeze_undef(
24 ; CHECK-NEXT:    ret i32 0
26   %f = freeze i32 undef
27   %res = and i32 %x, %f
28   ret i32 %res
31 declare void @use_i32(i32)
33 define i32 @and_freeze_undef_multipleuses(i32 %x) {
34 ; CHECK-LABEL: @and_freeze_undef_multipleuses(
35 ; CHECK-NEXT:    call void @use_i32(i32 0)
36 ; CHECK-NEXT:    ret i32 0
38   %f = freeze i32 undef
39   %res = and i32 %x, %f
40   call void @use_i32(i32 %f)
41   ret i32 %res
44 define i32 @or_freeze_undef(i32 %x) {
45 ; CHECK-LABEL: @or_freeze_undef(
46 ; CHECK-NEXT:    ret i32 -1
48   %f = freeze i32 undef
49   %res = or i32 %x, %f
50   ret i32 %res
53 define i32 @or_freeze_undef_multipleuses(i32 %x) {
54 ; CHECK-LABEL: @or_freeze_undef_multipleuses(
55 ; CHECK-NEXT:    call void @use_i32(i32 0)
56 ; CHECK-NEXT:    ret i32 [[X:%.*]]
58   %f = freeze i32 undef
59   %res = or i32 %x, %f
60   call void @use_i32(i32 %f)
61   ret i32 %res
64 declare void @use_i32_i1(i32, i1)
66 define void @or_select_multipleuses(i32 %x, i1 %y) {
67 ; CHECK-LABEL: @or_select_multipleuses(
68 ; CHECK-NEXT:    call void @use_i32_i1(i32 32, i1 [[Y:%.*]])
69 ; CHECK-NEXT:    ret void
71   %f = freeze i1 undef
72   %a = select i1 %f, i32 %x, i32 32 ; prefers %f to be false
73   %b = or i1 %f, %y ; prefers %f to be true
74   call void @use_i32_i1(i32 %a, i1 %b)
75   ret void
78 define void @or_select_multipleuses_logical(i32 %x, i1 %y) {
79 ; CHECK-LABEL: @or_select_multipleuses_logical(
80 ; CHECK-NEXT:    call void @use_i32_i1(i32 32, i1 [[Y:%.*]])
81 ; CHECK-NEXT:    ret void
83   %f = freeze i1 undef
84   %a = select i1 %f, i32 %x, i32 32 ; prefers %f to be false
85   %b = select i1 %f, i1 true, i1 %y ; prefers %f to be true
86   call void @use_i32_i1(i32 %a, i1 %b)
87   ret void
90 ; Move the freeze forward to prevent poison from spreading.
92 define i32 @early_freeze_test1(i32 %x, i32 %y) {
93 ; CHECK-LABEL: @early_freeze_test1(
94 ; CHECK-NEXT:    [[V1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
95 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1]]
96 ; CHECK-NEXT:    [[V2:%.*]] = shl i32 [[V1_FR]], 1
97 ; CHECK-NEXT:    [[V3:%.*]] = and i32 [[V2]], 2
98 ; CHECK-NEXT:    ret i32 [[V3]]
100   %v1 = add i32 %x, %y
101   %v2 = shl i32 %v1, 1
102   %v3 = and i32 %v2, 2
103   %v3.fr = freeze i32 %v3
104   ret i32 %v3.fr
107 define i1 @early_freeze_test2(i32* %ptr) {
108 ; CHECK-LABEL: @early_freeze_test2(
109 ; CHECK-NEXT:    [[V1:%.*]] = load i32, i32* [[PTR:%.*]], align 4
110 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1]]
111 ; CHECK-NEXT:    [[V2:%.*]] = and i32 [[V1_FR]], 1
112 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V2]], 0
113 ; CHECK-NEXT:    ret i1 [[COND]]
115   %v1 = load i32, i32* %ptr
116   %v2 = and i32 %v1, 1
117   %cond = icmp eq i32 %v2, 0
118   %cond.fr = freeze i1 %cond
119   ret i1 %cond.fr
122 define i32 @early_freeze_test3(i32 %v1) {
123 ; CHECK-LABEL: @early_freeze_test3(
124 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1:%.*]]
125 ; CHECK-NEXT:    [[V2:%.*]] = shl i32 [[V1_FR]], 1
126 ; CHECK-NEXT:    [[V3:%.*]] = add i32 [[V2]], 2
127 ; CHECK-NEXT:    [[V4:%.*]] = or i32 [[V3]], 1
128 ; CHECK-NEXT:    ret i32 [[V4]]
130   %v2 = shl i32 %v1, 1
131   %v3 = add nuw i32 %v2, 2
132   %v4 = or i32 %v3, 1
133   %v4.fr = freeze i32 %v4
134   ret i32 %v4.fr
137 ; If replace all dominated uses of v to freeze(v).
139 define void @freeze_dominated_uses_test1(i32 %v) {
140 ; CHECK-LABEL: @freeze_dominated_uses_test1(
141 ; CHECK-NEXT:    [[V_FR:%.*]] = freeze i32 [[V:%.*]]
142 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR]])
143 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR]])
144 ; CHECK-NEXT:    ret void
146   %v.fr = freeze i32 %v
147   call void @use_i32(i32 %v)
148   call void @use_i32(i32 %v.fr)
149   ret void
152 define void @freeze_dominated_uses_test2(i32 %v) {
153 ; CHECK-LABEL: @freeze_dominated_uses_test2(
154 ; CHECK-NEXT:  entry:
155 ; CHECK-NEXT:    call void @use_i32(i32 [[V:%.*]])
156 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[V]], 0
157 ; CHECK-NEXT:    br i1 [[COND]], label [[BB0:%.*]], label [[BB1:%.*]]
158 ; CHECK:       bb0:
159 ; CHECK-NEXT:    [[V_FR:%.*]] = freeze i32 [[V]]
160 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR]])
161 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR]])
162 ; CHECK-NEXT:    br label [[END:%.*]]
163 ; CHECK:       bb1:
164 ; CHECK-NEXT:    call void @use_i32(i32 [[V]])
165 ; CHECK-NEXT:    br label [[END]]
166 ; CHECK:       end:
167 ; CHECK-NEXT:    ret void
169 entry:
170   call void @use_i32(i32 %v)
171   %cond = icmp eq i32 %v, 0
172   br i1 %cond, label %bb0, label %bb1
174 bb0:
175   %v.fr = freeze i32 %v
176   call void @use_i32(i32 %v.fr)
177   call void @use_i32(i32 %v)
178   br label %end
180 bb1:
181   call void @use_i32(i32 %v)
182   br label %end
184 end:
185   ret void
188 ; If there is a duplicate freeze, it will be removed.
190 define void @freeze_dominated_uses_test3(i32 %v, i1 %cond) {
191 ; CHECK-LABEL: @freeze_dominated_uses_test3(
192 ; CHECK-NEXT:  entry:
193 ; CHECK-NEXT:    [[V_FR1:%.*]] = freeze i32 [[V:%.*]]
194 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR1]])
195 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
196 ; CHECK:       bb0:
197 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR1]])
198 ; CHECK-NEXT:    br label [[END:%.*]]
199 ; CHECK:       bb1:
200 ; CHECK-NEXT:    call void @use_i32(i32 [[V_FR1]])
201 ; CHECK-NEXT:    br label [[END]]
202 ; CHECK:       end:
203 ; CHECK-NEXT:    ret void
205 entry:
206   %v.fr1 = freeze i32 %v
207   call void @use_i32(i32 %v.fr1)
208   br i1 %cond, label %bb0, label %bb1
210 bb0:
211   %v.fr2 = freeze i32 %v
212   call void @use_i32(i32 %v.fr2)
213   br label %end
215 bb1:
216   call void @use_i32(i32 %v)
217   br label %end
219 end:
220   ret void
224 define i32 @propagate_drop_flags_add(i32 %arg) {
225 ; CHECK-LABEL: @propagate_drop_flags_add(
226 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
227 ; CHECK-NEXT:    [[V1:%.*]] = add i32 [[ARG_FR]], 2
228 ; CHECK-NEXT:    ret i32 [[V1]]
230   %v1 = add nsw nuw i32 %arg, 2
231   %v1.fr = freeze i32 %v1
232   ret i32 %v1.fr
235 define i32 @propagate_drop_flags_add_foldaway(i32 noundef %arg) {
236 ; CHECK-LABEL: @propagate_drop_flags_add_foldaway(
237 ; CHECK-NEXT:    [[V1:%.*]] = add i32 [[ARG:%.*]], 2
238 ; CHECK-NEXT:    ret i32 [[V1]]
240   %v1 = add nsw nuw i32 %arg, 2
241   %v1.fr = freeze i32 %v1
242   ret i32 %v1.fr
245 define i32 @propagate_drop_flags_sub(i32 %arg) {
246 ; CHECK-LABEL: @propagate_drop_flags_sub(
247 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
248 ; CHECK-NEXT:    [[V1:%.*]] = add i32 [[ARG_FR]], -2
249 ; CHECK-NEXT:    ret i32 [[V1]]
251   %v1 = sub nsw nuw i32 %arg, 2
252   %v1.fr = freeze i32 %v1
253   ret i32 %v1.fr
256 define i32 @propagate_drop_flags_mul(i32 %arg) {
257 ; CHECK-LABEL: @propagate_drop_flags_mul(
258 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
259 ; CHECK-NEXT:    [[V1:%.*]] = shl i32 [[ARG_FR]], 1
260 ; CHECK-NEXT:    ret i32 [[V1]]
262   %v1 = mul nsw nuw i32 %arg, 2
263   %v1.fr = freeze i32 %v1
264   ret i32 %v1.fr
267 define i32 @propagate_drop_flags_udiv(i32 %arg) {
268 ; CHECK-LABEL: @propagate_drop_flags_udiv(
269 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
270 ; CHECK-NEXT:    [[V1:%.*]] = lshr i32 [[ARG_FR]], 1
271 ; CHECK-NEXT:    ret i32 [[V1]]
273   %v1 = udiv exact i32 %arg, 2
274   %v1.fr = freeze i32 %v1
275   ret i32 %v1.fr
278 define i32 @propagate_drop_flags_sdiv(i32 %arg) {
279 ; CHECK-LABEL: @propagate_drop_flags_sdiv(
280 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
281 ; CHECK-NEXT:    [[V1:%.*]] = ashr i32 [[ARG_FR]], 1
282 ; CHECK-NEXT:    ret i32 [[V1]]
284   %v1 = sdiv exact i32 %arg, 2
285   %v1.fr = freeze i32 %v1
286   ret i32 %v1.fr
289 define i32 @propagate_drop_shl1(i32 %arg) {
290 ; CHECK-LABEL: @propagate_drop_shl1(
291 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
292 ; CHECK-NEXT:    [[V1:%.*]] = shl i32 [[ARG_FR]], 2
293 ; CHECK-NEXT:    ret i32 [[V1]]
295   %v1 = shl nsw nuw i32 %arg, 2
296   %v1.fr = freeze i32 %v1
297   ret i32 %v1.fr
300 define i32 @propagate_drop_shl2(i32 %arg, i32 %unknown) {
301 ; CHECK-LABEL: @propagate_drop_shl2(
302 ; CHECK-NEXT:    [[V1:%.*]] = shl nuw nsw i32 [[ARG:%.*]], [[UNKNOWN:%.*]]
303 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1]]
304 ; CHECK-NEXT:    ret i32 [[V1_FR]]
306   %v1 = shl nsw nuw i32 %arg, %unknown
307   %v1.fr = freeze i32 %v1
308   ret i32 %v1.fr
311 define i32 @propagate_drop_ashr1(i32 %arg) {
312 ; CHECK-LABEL: @propagate_drop_ashr1(
313 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
314 ; CHECK-NEXT:    [[V1:%.*]] = ashr i32 [[ARG_FR]], 2
315 ; CHECK-NEXT:    ret i32 [[V1]]
317   %v1 = ashr exact i32 %arg, 2
318   %v1.fr = freeze i32 %v1
319   ret i32 %v1.fr
322 define i32 @propagate_drop_ashr2(i32 %arg, i32 %unknown) {
323 ; CHECK-LABEL: @propagate_drop_ashr2(
324 ; CHECK-NEXT:    [[V1:%.*]] = ashr exact i32 [[ARG:%.*]], [[UNKNOWN:%.*]]
325 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1]]
326 ; CHECK-NEXT:    ret i32 [[V1_FR]]
328   %v1 = ashr exact i32 %arg, %unknown
329   %v1.fr = freeze i32 %v1
330   ret i32 %v1.fr
333 define i32 @propagate_drop_lshr1(i32 %arg) {
334 ; CHECK-LABEL: @propagate_drop_lshr1(
335 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
336 ; CHECK-NEXT:    [[V1:%.*]] = lshr i32 [[ARG_FR]], 2
337 ; CHECK-NEXT:    ret i32 [[V1]]
339   %v1 = lshr exact i32 %arg, 2
340   %v1.fr = freeze i32 %v1
341   ret i32 %v1.fr
344 define i32 @propagate_drop_lshr2(i32 %arg, i32 %unknown) {
345 ; CHECK-LABEL: @propagate_drop_lshr2(
346 ; CHECK-NEXT:    [[V1:%.*]] = lshr exact i32 [[ARG:%.*]], [[UNKNOWN:%.*]]
347 ; CHECK-NEXT:    [[V1_FR:%.*]] = freeze i32 [[V1]]
348 ; CHECK-NEXT:    ret i32 [[V1_FR]]
350   %v1 = lshr exact i32 %arg, %unknown
351   %v1.fr = freeze i32 %v1
352   ret i32 %v1.fr
355 define i8* @propagate_drop_gep1(i8* %arg) {
356 ; CHECK-LABEL: @propagate_drop_gep1(
357 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i8* [[ARG:%.*]]
358 ; CHECK-NEXT:    [[V1:%.*]] = getelementptr i8, i8* [[ARG_FR]], i64 16
359 ; CHECK-NEXT:    ret i8* [[V1]]
361   %v1 = getelementptr inbounds i8, i8* %arg, i64 16
362   %v1.fr = freeze i8* %v1
363   ret i8* %v1.fr
366 define float @propagate_drop_fneg(float %arg) {
367 ; CHECK-LABEL: @propagate_drop_fneg(
368 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
369 ; CHECK-NEXT:    [[V1:%.*]] = fneg float [[ARG_FR]]
370 ; CHECK-NEXT:    ret float [[V1]]
372   %v1 = fneg ninf nnan float %arg
373   %v1.fr = freeze float %v1
374   ret float %v1.fr
378 define float @propagate_drop_fadd(float %arg) {
379 ; CHECK-LABEL: @propagate_drop_fadd(
380 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
381 ; CHECK-NEXT:    [[V1:%.*]] = fadd float [[ARG_FR]], 2.000000e+00
382 ; CHECK-NEXT:    ret float [[V1]]
384   %v1 = fadd ninf nnan float %arg, 2.0
385   %v1.fr = freeze float %v1
386   ret float %v1.fr
389 define float @propagate_drop_fsub(float %arg) {
390 ; CHECK-LABEL: @propagate_drop_fsub(
391 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
392 ; CHECK-NEXT:    [[V1:%.*]] = fadd float [[ARG_FR]], -2.000000e+00
393 ; CHECK-NEXT:    ret float [[V1]]
395   %v1 = fsub ninf nnan float %arg, 2.0
396   %v1.fr = freeze float %v1
397   ret float %v1.fr
400 define float @propagate_drop_fmul(float %arg) {
401 ; CHECK-LABEL: @propagate_drop_fmul(
402 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
403 ; CHECK-NEXT:    [[V1:%.*]] = fmul float [[ARG_FR]], 2.000000e+00
404 ; CHECK-NEXT:    ret float [[V1]]
406   %v1 = fmul ninf nnan float %arg, 2.0
407   %v1.fr = freeze float %v1
408   ret float %v1.fr
411 define float @propagate_drop_fdiv(float %arg) {
412 ; CHECK-LABEL: @propagate_drop_fdiv(
413 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
414 ; CHECK-NEXT:    [[V1:%.*]] = fmul float [[ARG_FR]], 5.000000e-01
415 ; CHECK-NEXT:    ret float [[V1]]
417   %v1 = fdiv ninf nnan float %arg, 2.0
418   %v1.fr = freeze float %v1
419   ret float %v1.fr
422 define float @propagate_drop_frem(float %arg) {
423 ; CHECK-LABEL: @propagate_drop_frem(
424 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
425 ; CHECK-NEXT:    [[V1:%.*]] = frem float [[ARG_FR]], 2.000000e+00
426 ; CHECK-NEXT:    ret float [[V1]]
428   %v1 = frem ninf nnan float %arg, 2.0
429   %v1.fr = freeze float %v1
430   ret float %v1.fr
433 define i1 @propagate_drop_fcmp(float %arg) {
434 ; CHECK-LABEL: @propagate_drop_fcmp(
435 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze float [[ARG:%.*]]
436 ; CHECK-NEXT:    [[V1:%.*]] = fcmp une float [[ARG_FR]], 2.000000e+00
437 ; CHECK-NEXT:    ret i1 [[V1]]
439   %v1 = fcmp ninf nnan une float %arg, 2.0
440   %v1.fr = freeze i1 %v1
441   ret i1 %v1.fr
444 define float @propagate_drop_fmath_select(i1 %arg) {
445 ; CHECK-LABEL: @propagate_drop_fmath_select(
446 ; CHECK-NEXT:    [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]]
447 ; CHECK-NEXT:    [[V1:%.*]] = select i1 [[ARG_FR]], float 1.000000e+00, float -1.000000e+00
448 ; CHECK-NEXT:    ret float [[V1]]
450   %v1 = select ninf nnan i1 %arg, float 1.0, float -1.0
451   %v1.fr = freeze float %v1
452   ret float %v1.fr
455 define void @fold_phi_noop(i32 noundef %init, i32 %n) {
456 ; CHECK-LABEL: @fold_phi_noop(
457 ; CHECK-NEXT:  entry:
458 ; CHECK-NEXT:    br label [[LOOP:%.*]]
459 ; CHECK:       loop:
460 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
461 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
462 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
463 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
464 ; CHECK:       exit:
465 ; CHECK-NEXT:    ret void
467 entry:
468   br label %loop
470 loop:                                             ; preds = %loop, %entry
471   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
472   %i.fr = freeze i32 %i
473   %i.next = add i32 %i.fr, 1
474   %cond = icmp eq i32 %i.next, %n
475   br i1 %cond, label %loop, label %exit
477 exit:                                             ; preds = %loop
478   ret void
481 define void @fold_phi_through(i32 %init, i32 %n) {
482 ; CHECK-LABEL: @fold_phi_through(
483 ; CHECK-NEXT:  entry:
484 ; CHECK-NEXT:    [[PHI_FR:%.*]] = freeze i32 [[INIT:%.*]]
485 ; CHECK-NEXT:    br label [[LOOP:%.*]]
486 ; CHECK:       loop:
487 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[PHI_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
488 ; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
489 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
490 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
491 ; CHECK:       exit:
492 ; CHECK-NEXT:    ret void
494 entry:
495   br label %loop
497 loop:                                             ; preds = %loop, %entry
498   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
499   %i.fr = freeze i32 %i
500   %i.next = add i32 %i.fr, 1
501   %cond = icmp eq i32 %i.next, %n
502   br i1 %cond, label %loop, label %exit
504 exit:                                             ; preds = %loop
505   ret void
508 define void @fold_phi_neg_flags(i32 %init, i32 %n) {
509 ; CHECK-LABEL: @fold_phi_neg_flags(
510 ; CHECK-NEXT:  entry:
511 ; CHECK-NEXT:    br label [[LOOP:%.*]]
512 ; CHECK:       loop:
513 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
514 ; CHECK-NEXT:    [[I_FR:%.*]] = freeze i32 [[I]]
515 ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I_FR]], 1
516 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
517 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
518 ; CHECK:       exit:
519 ; CHECK-NEXT:    ret void
521 entry:
522   br label %loop
524 loop:                                             ; preds = %loop, %entry
525   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
526   %i.fr = freeze i32 %i
527   %i.next = add nsw nuw i32 %i.fr, 1
528   %cond = icmp eq i32 %i.next, %n
529   br i1 %cond, label %loop, label %exit
531 exit:                                             ; preds = %loop
532   ret void
535 define void @fold_phi_non_add(i32 %init, i32 %n) {
536 ; CHECK-LABEL: @fold_phi_non_add(
537 ; CHECK-NEXT:  entry:
538 ; CHECK-NEXT:    [[PHI_FR:%.*]] = freeze i32 [[INIT:%.*]]
539 ; CHECK-NEXT:    br label [[LOOP:%.*]]
540 ; CHECK:       loop:
541 ; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[PHI_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
542 ; CHECK-NEXT:    [[I_NEXT]] = shl i32 [[I]], 1
543 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]]
544 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
545 ; CHECK:       exit:
546 ; CHECK-NEXT:    ret void
548 entry:
549   br label %loop
551 loop:                                             ; preds = %loop, %entry
552   %i = phi i32 [ %init, %entry ], [ %i.next, %loop ]
553   %i.fr = freeze i32 %i
554   %i.next = shl i32 %i.fr, 1
555   %cond = icmp eq i32 %i.next, %n
556   br i1 %cond, label %loop, label %exit
558 exit:                                             ; preds = %loop
559   ret void
562 define void @fold_phi_gep(i8* %init, i8* %end) {
563 ; CHECK-LABEL: @fold_phi_gep(
564 ; CHECK-NEXT:  entry:
565 ; CHECK-NEXT:    [[PHI_FR:%.*]] = freeze i8* [[INIT:%.*]]
566 ; CHECK-NEXT:    br label [[LOOP:%.*]]
567 ; CHECK:       loop:
568 ; CHECK-NEXT:    [[I:%.*]] = phi i8* [ [[PHI_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ]
569 ; CHECK-NEXT:    [[I_NEXT]] = getelementptr i8, i8* [[I]], i64 1
570 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i8* [[I_NEXT]], [[END:%.*]]
571 ; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
572 ; CHECK:       exit:
573 ; CHECK-NEXT:    ret void
575 entry:
576   br label %loop
578 loop:                                             ; preds = %loop, %entry
579   %i = phi i8* [ %init, %entry ], [ %i.next, %loop ]
580   %i.fr = freeze i8* %i
581   %i.next = getelementptr i8, i8* %i.fr, i64 1
582   %cond = icmp eq i8* %i.next, %end
583   br i1 %cond, label %loop, label %exit
585 exit:                                             ; preds = %loop
586   ret void