xref: /llvm-project/llvm/test/Transforms/GVN/condprop.ll (revision 32cd18975d2e1de5a783e9b1c3c21a234d5723b4)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=gvn -S | FileCheck %s
3
4@a = external global i32		; <ptr> [#uses=7]
5
6define i32 @test1() nounwind {
7; CHECK-LABEL: @test1(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
10; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 4
11; CHECK-NEXT:    br i1 [[TMP1]], label [[BB:%.*]], label [[BB1:%.*]]
12; CHECK:       bb:
13; CHECK-NEXT:    br label [[BB8:%.*]]
14; CHECK:       bb1:
15; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 5
16; CHECK-NEXT:    br i1 [[TMP2]], label [[BB2:%.*]], label [[BB3:%.*]]
17; CHECK:       bb2:
18; CHECK-NEXT:    br label [[BB8]]
19; CHECK:       bb3:
20; CHECK-NEXT:    br i1 false, label [[BB4:%.*]], label [[BB5:%.*]]
21; CHECK:       bb4:
22; CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr @a, align 4
23; CHECK-NEXT:    [[TMP4:%.*]] = add i32 [[TMP3]], 5
24; CHECK-NEXT:    br label [[BB8]]
25; CHECK:       bb5:
26; CHECK-NEXT:    br i1 false, label [[BB6:%.*]], label [[BB7:%.*]]
27; CHECK:       bb6:
28; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr @a, align 4
29; CHECK-NEXT:    [[TMP6:%.*]] = add i32 [[TMP5]], 4
30; CHECK-NEXT:    br label [[BB8]]
31; CHECK:       bb7:
32; CHECK-NEXT:    br label [[BB8]]
33; CHECK:       bb8:
34; CHECK-NEXT:    [[DOT0:%.*]] = phi i32 [ [[TMP0]], [[BB7]] ], [ poison, [[BB6]] ], [ poison, [[BB4]] ], [ 4, [[BB2]] ], [ 5, [[BB]] ]
35; CHECK-NEXT:    ret i32 [[DOT0]]
36;
37entry:
38  %0 = load i32, ptr @a, align 4
39  %1 = icmp eq i32 %0, 4
40  br i1 %1, label %bb, label %bb1
41
42bb:		; preds = %entry
43  br label %bb8
44
45bb1:		; preds = %entry
46  %2 = load i32, ptr @a, align 4
47  %3 = icmp eq i32 %2, 5
48  br i1 %3, label %bb2, label %bb3
49
50bb2:		; preds = %bb1
51  br label %bb8
52
53bb3:		; preds = %bb1
54  %4 = load i32, ptr @a, align 4
55  %5 = icmp eq i32 %4, 4
56  br i1 %5, label %bb4, label %bb5
57
58bb4:		; preds = %bb3
59  %6 = load i32, ptr @a, align 4
60  %7 = add i32 %6, 5
61  br label %bb8
62
63bb5:		; preds = %bb3
64  %8 = load i32, ptr @a, align 4
65  %9 = icmp eq i32 %8, 5
66  br i1 %9, label %bb6, label %bb7
67
68bb6:		; preds = %bb5
69  %10 = load i32, ptr @a, align 4
70  %11 = add i32 %10, 4
71  br label %bb8
72
73bb7:		; preds = %bb5
74  %12 = load i32, ptr @a, align 4
75  br label %bb8
76
77bb8:		; preds = %bb7, %bb6, %bb4, %bb2, %bb
78  %.0 = phi i32 [ %12, %bb7 ], [ %11, %bb6 ], [ %7, %bb4 ], [ 4, %bb2 ], [ 5, %bb ]
79  br label %return
80
81return:		; preds = %bb8
82  ret i32 %.0
83}
84
85declare void @foo(i1)
86declare void @bar(i32)
87
88define void @test3(i32 %x, i32 %y) {
89; CHECK-LABEL: @test3(
90; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
91; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
92; CHECK-NEXT:    [[Z:%.*]] = and i1 [[XZ]], [[YZ]]
93; CHECK-NEXT:    br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
94; CHECK:       both_zero:
95; CHECK-NEXT:    call void @foo(i1 true)
96; CHECK-NEXT:    call void @foo(i1 true)
97; CHECK-NEXT:    call void @bar(i32 0)
98; CHECK-NEXT:    call void @bar(i32 0)
99; CHECK-NEXT:    ret void
100; CHECK:       nope:
101; CHECK-NEXT:    call void @foo(i1 false)
102; CHECK-NEXT:    ret void
103;
104  %xz = icmp eq i32 %x, 0
105  %yz = icmp eq i32 %y, 0
106  %z = and i1 %xz, %yz
107  br i1 %z, label %both_zero, label %nope
108both_zero:
109  call void @foo(i1 %xz)
110  call void @foo(i1 %yz)
111  call void @bar(i32 %x)
112  call void @bar(i32 %y)
113  ret void
114nope:
115  call void @foo(i1 %z)
116  ret void
117}
118
119define void @test3_select(i32 %x, i32 %y) {
120; CHECK-LABEL: @test3_select(
121; CHECK-NEXT:    [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0
122; CHECK-NEXT:    [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0
123; CHECK-NEXT:    [[Z:%.*]] = select i1 [[XZ]], i1 [[YZ]], i1 false
124; CHECK-NEXT:    br i1 [[Z]], label [[BOTH_ZERO:%.*]], label [[NOPE:%.*]]
125; CHECK:       both_zero:
126; CHECK-NEXT:    call void @foo(i1 true)
127; CHECK-NEXT:    call void @foo(i1 true)
128; CHECK-NEXT:    call void @bar(i32 0)
129; CHECK-NEXT:    call void @bar(i32 0)
130; CHECK-NEXT:    ret void
131; CHECK:       nope:
132; CHECK-NEXT:    call void @foo(i1 false)
133; CHECK-NEXT:    ret void
134;
135  %xz = icmp eq i32 %x, 0
136  %yz = icmp eq i32 %y, 0
137  %z = select i1 %xz, i1 %yz, i1 false
138  br i1 %z, label %both_zero, label %nope
139both_zero:
140  call void @foo(i1 %xz)
141  call void @foo(i1 %yz)
142  call void @bar(i32 %x)
143  call void @bar(i32 %y)
144  ret void
145nope:
146  call void @foo(i1 %z)
147  ret void
148}
149
150define void @test3_or(i32 %x, i32 %y) {
151; CHECK-LABEL: @test3_or(
152; CHECK-NEXT:    [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0
153; CHECK-NEXT:    [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0
154; CHECK-NEXT:    [[Z:%.*]] = or i1 [[XZ]], [[YZ]]
155; CHECK-NEXT:    br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]]
156; CHECK:       both_zero:
157; CHECK-NEXT:    call void @foo(i1 false)
158; CHECK-NEXT:    call void @foo(i1 false)
159; CHECK-NEXT:    call void @bar(i32 0)
160; CHECK-NEXT:    call void @bar(i32 0)
161; CHECK-NEXT:    ret void
162; CHECK:       nope:
163; CHECK-NEXT:    call void @foo(i1 true)
164; CHECK-NEXT:    ret void
165;
166  %xz = icmp ne i32 %x, 0
167  %yz = icmp ne i32 %y, 0
168  %z = or i1 %xz, %yz
169  br i1 %z, label %nope, label %both_zero
170both_zero:
171  call void @foo(i1 %xz)
172  call void @foo(i1 %yz)
173  call void @bar(i32 %x)
174  call void @bar(i32 %y)
175  ret void
176nope:
177  call void @foo(i1 %z)
178  ret void
179}
180
181define void @test3_or_select(i32 %x, i32 %y) {
182; CHECK-LABEL: @test3_or_select(
183; CHECK-NEXT:    [[XZ:%.*]] = icmp ne i32 [[X:%.*]], 0
184; CHECK-NEXT:    [[YZ:%.*]] = icmp ne i32 [[Y:%.*]], 0
185; CHECK-NEXT:    [[Z:%.*]] = select i1 [[XZ]], i1 true, i1 [[YZ]]
186; CHECK-NEXT:    br i1 [[Z]], label [[NOPE:%.*]], label [[BOTH_ZERO:%.*]]
187; CHECK:       both_zero:
188; CHECK-NEXT:    call void @foo(i1 false)
189; CHECK-NEXT:    call void @foo(i1 false)
190; CHECK-NEXT:    call void @bar(i32 0)
191; CHECK-NEXT:    call void @bar(i32 0)
192; CHECK-NEXT:    ret void
193; CHECK:       nope:
194; CHECK-NEXT:    call void @foo(i1 true)
195; CHECK-NEXT:    ret void
196;
197  %xz = icmp ne i32 %x, 0
198  %yz = icmp ne i32 %y, 0
199  %z = select i1 %xz, i1 true, i1 %yz
200  br i1 %z, label %nope, label %both_zero
201both_zero:
202  call void @foo(i1 %xz)
203  call void @foo(i1 %yz)
204  call void @bar(i32 %x)
205  call void @bar(i32 %y)
206  ret void
207nope:
208  call void @foo(i1 %z)
209  ret void
210}
211
212define void @test4(i1 %b, i32 %x) {
213; CHECK-LABEL: @test4(
214; CHECK-NEXT:    br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]]
215; CHECK:       sw:
216; CHECK-NEXT:    switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
217; CHECK-NEXT:      i32 0, label [[CASE0:%.*]]
218; CHECK-NEXT:      i32 1, label [[CASE1:%.*]]
219; CHECK-NEXT:      i32 2, label [[CASE0]]
220; CHECK-NEXT:      i32 3, label [[CASE3]]
221; CHECK-NEXT:      i32 4, label [[DEFAULT]]
222; CHECK-NEXT:    ]
223; CHECK:       default:
224; CHECK-NEXT:    call void @bar(i32 [[X]])
225; CHECK-NEXT:    ret void
226; CHECK:       case0:
227; CHECK-NEXT:    call void @bar(i32 [[X]])
228; CHECK-NEXT:    ret void
229; CHECK:       case1:
230; CHECK-NEXT:    call void @bar(i32 1)
231; CHECK-NEXT:    ret void
232; CHECK:       case3:
233; CHECK-NEXT:    call void @bar(i32 [[X]])
234; CHECK-NEXT:    ret void
235;
236  br i1 %b, label %sw, label %case3
237sw:
238  switch i32 %x, label %default [
239  i32 0, label %case0
240  i32 1, label %case1
241  i32 2, label %case0
242  i32 3, label %case3
243  i32 4, label %default
244  ]
245default:
246  call void @bar(i32 %x)
247  ret void
248case0:
249  call void @bar(i32 %x)
250  ret void
251case1:
252  call void @bar(i32 %x)
253  ret void
254case3:
255  call void @bar(i32 %x)
256  ret void
257}
258
259define i1 @test5(i32 %x, i32 %y) {
260; CHECK-LABEL: @test5(
261; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
262; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
263; CHECK:       same:
264; CHECK-NEXT:    ret i1 false
265; CHECK:       different:
266; CHECK-NEXT:    ret i1 false
267;
268  %cmp = icmp eq i32 %x, %y
269  br i1 %cmp, label %same, label %different
270
271same:
272  %cmp2 = icmp ne i32 %x, %y
273  ret i1 %cmp2
274
275different:
276  %cmp3 = icmp eq i32 %x, %y
277  ret i1 %cmp3
278}
279
280define i1 @test6(i32 %x, i32 %y) {
281; CHECK-LABEL: @test6(
282; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[X:%.*]], [[Y:%.*]]
283; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]]
284; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
285; CHECK:       same:
286; CHECK-NEXT:    ret i1 false
287; CHECK:       different:
288; CHECK-NEXT:    ret i1 false
289;
290  %cmp2 = icmp ne i32 %x, %y
291  %cmp = icmp eq i32 %x, %y
292  %cmp3 = icmp eq i32 %x, %y
293  br i1 %cmp, label %same, label %different
294
295same:
296  ret i1 %cmp2
297
298different:
299  ret i1 %cmp3
300}
301
302define i1 @test6_fp(float %x, float %y) {
303; CHECK-LABEL: @test6_fp(
304; CHECK-NEXT:    [[CMP2:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]]
305; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[X]], [[Y]]
306; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
307; CHECK:       same:
308; CHECK-NEXT:    ret i1 false
309; CHECK:       different:
310; CHECK-NEXT:    ret i1 false
311;
312  %cmp2 = fcmp une float %x, %y
313  %cmp = fcmp oeq float %x, %y
314  %cmp3 = fcmp oeq float  %x, %y
315  br i1 %cmp, label %same, label %different
316
317same:
318  ret i1 %cmp2
319
320different:
321  ret i1 %cmp3
322}
323
324define i1 @test7(i32 %x, i32 %y) {
325; CHECK-LABEL: @test7(
326; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
327; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
328; CHECK:       same:
329; CHECK-NEXT:    ret i1 false
330; CHECK:       different:
331; CHECK-NEXT:    ret i1 false
332;
333  %cmp = icmp sgt i32 %x, %y
334  br i1 %cmp, label %same, label %different
335
336same:
337  %cmp2 = icmp sle i32 %x, %y
338  ret i1 %cmp2
339
340different:
341  %cmp3 = icmp sgt i32 %x, %y
342  ret i1 %cmp3
343}
344
345define i1 @test7_fp(float %x, float %y) {
346; CHECK-LABEL: @test7_fp(
347; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
348; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
349; CHECK:       same:
350; CHECK-NEXT:    ret i1 false
351; CHECK:       different:
352; CHECK-NEXT:    ret i1 false
353;
354  %cmp = fcmp ogt float %x, %y
355  br i1 %cmp, label %same, label %different
356
357same:
358  %cmp2 = fcmp ule float %x, %y
359  ret i1 %cmp2
360
361different:
362  %cmp3 = fcmp ogt float %x, %y
363  ret i1 %cmp3
364}
365
366define i1 @test8(i32 %x, i32 %y) {
367; CHECK-LABEL: @test8(
368; CHECK-NEXT:    [[CMP2:%.*]] = icmp sle i32 [[X:%.*]], [[Y:%.*]]
369; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
370; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
371; CHECK:       same:
372; CHECK-NEXT:    ret i1 false
373; CHECK:       different:
374; CHECK-NEXT:    ret i1 false
375;
376  %cmp2 = icmp sle i32 %x, %y
377  %cmp = icmp sgt i32 %x, %y
378  %cmp3 = icmp sgt i32 %x, %y
379  br i1 %cmp, label %same, label %different
380
381same:
382  ret i1 %cmp2
383
384different:
385  ret i1 %cmp3
386}
387
388define i1 @test8_fp(float %x, float %y) {
389; CHECK-LABEL: @test8_fp(
390; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
391; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[X]], [[Y]]
392; CHECK-NEXT:    br i1 [[CMP]], label [[SAME:%.*]], label [[DIFFERENT:%.*]]
393; CHECK:       same:
394; CHECK-NEXT:    ret i1 false
395; CHECK:       different:
396; CHECK-NEXT:    ret i1 false
397;
398  %cmp2 = fcmp ule float %x, %y
399  %cmp = fcmp ogt float %x, %y
400  %cmp3 = fcmp ogt float %x, %y
401  br i1 %cmp, label %same, label %different
402
403same:
404  ret i1 %cmp2
405
406different:
407  ret i1 %cmp3
408}
409
410; PR1768
411define i32 @test9(i32 %i, i32 %j) {
412; CHECK-LABEL: @test9(
413; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
414; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
415; CHECK:       cond_true:
416; CHECK-NEXT:    ret i32 0
417; CHECK:       ret:
418; CHECK-NEXT:    ret i32 5
419;
420  %cmp = icmp eq i32 %i, %j
421  br i1 %cmp, label %cond_true, label %ret
422
423cond_true:
424  %diff = sub i32 %i, %j
425  ret i32 %diff
426
427ret:
428  ret i32 5
429}
430
431; PR1768
432define i32 @test10(i32 %j, i32 %i) {
433; CHECK-LABEL: @test10(
434; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], [[J:%.*]]
435; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[RET:%.*]]
436; CHECK:       cond_true:
437; CHECK-NEXT:    ret i32 0
438; CHECK:       ret:
439; CHECK-NEXT:    ret i32 5
440;
441  %cmp = icmp eq i32 %i, %j
442  br i1 %cmp, label %cond_true, label %ret
443
444cond_true:
445  %diff = sub i32 %i, %j
446  ret i32 %diff
447
448ret:
449  ret i32 5
450}
451
452declare i32 @yogibar()
453
454define i32 @test11(i32 %x) {
455; CHECK-LABEL: @test11(
456; CHECK-NEXT:    [[V0:%.*]] = call i32 @yogibar()
457; CHECK-NEXT:    [[V1:%.*]] = call i32 @yogibar()
458; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[V0]], [[V1]]
459; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[NEXT:%.*]]
460; CHECK:       cond_true:
461; CHECK-NEXT:    ret i32 [[V0]]
462; CHECK:       next:
463; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[X:%.*]], [[V0]]
464; CHECK-NEXT:    br i1 [[CMP2]], label [[COND_TRUE2:%.*]], label [[NEXT2:%.*]]
465; CHECK:       cond_true2:
466; CHECK-NEXT:    ret i32 [[X]]
467; CHECK:       next2:
468; CHECK-NEXT:    ret i32 0
469;
470  %v0 = call i32 @yogibar()
471  %v1 = call i32 @yogibar()
472  %cmp = icmp eq i32 %v0, %v1
473  br i1 %cmp, label %cond_true, label %next
474
475cond_true:
476  ret i32 %v1
477
478next:
479  %cmp2 = icmp eq i32 %x, %v0
480  br i1 %cmp2, label %cond_true2, label %next2
481
482cond_true2:
483  ret i32 %v0
484
485next2:
486  ret i32 0
487}
488
489define i32 @test12(i32 %x) {
490; CHECK-LABEL: @test12(
491; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0
492; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
493; CHECK:       cond_true:
494; CHECK-NEXT:    br label [[RET:%.*]]
495; CHECK:       cond_false:
496; CHECK-NEXT:    br label [[RET]]
497; CHECK:       ret:
498; CHECK-NEXT:    [[RES:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ [[X]], [[COND_FALSE]] ]
499; CHECK-NEXT:    ret i32 [[RES]]
500;
501  %cmp = icmp eq i32 %x, 0
502  br i1 %cmp, label %cond_true, label %cond_false
503
504cond_true:
505  br label %ret
506
507cond_false:
508  br label %ret
509
510ret:
511  %res = phi i32 [ %x, %cond_true ], [ %x, %cond_false ]
512  ret i32 %res
513}
514
515; On the path from entry->if->end we know that ptr1==ptr2, so we can determine
516; that gep2 does not alias ptr1 on that path (as it would require that
517; ptr2==ptr2+2), so we can perform PRE of the load.
518define i32 @test13(ptr %ptr1, ptr %ptr2) {
519; CHECK-LABEL: @test13(
520; CHECK-NEXT:  entry:
521; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr i32, ptr [[PTR2:%.*]], i32 1
522; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr i32, ptr [[PTR2]], i32 2
523; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[PTR1:%.*]], [[PTR2]]
524; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
525; CHECK:       if:
526; CHECK-NEXT:    [[VAL1:%.*]] = load i32, ptr [[GEP2]], align 4
527; CHECK-NEXT:    br label [[END]]
528; CHECK:       end:
529; CHECK-NEXT:    [[PHI1:%.*]] = phi ptr [ [[PTR1]], [[IF]] ], [ [[GEP1]], [[ENTRY:%.*]] ]
530; CHECK-NEXT:    [[PHI2:%.*]] = phi i32 [ [[VAL1]], [[IF]] ], [ 0, [[ENTRY]] ]
531; CHECK-NEXT:    store i32 0, ptr [[PHI1]], align 4
532; CHECK-NEXT:    [[VAL2:%.*]] = load i32, ptr [[GEP2]], align 4
533; CHECK-NEXT:    [[RET:%.*]] = add i32 [[PHI2]], [[VAL2]]
534; CHECK-NEXT:    ret i32 [[RET]]
535;
536entry:
537  %gep1 = getelementptr i32, ptr %ptr2, i32 1
538  %gep2 = getelementptr i32, ptr %ptr2, i32 2
539  %cmp = icmp eq ptr %ptr1, %ptr2
540  br i1 %cmp, label %if, label %end
541
542
543if:
544  %val1 = load i32, ptr %gep2, align 4
545  br label %end
546
547end:
548  %phi1 = phi ptr [ %ptr1, %if ], [ %gep1, %entry ]
549  %phi2 = phi i32 [ %val1, %if ], [ 0, %entry ]
550  store i32 0, ptr %phi1, align 4
551  %val2 = load i32, ptr %gep2, align 4
552  %ret = add i32 %phi2, %val2
553  ret i32 %ret
554}
555
556define void @test14(ptr %ptr1, ptr noalias %ptr2, i1 %b1, i1 %b2) {
557; CHECK-LABEL: @test14(
558; CHECK-NEXT:  entry:
559; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[PTR1:%.*]], i32 1
560; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[PTR1]], i32 2
561; CHECK-NEXT:    br label [[LOOP:%.*]]
562; CHECK:       loop:
563; CHECK-NEXT:    br i1 [[B1:%.*]], label [[LOOP_IF1_CRIT_EDGE:%.*]], label [[THEN:%.*]]
564; CHECK:       loop.if1_crit_edge:
565; CHECK-NEXT:    [[VAL2_PRE:%.*]] = load i32, ptr [[GEP2]], align 4
566; CHECK-NEXT:    br label [[IF1:%.*]]
567; CHECK:       if1:
568; CHECK-NEXT:    [[VAL2:%.*]] = phi i32 [ [[VAL2_PRE]], [[LOOP_IF1_CRIT_EDGE]] ], [ [[VAL3:%.*]], [[LOOP_END:%.*]] ]
569; CHECK-NEXT:    store i32 [[VAL2]], ptr [[GEP2]], align 4
570; CHECK-NEXT:    store i32 0, ptr [[GEP1]], align 4
571; CHECK-NEXT:    br label [[THEN]]
572; CHECK:       then:
573; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[PTR2:%.*]]
574; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_END]], label [[IF2:%.*]]
575; CHECK:       if2:
576; CHECK-NEXT:    br label [[LOOP_END]]
577; CHECK:       loop.end:
578; CHECK-NEXT:    [[PHI3:%.*]] = phi ptr [ [[GEP2]], [[THEN]] ], [ [[PTR1]], [[IF2]] ]
579; CHECK-NEXT:    [[VAL3]] = load i32, ptr [[GEP2]], align 4
580; CHECK-NEXT:    store i32 [[VAL3]], ptr [[PHI3]], align 4
581; CHECK-NEXT:    br i1 [[B2:%.*]], label [[LOOP]], label [[IF1]]
582;
583entry:
584  %gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1
585  %gep2 = getelementptr inbounds i32, ptr %ptr1, i32 2
586  br label %loop
587
588loop:
589  %phi1 = phi ptr [ %gep3, %loop.end ], [ %gep1, %entry ]
590  br i1 %b1, label %if1, label %then
591
592
593if1:
594  %val2 = load i32, ptr %gep2, align 4
595  store i32 %val2, ptr %gep2, align 4
596  store i32 0, ptr %phi1, align 4
597  br label %then
598
599then:
600  %cmp = icmp eq ptr %gep2, %ptr2
601  br i1 %cmp, label %loop.end, label %if2
602
603if2:
604  br label %loop.end
605
606loop.end:
607  %phi3 = phi ptr [ %gep2, %then ], [ %ptr1, %if2 ]
608  %val3 = load i32, ptr %gep2, align 4
609  store i32 %val3, ptr %phi3, align 4
610  %gep3 = getelementptr inbounds i32, ptr %ptr1, i32 1
611  br i1 %b2, label %loop, label %if1
612}
613
614; Make sure that the call to use_ptr does not have %p1
615define void @single_phi1(ptr %p0, ptr %p1, i8 %s) {
616; CHECK-LABEL: @single_phi1(
617; CHECK-NEXT:  entry:
618; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8
619; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]]
620; CHECK-NEXT:    br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]]
621; CHECK:       bb1:
622; CHECK-NEXT:    switch i8 [[S:%.*]], label [[BB2:%.*]] [
623; CHECK-NEXT:      i8 0, label [[BB1]]
624; CHECK-NEXT:      i8 1, label [[BB3:%.*]]
625; CHECK-NEXT:    ]
626; CHECK:       bb2:
627; CHECK-NEXT:    unreachable
628; CHECK:       bb3:
629; CHECK-NEXT:    br label [[BB4]]
630; CHECK:       bb4:
631; CHECK-NEXT:    call void @use_bool(i1 [[CMP1]])
632; CHECK-NEXT:    call void @use_ptr(ptr [[P2]])
633; CHECK-NEXT:    ret void
634;
635entry:
636  %p2 = load ptr, ptr %p0, align 8
637  %cmp1 = icmp eq ptr %p2, %p1
638  br i1 %cmp1, label %bb4, label %bb1
639
640bb1:
641  switch i8 %s, label %bb2 [
642  i8 0, label %bb1
643  i8 1, label %bb3
644  ]
645
646bb2:
647  unreachable
648
649bb3:
650  br label %bb4
651
652bb4:
653  %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb3 ]
654  %cmp2 = icmp eq ptr %phi1, %p1
655  call void @use_bool(i1 %cmp2)
656  call void @use_ptr(ptr %phi1)
657  ret void
658}
659
660define void @single_phi2(ptr %p0, ptr %p1, i8 %s) {
661; CHECK-LABEL: @single_phi2(
662; CHECK-NEXT:  entry:
663; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8
664; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]]
665; CHECK-NEXT:    br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]]
666; CHECK:       bb1:
667; CHECK-NEXT:    switch i8 [[S:%.*]], label [[BB2:%.*]] [
668; CHECK-NEXT:      i8 0, label [[BB1]]
669; CHECK-NEXT:      i8 1, label [[BB3:%.*]]
670; CHECK-NEXT:    ]
671; CHECK:       bb2:
672; CHECK-NEXT:    br label [[BB4]]
673; CHECK:       bb3:
674; CHECK-NEXT:    br label [[BB4]]
675; CHECK:       bb4:
676; CHECK-NEXT:    call void @use_bool(i1 [[CMP1]])
677; CHECK-NEXT:    call void @use_ptr(ptr [[P2]])
678; CHECK-NEXT:    ret void
679;
680entry:
681  %p2 = load ptr, ptr %p0, align 8
682  %cmp1 = icmp eq ptr %p2, %p1
683  br i1 %cmp1, label %bb4, label %bb1
684
685bb1:
686  switch i8 %s, label %bb2 [
687  i8 0, label %bb1
688  i8 1, label %bb3
689  ]
690
691bb2:
692  br label %bb4
693
694bb3:
695  br label %bb4
696
697bb4:
698  %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ %p2, %bb3 ]
699  %cmp2 = icmp eq ptr %phi1, %p1
700  call void @use_bool(i1 %cmp2)
701  call void @use_ptr(ptr %phi1)
702  ret void
703}
704
705define void @multiple_phi1(ptr %p0, ptr %p1, i8 %s) {
706; CHECK-LABEL: @multiple_phi1(
707; CHECK-NEXT:  entry:
708; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8
709; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]]
710; CHECK-NEXT:    br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]]
711; CHECK:       bb1:
712; CHECK-NEXT:    switch i8 [[S:%.*]], label [[BB2:%.*]] [
713; CHECK-NEXT:      i8 0, label [[BB1]]
714; CHECK-NEXT:      i8 1, label [[BB3:%.*]]
715; CHECK-NEXT:    ]
716; CHECK:       bb2:
717; CHECK-NEXT:    unreachable
718; CHECK:       bb3:
719; CHECK-NEXT:    br label [[BB4]]
720; CHECK:       bb4:
721; CHECK-NEXT:    call void @use_bool(i1 [[CMP1]])
722; CHECK-NEXT:    br label [[BB5:%.*]]
723; CHECK:       bb5:
724; CHECK-NEXT:    call void @use_ptr(ptr [[P2]])
725; CHECK-NEXT:    br label [[BB5]]
726;
727entry:
728  %p2 = load ptr, ptr %p0, align 8
729  %cmp1 = icmp eq ptr %p2, %p1
730  br i1 %cmp1, label %bb4, label %bb1
731
732bb1:
733  switch i8 %s, label %bb2 [
734  i8 0, label %bb1
735  i8 1, label %bb3
736  ]
737
738bb2:
739  unreachable
740
741bb3:
742  br label %bb4
743
744bb4:
745  %phi1 = phi ptr [ %p2, %entry ], [ poison, %bb3 ]
746  %cmp2 = icmp eq ptr %phi1, %p1
747  call void @use_bool(i1 %cmp2)
748  br label %bb5
749
750bb5:
751  %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ]
752  call void @use_ptr(ptr %phi2)
753  br label %bb5
754}
755
756define void @multiple_phi2(ptr %p0, ptr %p1, i8 %s) {
757; CHECK-LABEL: @multiple_phi2(
758; CHECK-NEXT:  entry:
759; CHECK-NEXT:    [[P2:%.*]] = load ptr, ptr [[P0:%.*]], align 8
760; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq ptr [[P2]], [[P1:%.*]]
761; CHECK-NEXT:    br i1 [[CMP1]], label [[BB4:%.*]], label [[BB1:%.*]]
762; CHECK:       bb1:
763; CHECK-NEXT:    switch i8 [[S:%.*]], label [[BB2:%.*]] [
764; CHECK-NEXT:      i8 0, label [[BB1]]
765; CHECK-NEXT:      i8 1, label [[BB3:%.*]]
766; CHECK-NEXT:    ]
767; CHECK:       bb2:
768; CHECK-NEXT:    br label [[BB4]]
769; CHECK:       bb3:
770; CHECK-NEXT:    br label [[BB4]]
771; CHECK:       bb4:
772; CHECK-NEXT:    call void @use_bool(i1 [[CMP1]])
773; CHECK-NEXT:    br label [[BB5:%.*]]
774; CHECK:       bb5:
775; CHECK-NEXT:    call void @use_ptr(ptr [[P2]])
776; CHECK-NEXT:    br label [[BB5]]
777;
778entry:
779  %p2 = load ptr, ptr %p0, align 8
780  %cmp1 = icmp eq ptr %p2, %p1
781  br i1 %cmp1, label %bb4, label %bb1
782
783bb1:
784  switch i8 %s, label %bb2 [
785  i8 0, label %bb1
786  i8 1, label %bb3
787  ]
788
789bb2:
790  br label %bb4
791
792bb3:
793  br label %bb4
794
795bb4:
796  %phi1 = phi ptr [ %p2, %entry ], [ %p2, %bb2 ], [ poison, %bb3 ]
797  %cmp2 = icmp eq ptr %phi1, %p1
798  call void @use_bool(i1 %cmp2)
799  br label %bb5
800
801bb5:
802  %phi2 = phi ptr [ poison, %bb5 ], [ %phi1, %bb4 ]
803  call void @use_ptr(ptr %phi2)
804  br label %bb5
805}
806
807define void @select_same_obj(i1 %c, ptr %p, i64 %x) {
808; CHECK-LABEL: @select_same_obj(
809; CHECK-NEXT:  entry:
810; CHECK-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X:%.*]]
811; CHECK-NEXT:    [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P]], ptr [[P2]]
812; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]]
813; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]]
814; CHECK:       if:
815; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
816; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
817; CHECK-NEXT:    ret void
818; CHECK:       exit:
819; CHECK-NEXT:    ret void
820;
821entry:
822  %p2 = getelementptr i8, ptr %p, i64 %x
823  %p3 = select i1 %c, ptr %p, ptr %p2
824  %cmp = icmp eq ptr %p, %p3
825  br i1 %cmp, label %if, label %exit
826
827if:
828  call void @use_ptr(ptr %p)
829  call void @use_ptr(ptr %p3)
830  ret void
831
832exit:
833  ret void
834}
835
836define void @select_different_obj(i1 %c, ptr %p, ptr %p2) {
837; CHECK-LABEL: @select_different_obj(
838; CHECK-NEXT:  entry:
839; CHECK-NEXT:    [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]]
840; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]]
841; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]]
842; CHECK:       if:
843; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
844; CHECK-NEXT:    call void @use_ptr(ptr [[P3]])
845; CHECK-NEXT:    ret void
846; CHECK:       exit:
847; CHECK-NEXT:    ret void
848;
849entry:
850  %p3 = select i1 %c, ptr %p, ptr %p2
851  %cmp = icmp eq ptr %p, %p3
852  br i1 %cmp, label %if, label %exit
853
854if:
855  call void @use_ptr(ptr %p)
856  call void @use_ptr(ptr %p3)
857  ret void
858
859exit:
860  ret void
861}
862
863define void @select_same_obj_is_select(i1 %c, ptr %p, ptr %p2, i64 %x) {
864; CHECK-LABEL: @select_same_obj_is_select(
865; CHECK-NEXT:  entry:
866; CHECK-NEXT:    [[P3:%.*]] = select i1 [[C:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]]
867; CHECK-NEXT:    [[P4:%.*]] = getelementptr i8, ptr [[P3]], i64 [[X:%.*]]
868; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P3]], [[P4]]
869; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[EXIT:%.*]]
870; CHECK:       if:
871; CHECK-NEXT:    call void @use_ptr(ptr [[P3]])
872; CHECK-NEXT:    call void @use_ptr(ptr [[P3]])
873; CHECK-NEXT:    ret void
874; CHECK:       exit:
875; CHECK-NEXT:    ret void
876;
877entry:
878  %p3 = select i1 %c, ptr %p, ptr %p2
879  %p4 = getelementptr i8, ptr %p3, i64 %x
880  %cmp = icmp eq ptr %p3, %p4
881  br i1 %cmp, label %if, label %exit
882
883if:
884  call void @use_ptr(ptr %p3)
885  call void @use_ptr(ptr %p4)
886  ret void
887
888exit:
889  ret void
890}
891
892define void @phi_same_obj(i1 %c, ptr %p, i64 %x) {
893; CHECK-LABEL: @phi_same_obj(
894; CHECK-NEXT:  entry:
895; CHECK-NEXT:    [[P2:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[X:%.*]]
896; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
897; CHECK:       if:
898; CHECK-NEXT:    br label [[JOIN]]
899; CHECK:       join:
900; CHECK-NEXT:    [[P3:%.*]] = phi ptr [ [[P]], [[IF]] ], [ [[P2]], [[ENTRY:%.*]] ]
901; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]]
902; CHECK-NEXT:    br i1 [[CMP]], label [[IF2:%.*]], label [[EXIT:%.*]]
903; CHECK:       if2:
904; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
905; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
906; CHECK-NEXT:    ret void
907; CHECK:       exit:
908; CHECK-NEXT:    ret void
909;
910entry:
911  %p2 = getelementptr i8, ptr %p, i64 %x
912  br i1 %c, label %if, label %join
913
914if:
915  br label %join
916
917join:
918  %p3 = phi ptr [ %p, %if ], [ %p2, %entry ]
919  %cmp = icmp eq ptr %p, %p3
920  br i1 %cmp, label %if2, label %exit
921
922if2:
923  call void @use_ptr(ptr %p)
924  call void @use_ptr(ptr %p3)
925  ret void
926
927exit:
928  ret void
929}
930
931define void @phi_different_obj(i1 %c, ptr %p, ptr %p2) {
932; CHECK-LABEL: @phi_different_obj(
933; CHECK-NEXT:  entry:
934; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
935; CHECK:       if:
936; CHECK-NEXT:    br label [[JOIN]]
937; CHECK:       join:
938; CHECK-NEXT:    [[P3:%.*]] = phi ptr [ [[P:%.*]], [[IF]] ], [ [[P2:%.*]], [[ENTRY:%.*]] ]
939; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P]], [[P3]]
940; CHECK-NEXT:    br i1 [[CMP]], label [[IF2:%.*]], label [[EXIT:%.*]]
941; CHECK:       if2:
942; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
943; CHECK-NEXT:    call void @use_ptr(ptr [[P3]])
944; CHECK-NEXT:    ret void
945; CHECK:       exit:
946; CHECK-NEXT:    ret void
947;
948entry:
949  br i1 %c, label %if, label %join
950
951if:
952  br label %join
953
954join:
955  %p3 = phi ptr [ %p, %if ], [ %p2, %entry ]
956  %cmp = icmp eq ptr %p, %p3
957  br i1 %cmp, label %if2, label %exit
958
959if2:
960  call void @use_ptr(ptr %p)
961  call void @use_ptr(ptr %p3)
962  ret void
963
964exit:
965  ret void
966}
967
968define void @phi_same_obj_cycle(i1 %c, ptr %p, i64 %x) {
969; CHECK-LABEL: @phi_same_obj_cycle(
970; CHECK-NEXT:  entry:
971; CHECK-NEXT:    br label [[LOOP:%.*]]
972; CHECK:       loop:
973; CHECK-NEXT:    [[P_IV:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
974; CHECK-NEXT:    [[P_NEXT]] = getelementptr i8, ptr [[P_IV]], i64 [[X:%.*]]
975; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P_IV]], [[P]]
976; CHECK-NEXT:    br i1 [[CMP]], label [[IF:%.*]], label [[LOOP_LATCH]]
977; CHECK:       if:
978; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
979; CHECK-NEXT:    call void @use_ptr(ptr [[P]])
980; CHECK-NEXT:    br label [[LOOP_LATCH]]
981; CHECK:       loop.latch:
982; CHECK-NEXT:    br label [[LOOP]]
983;
984entry:
985  br label %loop
986
987loop:
988  %p.iv = phi ptr [ %p, %entry ], [ %p.next, %loop.latch ]
989  %p.next = getelementptr i8, ptr %p.iv, i64 %x
990  %cmp = icmp eq ptr %p.iv, %p
991  br i1 %cmp, label %if, label %loop.latch
992
993if:
994  call void @use_ptr(ptr %p.iv)
995  call void @use_ptr(ptr %p)
996  br label %loop.latch
997
998loop.latch:
999  br label %loop
1000}
1001
1002declare void @use_bool(i1)
1003declare void @use_ptr(ptr)
1004