xref: /llvm-project/llvm/test/Transforms/InstCombine/binop-phi-operands.ll (revision 2fda200cd8c15773c640b943c28b94fcdb874646)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(i32)
5declare void @sideeffect()
6
7; negative test (but we could allow this?) - don't hoist to conditional predecessor block
8
9define i32 @add_const_incoming0_speculative(i1 %b, i32 %x, i32 %y) {
10; CHECK-LABEL: @add_const_incoming0_speculative(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
13; CHECK:       if:
14; CHECK-NEXT:    br label [[THEN]]
15; CHECK:       then:
16; CHECK-NEXT:    [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
17; CHECK-NEXT:    [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
18; CHECK-NEXT:    [[R:%.*]] = add i32 [[P0]], [[P1]]
19; CHECK-NEXT:    ret i32 [[R]]
20;
21entry:
22  br i1 %b, label %if, label %then
23
24if:
25  br label %then
26
27then:
28  %p0 = phi i32 [ 42, %if ], [ %x, %entry ]
29  %p1 = phi i32 [ 17, %if ], [ %y, %entry ]
30  %r = add i32 %p0, %p1
31  ret i32 %r
32}
33
34define i32 @add_const_incoming0_nonspeculative(i1 %b, i32 %x, i32 %y) {
35; CHECK-LABEL: @add_const_incoming0_nonspeculative(
36; CHECK-NEXT:  entry:
37; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
38; CHECK:       if:
39; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[X:%.*]], [[Y:%.*]]
40; CHECK-NEXT:    br label [[THEN]]
41; CHECK:       then:
42; CHECK-NEXT:    [[R:%.*]] = phi i32 [ 59, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ]
43; CHECK-NEXT:    ret i32 [[R]]
44;
45entry:
46  br i1 %b, label %if, label %then
47
48if:
49  br label %then
50
51then:
52  %p0 = phi i32 [ 42, %entry ], [ %x, %if ]
53  %p1 = phi i32 [ 17, %entry ], [ %y, %if ]
54  %r = add i32 %p0, %p1
55  ret i32 %r
56}
57
58; negative test (but we could allow this?) - don't hoist to conditional predecessor block
59
60define i32 @sub_const_incoming0(i1 %b, i32 %x, i32 %y) {
61; CHECK-LABEL: @sub_const_incoming0(
62; CHECK-NEXT:  entry:
63; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
64; CHECK:       if:
65; CHECK-NEXT:    br label [[THEN]]
66; CHECK:       then:
67; CHECK-NEXT:    [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
68; CHECK-NEXT:    [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
69; CHECK-NEXT:    [[R:%.*]] = sub i32 [[P1]], [[P0]]
70; CHECK-NEXT:    ret i32 [[R]]
71;
72entry:
73  br i1 %b, label %if, label %then
74
75if:
76  br label %then
77
78then:
79  %p0 = phi i32 [ 42, %if ], [ %x, %entry ]
80  %p1 = phi i32 [ 17, %if ], [ %y, %entry ]
81  %r = sub i32 %p1, %p0
82  ret i32 %r
83}
84
85define i32 @sub_const_incoming1(i1 %b, i32 %x, i32 %y) {
86; CHECK-LABEL: @sub_const_incoming1(
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
89; CHECK:       if:
90; CHECK-NEXT:    [[TMP0:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
91; CHECK-NEXT:    br label [[THEN]]
92; CHECK:       then:
93; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[TMP0]], [[IF]] ], [ 25, [[ENTRY:%.*]] ]
94; CHECK-NEXT:    ret i32 [[R]]
95;
96entry:
97  br i1 %b, label %if, label %then
98
99if:
100  br label %then
101
102then:
103  %p0 = phi i32 [ %x, %if ], [ 42, %entry ]
104  %p1 = phi i32 [ %y, %if ], [ 17, %entry ]
105  %r = sub i32 %p0, %p1
106  ret i32 %r
107}
108
109define i8 @mul_const_incoming1(i1 %b, i8 %x, i8 %y) {
110; CHECK-LABEL: @mul_const_incoming1(
111; CHECK-NEXT:  entry:
112; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
113; CHECK:       if:
114; CHECK-NEXT:    [[TMP0:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]
115; CHECK-NEXT:    br label [[THEN]]
116; CHECK:       then:
117; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ -54, [[ENTRY:%.*]] ]
118; CHECK-NEXT:    ret i8 [[R]]
119;
120entry:
121  br i1 %b, label %if, label %then
122
123if:
124  br label %then
125
126then:
127  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
128  %p1 = phi i8 [ %y, %if ], [ 17, %entry ]
129  %r = mul i8 %p0, %p1
130  ret i8 %r
131}
132
133define i8 @and_const_incoming1(i1 %b, i8 %x, i8 %y) {
134; CHECK-LABEL: @and_const_incoming1(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
137; CHECK:       if:
138; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]
139; CHECK-NEXT:    br label [[THEN]]
140; CHECK:       then:
141; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 0, [[ENTRY:%.*]] ]
142; CHECK-NEXT:    ret i8 [[R]]
143;
144entry:
145  br i1 %b, label %if, label %then
146
147if:
148  br label %then
149
150then:
151  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
152  %p1 = phi i8 [ %y, %if ], [ 17, %entry ]
153  %r = and i8 %p0, %p1
154  ret i8 %r
155}
156
157define i8 @xor_const_incoming1(i1 %b, i8 %x, i8 %y) {
158; CHECK-LABEL: @xor_const_incoming1(
159; CHECK-NEXT:  entry:
160; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
161; CHECK:       if:
162; CHECK-NEXT:    [[TMP0:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]]
163; CHECK-NEXT:    br label [[THEN]]
164; CHECK:       then:
165; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 59, [[ENTRY:%.*]] ]
166; CHECK-NEXT:    ret i8 [[R]]
167;
168entry:
169  br i1 %b, label %if, label %then
170
171if:
172  br label %then
173
174then:
175  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
176  %p1 = phi i8 [ %y, %if ], [ 17, %entry ]
177  %r = xor i8 %p0, %p1
178  ret i8 %r
179}
180
181define i64 @or_const_incoming1(i1 %b, i64 %x, i64 %y) {
182; CHECK-LABEL: @or_const_incoming1(
183; CHECK-NEXT:  entry:
184; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
185; CHECK:       if:
186; CHECK-NEXT:    [[TMP0:%.*]] = or i64 [[X:%.*]], [[Y:%.*]]
187; CHECK-NEXT:    br label [[THEN]]
188; CHECK:       then:
189; CHECK-NEXT:    [[R:%.*]] = phi i64 [ [[TMP0]], [[IF]] ], [ 19, [[ENTRY:%.*]] ]
190; CHECK-NEXT:    ret i64 [[R]]
191;
192entry:
193  br i1 %b, label %if, label %then
194
195if:
196  br label %then
197
198then:
199  %p0 = phi i64 [ %x, %if ], [ 3, %entry ]
200  %p1 = phi i64 [ %y, %if ], [ 16, %entry ]
201  %r = or i64 %p0, %p1
202  ret i64 %r
203}
204
205define i64 @or_const_incoming01(i1 %b, i64 %x, i64 %y) {
206; CHECK-LABEL: @or_const_incoming01(
207; CHECK-NEXT:  entry:
208; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
209; CHECK:       if:
210; CHECK-NEXT:    [[TMP0:%.*]] = or i64 [[X:%.*]], [[Y:%.*]]
211; CHECK-NEXT:    br label [[THEN]]
212; CHECK:       then:
213; CHECK-NEXT:    [[R:%.*]] = phi i64 [ 19, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ]
214; CHECK-NEXT:    ret i64 [[R]]
215;
216entry:
217  br i1 %b, label %if, label %then
218
219if:
220  br label %then
221
222then:
223  %p0 = phi i64 [ 3, %entry ], [ %x, %if]
224  %p1 = phi i64 [ %y, %if ], [ 16, %entry ]
225  %r = or i64 %p0, %p1
226  ret i64 %r
227}
228
229define i64 @or_const_incoming10(i1 %b, i64 %x, i64 %y) {
230; CHECK-LABEL: @or_const_incoming10(
231; CHECK-NEXT:  entry:
232; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
233; CHECK:       if:
234; CHECK-NEXT:    [[TMP0:%.*]] = or i64 [[Y:%.*]], [[X:%.*]]
235; CHECK-NEXT:    br label [[THEN]]
236; CHECK:       then:
237; CHECK-NEXT:    [[R:%.*]] = phi i64 [ [[TMP0]], [[IF]] ], [ 19, [[ENTRY:%.*]] ]
238; CHECK-NEXT:    ret i64 [[R]]
239;
240entry:
241  br i1 %b, label %if, label %then
242
243if:
244  br label %then
245
246then:
247  %p0 = phi i64 [ %y, %if ], [ 16, %entry ]
248  %p1 = phi i64 [ 3, %entry ], [ %x, %if]
249  %r = or i64 %p0, %p1
250  ret i64 %r
251}
252
253; negative test (but we could allow this?) - don't hoist to conditional predecessor block
254
255define i8 @ashr_const_incoming0_speculative(i1 %b, i8 %x, i8 %y) {
256; CHECK-LABEL: @ashr_const_incoming0_speculative(
257; CHECK-NEXT:  entry:
258; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
259; CHECK:       if:
260; CHECK-NEXT:    br label [[THEN]]
261; CHECK:       then:
262; CHECK-NEXT:    [[P0:%.*]] = phi i8 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
263; CHECK-NEXT:    [[P1:%.*]] = phi i8 [ 3, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
264; CHECK-NEXT:    [[R:%.*]] = ashr i8 [[P0]], [[P1]]
265; CHECK-NEXT:    ret i8 [[R]]
266;
267entry:
268  br i1 %b, label %if, label %then
269
270if:
271  br label %then
272
273then:
274  %p0 = phi i8 [ 42, %if ], [ %x, %entry ]
275  %p1 = phi i8 [ 3, %if ], [ %y, %entry ]
276  %r = ashr i8 %p0, %p1
277  ret i8 %r
278}
279
280define i8 @ashr_const_incoming0(i1 %b, i8 %x, i8 %y) {
281; CHECK-LABEL: @ashr_const_incoming0(
282; CHECK-NEXT:  entry:
283; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
284; CHECK:       if:
285; CHECK-NEXT:    [[TMP0:%.*]] = ashr i8 [[X:%.*]], [[Y:%.*]]
286; CHECK-NEXT:    br label [[THEN]]
287; CHECK:       then:
288; CHECK-NEXT:    [[R:%.*]] = phi i8 [ 5, [[ENTRY:%.*]] ], [ [[TMP0]], [[IF]] ]
289; CHECK-NEXT:    ret i8 [[R]]
290;
291entry:
292  br i1 %b, label %if, label %then
293
294if:
295  br label %then
296
297then:
298  %p0 = phi i8 [ 42, %entry ], [ %x, %if ]
299  %p1 = phi i8 [ 3, %entry ], [ %y, %if ]
300  %r = ashr i8 %p0, %p1
301  ret i8 %r
302}
303
304define i8 @lshr_const_incoming1(i1 %b, i8 %x, i8 %y) {
305; CHECK-LABEL: @lshr_const_incoming1(
306; CHECK-NEXT:  entry:
307; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
308; CHECK:       if:
309; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]]
310; CHECK-NEXT:    br label [[THEN]]
311; CHECK:       then:
312; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 5, [[ENTRY:%.*]] ]
313; CHECK-NEXT:    ret i8 [[R]]
314;
315entry:
316  br i1 %b, label %if, label %then
317
318if:
319  br label %then
320
321then:
322  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
323  %p1 = phi i8 [ %y, %if ], [ 3, %entry ]
324  %r = lshr i8 %p0, %p1
325  ret i8 %r
326}
327
328define i8 @shl_const_incoming1(i1 %b, i8 %x, i8 %y) {
329; CHECK-LABEL: @shl_const_incoming1(
330; CHECK-NEXT:  entry:
331; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
332; CHECK:       if:
333; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]]
334; CHECK-NEXT:    br label [[THEN]]
335; CHECK:       then:
336; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 80, [[ENTRY:%.*]] ]
337; CHECK-NEXT:    ret i8 [[R]]
338;
339entry:
340  br i1 %b, label %if, label %then
341
342if:
343  br label %then
344
345then:
346  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
347  %p1 = phi i8 [ %y, %if ], [ 3, %entry ]
348  %r = shl nsw nuw i8 %p0, %p1
349  ret i8 %r
350}
351
352define i8 @sdiv_not_safe_to_speculate(i1 %b, i8 %x, i8 %y) {
353; CHECK-LABEL: @sdiv_not_safe_to_speculate(
354; CHECK-NEXT:  entry:
355; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
356; CHECK:       if:
357; CHECK-NEXT:    br label [[THEN]]
358; CHECK:       then:
359; CHECK-NEXT:    [[P0:%.*]] = phi i8 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
360; CHECK-NEXT:    [[P1:%.*]] = phi i8 [ 3, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
361; CHECK-NEXT:    [[R:%.*]] = sdiv exact i8 [[P0]], [[P1]]
362; CHECK-NEXT:    ret i8 [[R]]
363;
364entry:
365  br i1 %b, label %if, label %then
366
367if:
368  br label %then
369
370then:
371  %p0 = phi i8 [ 42, %if ], [ %x, %entry ]
372  %p1 = phi i8 [ 3, %if ], [ %y, %entry ]
373  %r = sdiv exact i8 %p0, %p1
374  ret i8 %r
375}
376
377define i8 @sdiv_const_incoming1(i1 %b, i8 %x, i8 %y) {
378; CHECK-LABEL: @sdiv_const_incoming1(
379; CHECK-NEXT:  entry:
380; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
381; CHECK:       if:
382; CHECK-NEXT:    [[TMP0:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
383; CHECK-NEXT:    br label [[THEN]]
384; CHECK:       then:
385; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ -2, [[ENTRY:%.*]] ]
386; CHECK-NEXT:    ret i8 [[R]]
387;
388entry:
389  br i1 %b, label %if, label %then
390
391if:
392  br label %then
393
394then:
395  %p0 = phi i8 [ %x, %if ], [ -42, %entry ]
396  %p1 = phi i8 [ %y, %if ], [ 17, %entry ]
397  %r = sdiv i8 %p0, %p1
398  ret i8 %r
399}
400
401define i8 @udiv_const_incoming1(i1 %b, i8 %x, i8 %y) {
402; CHECK-LABEL: @udiv_const_incoming1(
403; CHECK-NEXT:  entry:
404; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
405; CHECK:       if:
406; CHECK-NEXT:    [[TMP0:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]]
407; CHECK-NEXT:    br label [[THEN]]
408; CHECK:       then:
409; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 12, [[ENTRY:%.*]] ]
410; CHECK-NEXT:    ret i8 [[R]]
411;
412entry:
413  br i1 %b, label %if, label %then
414
415if:
416  br label %then
417
418then:
419  %p0 = phi i8 [ %x, %if ], [ -42, %entry ]
420  %p1 = phi i8 [ %y, %if ], [ 17, %entry ]
421  %r = udiv i8 %p0, %p1
422  ret i8 %r
423}
424
425define i8 @srem_const_incoming1(i1 %b, i8 %x, i8 %y) {
426; CHECK-LABEL: @srem_const_incoming1(
427; CHECK-NEXT:  entry:
428; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
429; CHECK:       if:
430; CHECK-NEXT:    [[TMP0:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]]
431; CHECK-NEXT:    br label [[THEN]]
432; CHECK:       then:
433; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 8, [[ENTRY:%.*]] ]
434; CHECK-NEXT:    ret i8 [[R]]
435;
436entry:
437  br i1 %b, label %if, label %then
438
439if:
440  br label %then
441
442then:
443  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
444  %p1 = phi i8 [ %y, %if ], [ -17, %entry ]
445  %r = srem i8 %p0, %p1
446  ret i8 %r
447}
448
449define i8 @urem_const_incoming1(i1 %b, i8 %x, i8 %y) {
450; CHECK-LABEL: @urem_const_incoming1(
451; CHECK-NEXT:  entry:
452; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
453; CHECK:       if:
454; CHECK-NEXT:    [[TMP0:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]
455; CHECK-NEXT:    br label [[THEN]]
456; CHECK:       then:
457; CHECK-NEXT:    [[R:%.*]] = phi i8 [ [[TMP0]], [[IF]] ], [ 42, [[ENTRY:%.*]] ]
458; CHECK-NEXT:    ret i8 [[R]]
459;
460entry:
461  br i1 %b, label %if, label %then
462
463if:
464  br label %then
465
466then:
467  %p0 = phi i8 [ %x, %if ], [ 42, %entry ]
468  %p1 = phi i8 [ %y, %if ], [ -17, %entry ]
469  %r = urem i8 %p0, %p1
470  ret i8 %r
471}
472
473define float @fmul_const_incoming1(i1 %b, float %x, float %y) {
474; CHECK-LABEL: @fmul_const_incoming1(
475; CHECK-NEXT:  entry:
476; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
477; CHECK:       if:
478; CHECK-NEXT:    [[TMP0:%.*]] = fmul float [[X:%.*]], [[Y:%.*]]
479; CHECK-NEXT:    br label [[THEN]]
480; CHECK:       then:
481; CHECK-NEXT:    [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 7.140000e+02, [[ENTRY:%.*]] ]
482; CHECK-NEXT:    ret float [[R]]
483;
484entry:
485  br i1 %b, label %if, label %then
486
487if:
488  br label %then
489
490then:
491  %p0 = phi float [ %x, %if ], [ 42.0, %entry ]
492  %p1 = phi float [ %y, %if ], [ 17.0, %entry ]
493  %r = fmul float %p0, %p1
494  ret float %r
495}
496
497define float @fadd_const_incoming1(i1 %b, float %x, float %y) {
498; CHECK-LABEL: @fadd_const_incoming1(
499; CHECK-NEXT:  entry:
500; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
501; CHECK:       if:
502; CHECK-NEXT:    [[TMP0:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]]
503; CHECK-NEXT:    br label [[THEN]]
504; CHECK:       then:
505; CHECK-NEXT:    [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 5.900000e+01, [[ENTRY:%.*]] ]
506; CHECK-NEXT:    ret float [[R]]
507;
508entry:
509  br i1 %b, label %if, label %then
510
511if:
512  br label %then
513
514then:
515  %p0 = phi float [ %x, %if ], [ 42.0, %entry ]
516  %p1 = phi float [ %y, %if ], [ 17.0, %entry ]
517  %r = fadd fast float %p0, %p1
518  ret float %r
519}
520
521define float @fsub_const_incoming1(i1 %b, float %x, float %y) {
522; CHECK-LABEL: @fsub_const_incoming1(
523; CHECK-NEXT:  entry:
524; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
525; CHECK:       if:
526; CHECK-NEXT:    [[TMP0:%.*]] = fsub nnan ninf float [[X:%.*]], [[Y:%.*]]
527; CHECK-NEXT:    br label [[THEN]]
528; CHECK:       then:
529; CHECK-NEXT:    [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 2.500000e+01, [[ENTRY:%.*]] ]
530; CHECK-NEXT:    ret float [[R]]
531;
532entry:
533  br i1 %b, label %if, label %then
534
535if:
536  br label %then
537
538then:
539  %p0 = phi float [ %x, %if ], [ 42.0, %entry ]
540  %p1 = phi float [ %y, %if ], [ 17.0, %entry ]
541  %r = fsub ninf nnan float %p0, %p1
542  ret float %r
543}
544
545define float @frem_const_incoming1(i1 %b, float %x, float %y) {
546; CHECK-LABEL: @frem_const_incoming1(
547; CHECK-NEXT:  entry:
548; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
549; CHECK:       if:
550; CHECK-NEXT:    [[TMP0:%.*]] = frem nsz float [[X:%.*]], [[Y:%.*]]
551; CHECK-NEXT:    br label [[THEN]]
552; CHECK:       then:
553; CHECK-NEXT:    [[R:%.*]] = phi float [ [[TMP0]], [[IF]] ], [ 8.000000e+00, [[ENTRY:%.*]] ]
554; CHECK-NEXT:    ret float [[R]]
555;
556entry:
557  br i1 %b, label %if, label %then
558
559if:
560  br label %then
561
562then:
563  %p0 = phi float [ %x, %if ], [ 42.0, %entry ]
564  %p1 = phi float [ %y, %if ], [ 17.0, %entry ]
565  %r = frem nsz float %p0, %p1
566  ret float %r
567}
568
569define i32 @add_const_incoming0_use1(i1 %b, i32 %x, i32 %y) {
570; CHECK-LABEL: @add_const_incoming0_use1(
571; CHECK-NEXT:  entry:
572; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
573; CHECK:       if:
574; CHECK-NEXT:    br label [[THEN]]
575; CHECK:       then:
576; CHECK-NEXT:    [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
577; CHECK-NEXT:    [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
578; CHECK-NEXT:    call void @use(i32 [[P0]])
579; CHECK-NEXT:    [[R:%.*]] = add i32 [[P0]], [[P1]]
580; CHECK-NEXT:    ret i32 [[R]]
581;
582entry:
583  br i1 %b, label %if, label %then
584
585if:
586  br label %then
587
588then:
589  %p0 = phi i32 [ 42, %if ], [ %x, %entry ]
590  %p1 = phi i32 [ 17, %if ], [ %y, %entry ]
591  call void @use(i32 %p0)
592  %r = add i32 %p0, %p1
593  ret i32 %r
594}
595
596define i32 @add_const_incoming0_use2(i1 %b, i32 %x, i32 %y) {
597; CHECK-LABEL: @add_const_incoming0_use2(
598; CHECK-NEXT:  entry:
599; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
600; CHECK:       if:
601; CHECK-NEXT:    br label [[THEN]]
602; CHECK:       then:
603; CHECK-NEXT:    [[P0:%.*]] = phi i32 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
604; CHECK-NEXT:    [[P1:%.*]] = phi i32 [ 17, [[IF]] ], [ [[Y:%.*]], [[ENTRY]] ]
605; CHECK-NEXT:    call void @use(i32 [[P1]])
606; CHECK-NEXT:    [[R:%.*]] = add i32 [[P0]], [[P1]]
607; CHECK-NEXT:    ret i32 [[R]]
608;
609entry:
610  br i1 %b, label %if, label %then
611
612if:
613  br label %then
614
615then:
616  %p0 = phi i32 [ 42, %if ], [ %x, %entry ]
617  %p1 = phi i32 [ 17, %if ], [ %y, %entry ]
618  call void @use(i32 %p1)
619  %r = add i32 %p0, %p1
620  ret i32 %r
621}
622
623define i64 @or_notconst_incoming(i1 %b, i64 %x, i64 %y) {
624; CHECK-LABEL: @or_notconst_incoming(
625; CHECK-NEXT:  entry:
626; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
627; CHECK:       if:
628; CHECK-NEXT:    br label [[THEN]]
629; CHECK:       then:
630; CHECK-NEXT:    [[P0:%.*]] = phi i64 [ 42, [[IF]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
631; CHECK-NEXT:    [[P1:%.*]] = phi i64 [ [[Y:%.*]], [[IF]] ], [ 43, [[ENTRY]] ]
632; CHECK-NEXT:    [[R:%.*]] = or i64 [[P0]], [[P1]]
633; CHECK-NEXT:    ret i64 [[R]]
634;
635entry:
636  br i1 %b, label %if, label %then
637
638if:
639  br label %then
640
641then:
642  %p0 = phi i64 [ 42, %if ], [ %x, %entry ]
643  %p1 = phi i64 [ %y, %if ], [ 43, %entry ]
644  %r = or i64 %p0, %p1
645  ret i64 %r
646}
647
648; The mul could be hoisted before the call that may not return
649; if we are ok with speculating a potentially expensive op.
650
651define i8 @mul_const_incoming0_speculatable(i1 %b, i8 %x, i8 %y) {
652; CHECK-LABEL: @mul_const_incoming0_speculatable(
653; CHECK-NEXT:  entry:
654; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
655; CHECK:       if:
656; CHECK-NEXT:    br label [[THEN]]
657; CHECK:       then:
658; CHECK-NEXT:    [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ]
659; CHECK-NEXT:    [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ]
660; CHECK-NEXT:    call void @sideeffect()
661; CHECK-NEXT:    [[R:%.*]] = mul i8 [[P0]], [[P1]]
662; CHECK-NEXT:    ret i8 [[R]]
663;
664entry:
665  br i1 %b, label %if, label %then
666
667if:
668  br label %then
669
670then:
671  %p0 = phi i8 [ 42, %entry ], [ %x, %if ]
672  %p1 = phi i8 [ 17, %entry ], [ %y, %if ]
673  call void @sideeffect()
674  %r = mul i8 %p0, %p1
675  ret i8 %r
676}
677
678; The udiv should never be hoisted before the call that may not return.
679
680define i8 @udiv_const_incoming0_not_speculatable(i1 %b, i8 %x, i8 %y) {
681; CHECK-LABEL: @udiv_const_incoming0_not_speculatable(
682; CHECK-NEXT:  entry:
683; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
684; CHECK:       if:
685; CHECK-NEXT:    br label [[THEN]]
686; CHECK:       then:
687; CHECK-NEXT:    [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ]
688; CHECK-NEXT:    [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ]
689; CHECK-NEXT:    call void @sideeffect()
690; CHECK-NEXT:    [[R:%.*]] = udiv i8 [[P0]], [[P1]]
691; CHECK-NEXT:    ret i8 [[R]]
692;
693entry:
694  br i1 %b, label %if, label %then
695
696if:
697  br label %then
698
699then:
700  %p0 = phi i8 [ 42, %entry ], [ %x, %if ]
701  %p1 = phi i8 [ 17, %entry ], [ %y, %if ]
702  call void @sideeffect()
703  %r = udiv i8 %p0, %p1
704  ret i8 %r
705}
706
707; TODO: It is ok to hoist the udiv even though it is not in the same block as the phis.
708
709define i8 @udiv_const_incoming0_different_block(i1 %b, i8 %x, i8 %y) {
710; CHECK-LABEL: @udiv_const_incoming0_different_block(
711; CHECK-NEXT:  entry:
712; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF:%.*]], label [[THEN:%.*]]
713; CHECK:       if:
714; CHECK-NEXT:    br label [[THEN]]
715; CHECK:       then:
716; CHECK-NEXT:    [[P0:%.*]] = phi i8 [ 42, [[ENTRY:%.*]] ], [ [[X:%.*]], [[IF]] ]
717; CHECK-NEXT:    [[P1:%.*]] = phi i8 [ 17, [[ENTRY]] ], [ [[Y:%.*]], [[IF]] ]
718; CHECK-NEXT:    br label [[END:%.*]]
719; CHECK:       end:
720; CHECK-NEXT:    [[R:%.*]] = udiv i8 [[P0]], [[P1]]
721; CHECK-NEXT:    ret i8 [[R]]
722;
723entry:
724  br i1 %b, label %if, label %then
725
726if:
727  br label %then
728
729then:
730  %p0 = phi i8 [ 42, %entry ], [ %x, %if ]
731  %p1 = phi i8 [ 17, %entry ], [ %y, %if ]
732  br label %end
733
734end:
735  %r = udiv i8 %p0, %p1
736  ret i8 %r
737}
738
739define { i64, i32 } @ParseRetVal(i1 %b, ptr %x) {
740; CHECK-LABEL: @ParseRetVal(
741; CHECK-NEXT:  entry:
742; CHECK-NEXT:    br i1 [[B:%.*]], label [[T:%.*]], label [[F:%.*]]
743; CHECK:       t:
744; CHECK-NEXT:    [[T4:%.*]] = tail call { i64, i32 } [[X:%.*]]()
745; CHECK-NEXT:    [[T5:%.*]] = extractvalue { i64, i32 } [[T4]], 0
746; CHECK-NEXT:    [[T6:%.*]] = extractvalue { i64, i32 } [[T4]], 1
747; CHECK-NEXT:    br label [[F]]
748; CHECK:       f:
749; CHECK-NEXT:    [[T16:%.*]] = phi i32 [ [[T6]], [[T]] ], [ 0, [[ENTRY:%.*]] ]
750; CHECK-NEXT:    [[T19:%.*]] = phi i64 [ [[T5]], [[T]] ], [ 0, [[ENTRY]] ]
751; CHECK-NEXT:    [[T20:%.*]] = insertvalue { i64, i32 } poison, i64 [[T19]], 0
752; CHECK-NEXT:    [[T21:%.*]] = insertvalue { i64, i32 } [[T20]], i32 [[T16]], 1
753; CHECK-NEXT:    ret { i64, i32 } [[T21]]
754;
755entry:
756  br i1 %b, label %t, label %f
757
758t:
759  %t4 = tail call { i64, i32 } %x()
760  %t5 = extractvalue { i64, i32 } %t4, 0
761  %t6 = extractvalue { i64, i32 } %t4, 1
762  %t7 = and i64 %t5, -4294967296
763  %t8 = and i64 %t5, 4294901760
764  %t9 = and i64 %t5, 65280
765  %t10 = and i64 %t5, 255
766  br label %f
767
768f:
769  %t12 = phi i64 [ %t10, %t ], [ 0, %entry ]
770  %t13 = phi i64 [ %t9, %t ], [ 0, %entry ]
771  %t14 = phi i64 [ %t8, %t ], [ 0, %entry ]
772  %t15 = phi i64 [ %t7, %t ], [ 0, %entry ]
773  %t16 = phi i32 [ %t6, %t ], [ 0, %entry ]
774  %t17 = or i64 %t13, %t12
775  %t18 = or i64 %t17, %t14
776  %t19 = or i64 %t18, %t15
777  %t20 = insertvalue { i64, i32 } poison, i64 %t19, 0
778  %t21 = insertvalue { i64, i32 } %t20, i32 %t16, 1
779  ret { i64, i32 } %t21
780}
781