xref: /llvm-project/llvm/test/Transforms/AggressiveInstCombine/funnel.ll (revision 7c802f985f2c28985c233d05b559a4e8c92110ae)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s
3
4define i32 @fshl(i32 %a, i32 %b, i32 %c) {
5; CHECK-LABEL: @fshl(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
8; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
9; CHECK:       fshbb:
10; CHECK-NEXT:    br label [[END]]
11; CHECK:       end:
12; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[B:%.*]]
13; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
14; CHECK-NEXT:    ret i32 [[TMP1]]
15;
16entry:
17  %cmp = icmp eq i32 %c, 0
18  br i1 %cmp, label %end, label %fshbb
19
20fshbb:
21  %sub = sub i32 32, %c
22  %shr = lshr i32 %b, %sub
23  %shl = shl i32 %a, %c
24  %or = or i32 %shr, %shl
25  br label %end
26
27end:
28  %cond = phi i32 [ %or, %fshbb ], [ %a, %entry ]
29  ret i32 %cond
30}
31
32define i32 @fshl_commute_phi(i32 %a, i32 %b, i32 %c) {
33; CHECK-LABEL: @fshl_commute_phi(
34; CHECK-NEXT:  entry:
35; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
36; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
37; CHECK:       fshbb:
38; CHECK-NEXT:    br label [[END]]
39; CHECK:       end:
40; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[B:%.*]]
41; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
42; CHECK-NEXT:    ret i32 [[TMP1]]
43;
44entry:
45  %cmp = icmp eq i32 %c, 0
46  br i1 %cmp, label %end, label %fshbb
47
48fshbb:
49  %sub = sub i32 32, %c
50  %shr = lshr i32 %b, %sub
51  %shl = shl i32 %a, %c
52  %or = or i32 %shr, %shl
53  br label %end
54
55end:
56  %cond = phi i32 [ %a, %entry ], [ %or, %fshbb ]
57  ret i32 %cond
58}
59
60define i32 @fshl_commute_or(i32 %a, i32 %b, i32 %c) {
61; CHECK-LABEL: @fshl_commute_or(
62; CHECK-NEXT:  entry:
63; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
64; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
65; CHECK:       fshbb:
66; CHECK-NEXT:    br label [[END]]
67; CHECK:       end:
68; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[B:%.*]]
69; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
70; CHECK-NEXT:    ret i32 [[TMP1]]
71;
72entry:
73  %cmp = icmp eq i32 %c, 0
74  br i1 %cmp, label %end, label %fshbb
75
76fshbb:
77  %sub = sub i32 32, %c
78  %shr = lshr i32 %b, %sub
79  %shl = shl i32 %a, %c
80  %or = or i32 %shl, %shr
81  br label %end
82
83end:
84  %cond = phi i32 [ %a, %entry ], [ %or, %fshbb ]
85  ret i32 %cond
86}
87
88; Verify that the intrinsic is inserted into a valid position.
89
90define i32 @fshl_insert_valid_location(i32 %a, i32 %b, i32 %c) {
91; CHECK-LABEL: @fshl_insert_valid_location(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
94; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
95; CHECK:       fshbb:
96; CHECK-NEXT:    br label [[END]]
97; CHECK:       end:
98; CHECK-NEXT:    [[OTHER:%.*]] = phi i32 [ 1, [[FSHBB]] ], [ 2, [[ENTRY:%.*]] ]
99; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[B:%.*]]
100; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[TMP0]], i32 [[C]])
101; CHECK-NEXT:    [[RES:%.*]] = or i32 [[TMP1]], [[OTHER]]
102; CHECK-NEXT:    ret i32 [[RES]]
103;
104entry:
105  %cmp = icmp eq i32 %c, 0
106  br i1 %cmp, label %end, label %fshbb
107
108fshbb:
109  %sub = sub i32 32, %c
110  %shr = lshr i32 %b, %sub
111  %shl = shl i32 %a, %c
112  %or = or i32 %shr, %shl
113  br label %end
114
115end:
116  %cond = phi i32 [ %or, %fshbb ], [ %a, %entry ]
117  %other = phi i32 [ 1, %fshbb ], [ 2, %entry ]
118  %res = or i32 %cond, %other
119  ret i32 %res
120}
121
122define i32 @fshr(i32 %a, i32 %b, i32 %c) {
123; CHECK-LABEL: @fshr(
124; CHECK-NEXT:  entry:
125; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
126; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
127; CHECK:       fshbb:
128; CHECK-NEXT:    br label [[END]]
129; CHECK:       end:
130; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[A:%.*]]
131; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
132; CHECK-NEXT:    ret i32 [[TMP1]]
133;
134entry:
135  %cmp = icmp eq i32 %c, 0
136  br i1 %cmp, label %end, label %fshbb
137
138fshbb:
139  %sub = sub i32 32, %c
140  %shl = shl i32 %a, %sub
141  %shr = lshr i32 %b, %c
142  %or = or i32 %shr, %shl
143  br label %end
144
145end:
146  %cond = phi i32 [ %or, %fshbb ], [ %b, %entry ]
147  ret i32 %cond
148}
149
150define i32 @fshr_commute_phi(i32 %a, i32 %b, i32 %c) {
151; CHECK-LABEL: @fshr_commute_phi(
152; CHECK-NEXT:  entry:
153; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
154; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
155; CHECK:       fshbb:
156; CHECK-NEXT:    br label [[END]]
157; CHECK:       end:
158; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[A:%.*]]
159; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
160; CHECK-NEXT:    ret i32 [[TMP1]]
161;
162entry:
163  %cmp = icmp eq i32 %c, 0
164  br i1 %cmp, label %end, label %fshbb
165
166fshbb:
167  %sub = sub i32 32, %c
168  %shl = shl i32 %a, %sub
169  %shr = lshr i32 %b, %c
170  %or = or i32 %shr, %shl
171  br label %end
172
173end:
174  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
175  ret i32 %cond
176}
177
178define i32 @fshr_commute_or(i32 %a, i32 %b, i32 %c) {
179; CHECK-LABEL: @fshr_commute_or(
180; CHECK-NEXT:  entry:
181; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
182; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
183; CHECK:       fshbb:
184; CHECK-NEXT:    br label [[END]]
185; CHECK:       end:
186; CHECK-NEXT:    [[TMP0:%.*]] = freeze i32 [[A:%.*]]
187; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.fshr.i32(i32 [[TMP0]], i32 [[B:%.*]], i32 [[C]])
188; CHECK-NEXT:    ret i32 [[TMP1]]
189;
190entry:
191  %cmp = icmp eq i32 %c, 0
192  br i1 %cmp, label %end, label %fshbb
193
194fshbb:
195  %sub = sub i32 32, %c
196  %shl = shl i32 %a, %sub
197  %shr = lshr i32 %b, %c
198  %or = or i32 %shl, %shr
199  br label %end
200
201end:
202  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
203  ret i32 %cond
204}
205
206; Negative test - non-power-of-2 might require urem expansion in the backend.
207
208define i12 @could_be_fshr_weird_type(i12 %a, i12 %b, i12 %c) {
209; CHECK-LABEL: @could_be_fshr_weird_type(
210; CHECK-NEXT:  entry:
211; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i12 [[C:%.*]], 0
212; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
213; CHECK:       fshbb:
214; CHECK-NEXT:    [[SUB:%.*]] = sub i12 12, [[C]]
215; CHECK-NEXT:    [[SHL:%.*]] = shl i12 [[A:%.*]], [[SUB]]
216; CHECK-NEXT:    [[SHR:%.*]] = lshr i12 [[B:%.*]], [[C]]
217; CHECK-NEXT:    [[OR:%.*]] = or i12 [[SHL]], [[SHR]]
218; CHECK-NEXT:    br label [[END]]
219; CHECK:       end:
220; CHECK-NEXT:    [[COND:%.*]] = phi i12 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
221; CHECK-NEXT:    ret i12 [[COND]]
222;
223entry:
224  %cmp = icmp eq i12 %c, 0
225  br i1 %cmp, label %end, label %fshbb
226
227fshbb:
228  %sub = sub i12 12, %c
229  %shl = shl i12 %a, %sub
230  %shr = lshr i12 %b, %c
231  %or = or i12 %shl, %shr
232  br label %end
233
234end:
235  %cond = phi i12 [ %b, %entry ], [ %or, %fshbb ]
236  ret i12 %cond
237}
238
239; Negative test - wrong phi ops.
240
241define i32 @not_fshr_1(i32 %a, i32 %b, i32 %c) {
242; CHECK-LABEL: @not_fshr_1(
243; CHECK-NEXT:  entry:
244; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
245; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
246; CHECK:       fshbb:
247; CHECK-NEXT:    [[SUB:%.*]] = sub i32 32, [[C]]
248; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
249; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
250; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
251; CHECK-NEXT:    br label [[END]]
252; CHECK:       end:
253; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[C]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
254; CHECK-NEXT:    ret i32 [[COND]]
255;
256entry:
257  %cmp = icmp eq i32 %c, 0
258  br i1 %cmp, label %end, label %fshbb
259
260fshbb:
261  %sub = sub i32 32, %c
262  %shl = shl i32 %a, %sub
263  %shr = lshr i32 %b, %c
264  %or = or i32 %shl, %shr
265  br label %end
266
267end:
268  %cond = phi i32 [ %c, %entry ], [ %or, %fshbb ]
269  ret i32 %cond
270}
271
272; Negative test - too many phi ops.
273
274define i32 @not_fshr_2(i32 %a, i32 %b, i32 %c, i32 %d) {
275; CHECK-LABEL: @not_fshr_2(
276; CHECK-NEXT:  entry:
277; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
278; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
279; CHECK:       fshbb:
280; CHECK-NEXT:    [[SUB:%.*]] = sub i32 32, [[C]]
281; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
282; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
283; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
284; CHECK-NEXT:    [[CMP42:%.*]] = icmp ugt i32 [[OR]], 42
285; CHECK-NEXT:    br i1 [[CMP42]], label [[END]], label [[BOGUS:%.*]]
286; CHECK:       bogus:
287; CHECK-NEXT:    br label [[END]]
288; CHECK:       end:
289; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ], [ [[D:%.*]], [[BOGUS]] ]
290; CHECK-NEXT:    ret i32 [[COND]]
291;
292entry:
293  %cmp = icmp eq i32 %c, 0
294  br i1 %cmp, label %end, label %fshbb
295
296fshbb:
297  %sub = sub i32 32, %c
298  %shl = shl i32 %a, %sub
299  %shr = lshr i32 %b, %c
300  %or = or i32 %shl, %shr
301  %cmp42 = icmp ugt i32 %or, 42
302  br i1 %cmp42, label %end, label %bogus
303
304bogus:
305  br label %end
306
307end:
308  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ], [ %d, %bogus ]
309  ret i32 %cond
310}
311
312; Negative test - wrong cmp (but this should match?).
313
314define i32 @not_fshr_3(i32 %a, i32 %b, i32 %c) {
315; CHECK-LABEL: @not_fshr_3(
316; CHECK-NEXT:  entry:
317; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i32 [[C:%.*]], 0
318; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
319; CHECK:       fshbb:
320; CHECK-NEXT:    [[SUB:%.*]] = sub i32 32, [[C]]
321; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
322; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
323; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
324; CHECK-NEXT:    br label [[END]]
325; CHECK:       end:
326; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
327; CHECK-NEXT:    ret i32 [[COND]]
328;
329entry:
330  %cmp = icmp sle i32 %c, 0
331  br i1 %cmp, label %end, label %fshbb
332
333fshbb:
334  %sub = sub i32 32, %c
335  %shl = shl i32 %a, %sub
336  %shr = lshr i32 %b, %c
337  %or = or i32 %shl, %shr
338  br label %end
339
340end:
341  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
342  ret i32 %cond
343}
344
345; Negative test - wrong shift.
346
347define i32 @not_fshr_4(i32 %a, i32 %b, i32 %c) {
348; CHECK-LABEL: @not_fshr_4(
349; CHECK-NEXT:  entry:
350; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
351; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
352; CHECK:       fshbb:
353; CHECK-NEXT:    [[SUB:%.*]] = sub i32 32, [[C]]
354; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
355; CHECK-NEXT:    [[SHR:%.*]] = ashr i32 [[B:%.*]], [[C]]
356; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
357; CHECK-NEXT:    br label [[END]]
358; CHECK:       end:
359; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
360; CHECK-NEXT:    ret i32 [[COND]]
361;
362entry:
363  %cmp = icmp eq i32 %c, 0
364  br i1 %cmp, label %end, label %fshbb
365
366fshbb:
367  %sub = sub i32 32, %c
368  %shl = shl i32 %a, %sub
369  %shr = ashr i32 %b, %c
370  %or = or i32 %shl, %shr
371  br label %end
372
373end:
374  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
375  ret i32 %cond
376}
377
378; Negative test - wrong shift for rotate (but can be folded to a generic funnel shift).
379
380define i32 @not_fshr_5(i32 %a, i32 %b, i32 %c) {
381; CHECK-LABEL: @not_fshr_5(
382; CHECK-NEXT:  entry:
383; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
384; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
385; CHECK:       fshbb:
386; CHECK-NEXT:    br label [[END]]
387; CHECK:       end:
388; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.fshr.i32(i32 [[C]], i32 [[B:%.*]], i32 [[C]])
389; CHECK-NEXT:    ret i32 [[TMP0]]
390;
391entry:
392  %cmp = icmp eq i32 %c, 0
393  br i1 %cmp, label %end, label %fshbb
394
395fshbb:
396  %sub = sub i32 32, %c
397  %shl = shl i32 %c, %sub
398  %shr = lshr i32 %b, %c
399  %or = or i32 %shl, %shr
400  br label %end
401
402end:
403  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
404  ret i32 %cond
405}
406
407; Negative test - wrong sub.
408
409define i32 @not_fshr_6(i32 %a, i32 %b, i32 %c) {
410; CHECK-LABEL: @not_fshr_6(
411; CHECK-NEXT:  entry:
412; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
413; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
414; CHECK:       fshbb:
415; CHECK-NEXT:    [[SUB:%.*]] = sub i32 8, [[C]]
416; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
417; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
418; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
419; CHECK-NEXT:    br label [[END]]
420; CHECK:       end:
421; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
422; CHECK-NEXT:    ret i32 [[COND]]
423;
424entry:
425  %cmp = icmp eq i32 %c, 0
426  br i1 %cmp, label %end, label %fshbb
427
428fshbb:
429  %sub = sub i32 8, %c
430  %shl = shl i32 %a, %sub
431  %shr = lshr i32 %b, %c
432  %or = or i32 %shl, %shr
433  br label %end
434
435end:
436  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
437  ret i32 %cond
438}
439
440; Negative test - extra use. Technically, we could transform this
441; because it doesn't increase the instruction count, but we're
442; being cautious not to cause a potential perf pessimization for
443; targets that do not have a fshate instruction.
444
445define i32 @could_be_fshr(i32 %a, i32 %b, i32 %c, ptr %p) {
446; CHECK-LABEL: @could_be_fshr(
447; CHECK-NEXT:  entry:
448; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
449; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[FSHBB:%.*]]
450; CHECK:       fshbb:
451; CHECK-NEXT:    [[SUB:%.*]] = sub i32 32, [[C]]
452; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]
453; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[B:%.*]], [[C]]
454; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR]]
455; CHECK-NEXT:    store i32 [[OR]], ptr [[P:%.*]], align 4
456; CHECK-NEXT:    br label [[END]]
457; CHECK:       end:
458; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[FSHBB]] ]
459; CHECK-NEXT:    ret i32 [[COND]]
460;
461entry:
462  %cmp = icmp eq i32 %c, 0
463  br i1 %cmp, label %end, label %fshbb
464
465fshbb:
466  %sub = sub i32 32, %c
467  %shl = shl i32 %a, %sub
468  %shr = lshr i32 %b, %c
469  %or = or i32 %shl, %shr
470  store i32 %or, ptr %p
471  br label %end
472
473end:
474  %cond = phi i32 [ %b, %entry ], [ %or, %fshbb ]
475  ret i32 %cond
476}
477
478; PR48068 - Ensure we don't fold a funnel shift that depends on a shift value that
479; can't be hoisted out of a basic block.
480@a = global i32 0, align 4
481declare i32 @i(...)
482declare i32 @f(...)
483
484define i32 @PR48068() {
485; CHECK-LABEL: @PR48068(
486; CHECK-NEXT:  entry:
487; CHECK-NEXT:    [[CALL:%.*]] = call i32 @i()
488; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
489; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP0]], 0
490; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
491; CHECK:       if.then:
492; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CALL]], [[TMP0]]
493; CHECK-NEXT:    [[CALL_I:%.*]] = call i32 @f()
494; CHECK-NEXT:    [[SUB_I:%.*]] = sub nsw i32 32, [[TMP0]]
495; CHECK-NEXT:    [[SHR_I:%.*]] = lshr i32 [[CALL_I]], [[SUB_I]]
496; CHECK-NEXT:    [[OR:%.*]] = or i32 [[SHL]], [[SHR_I]]
497; CHECK-NEXT:    br label [[IF_END]]
498; CHECK:       if.end:
499; CHECK-NEXT:    [[H_0:%.*]] = phi i32 [ [[OR]], [[IF_THEN]] ], [ [[CALL]], [[ENTRY:%.*]] ]
500; CHECK-NEXT:    ret i32 [[H_0]]
501;
502entry:
503  %call = call i32 @i()
504  %0 = load i32, ptr @a, align 4
505  %tobool.not = icmp eq i32 %0, 0
506  br i1 %tobool.not, label %if.end, label %if.then
507
508if.then:                                          ; preds = %entry
509  %shl = shl i32 %call, %0
510  %call.i = call i32 @f()
511  %sub.i = sub nsw i32 32, %0
512  %shr.i = lshr i32 %call.i, %sub.i
513  %or = or i32 %shl, %shr.i
514  br label %if.end
515
516if.end:                                           ; preds = %if.then, %entry
517  %h.0 = phi i32 [ %or, %if.then ], [ %call, %entry ]
518  ret i32 %h.0
519}
520