xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/hoist-common-skip.ll (revision 07b9d231ff9baa6473b0dd588a3ce5330d3e4871)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S --passes='simplifycfg<hoist-common-insts>' %s | FileCheck %s
3
4;; Check that the two loads are hoisted to the common predecessor, skipping
5;; over the add/sub instructions.
6
7define void @f0(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m,  ptr nocapture noundef readonly %b) {
8; CHECK-LABEL: @f0(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
11; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
12; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
13; CHECK:       if.then:
14; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[TMP0]], 1
15; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD]], [[TMP1]]
16; CHECK-NEXT:    br label [[IF_END:%.*]]
17; CHECK:       if.else:
18; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1
19; CHECK-NEXT:    [[TMP2:%.*]] = add i16 [[SUB]], 3
20; CHECK-NEXT:    [[V:%.*]] = add i16 [[SUB]], [[TMP2]]
21; CHECK-NEXT:    br label [[IF_END]]
22; CHECK:       if.end:
23; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ]
24; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
25; CHECK-NEXT:    ret void
26;
27entry:
28  br i1 %c, label %if.then, label %if.else
29
30if.then:
31  %0 = load i16, ptr %b, align 2
32  %add = add nsw i16 %0, 1
33  %1 = load i16, ptr %m, align 2
34  %u = add i16 %add, %1
35  br label %if.end
36
37if.else:
38  %2 = load i16, ptr %b, align 2
39  %sub = sub nsw i16 %2, 1
40  %3 = load i16, ptr %m, align 2
41  %4 = add i16 %sub, 3
42  %v = add i16 %sub, %4
43  br label %if.end
44
45if.end:
46  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
47  store i16 %uv, ptr %d, align 2
48  ret void
49}
50
51define void @f0_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m,  ptr nocapture noundef readonly %b) {
52; CHECK-LABEL: @f0_switch(
53; CHECK-NEXT:  entry:
54; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
55; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
56; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
57; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
58; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
59; CHECK-NEXT:    ]
60; CHECK:       bb0:
61; CHECK-NEXT:    [[ADD:%.*]] = add nsw i16 [[TMP0]], 1
62; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD]], [[TMP1]]
63; CHECK-NEXT:    br label [[END:%.*]]
64; CHECK:       bb1:
65; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1
66; CHECK-NEXT:    [[TMP2:%.*]] = add i16 [[SUB]], 3
67; CHECK-NEXT:    [[V:%.*]] = add i16 [[SUB]], [[TMP2]]
68; CHECK-NEXT:    br label [[END]]
69; CHECK:       bb2:
70; CHECK-NEXT:    [[SUB2:%.*]] = sub nsw i16 [[TMP0]], 1
71; CHECK-NEXT:    [[TMP3:%.*]] = add i16 [[SUB2]], 3
72; CHECK-NEXT:    [[W:%.*]] = add i16 [[SUB2]], [[TMP3]]
73; CHECK-NEXT:    br label [[END]]
74; CHECK:       end:
75; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
76; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
77; CHECK-NEXT:    ret void
78;
79entry:
80  switch i64 %i, label %bb0 [
81  i64 1, label %bb1
82  i64 2, label %bb2
83  ]
84
85bb0:
86  %0 = load i16, ptr %b, align 2
87  %add = add nsw i16 %0, 1
88  %1 = load i16, ptr %m, align 2
89  %u = add i16 %add, %1
90  br label %end
91
92bb1:
93  %2 = load i16, ptr %b, align 2
94  %sub = sub nsw i16 %2, 1
95  %3 = load i16, ptr %m, align 2
96  %4 = add i16 %sub, 3
97  %v = add i16 %sub, %4
98  br label %end
99
100bb2:
101  %5 = load i16, ptr %b, align 2
102  %sub2 = sub nsw i16 %5, 1
103  %6 = load i16, ptr %m, align 2
104  %7 = add i16 %sub2, 3
105  %w = add i16 %sub2, %7
106  br label %end
107
108end:
109  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
110  store i16 %uv, ptr %d, align 2
111  ret void
112}
113
114;; Check some instructions (e.g. add) can be reordered across instructions with side
115;; effects, while others (e.g. load) can't.
116define void @f2(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
117; CHECK-LABEL: @f2(
118; CHECK-NEXT:  entry:
119; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
120; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
121; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
122; CHECK:       if.then:
123; CHECK-NEXT:    call void @side_effects0()
124; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
125; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
126; CHECK-NEXT:    br label [[IF_END:%.*]]
127; CHECK:       if.else:
128; CHECK-NEXT:    call void @no_side_effects0()
129; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[M]], align 2
130; CHECK-NEXT:    [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]]
131; CHECK-NEXT:    br label [[IF_END]]
132; CHECK:       if.end:
133; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ]
134; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
135; CHECK-NEXT:    ret void
136;
137entry:
138  br i1 %c, label %if.then, label %if.else
139
140if.then:
141  %0 = load i16, ptr %b, align 2
142  call void @side_effects0()
143  %add.0 = add nsw i16 %0, 1
144  %1 = load i16, ptr %m, align 2
145  %u = add i16 %add.0, %1
146  br label %if.end
147
148if.else:
149  %2 = load i16, ptr %b, align 2
150  call void @no_side_effects0()
151  %add.1 = add nsw i16 %2, 1
152  %3 = load i16, ptr %m, align 2
153  %v = add i16 %add.1, %3
154  br label %if.end
155
156if.end:
157  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
158  store i16 %uv, ptr %d, align 2
159  ret void
160}
161
162define void @f2_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
163; CHECK-LABEL: @f2_switch(
164; CHECK-NEXT:  entry:
165; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
166; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
167; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
168; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
169; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
170; CHECK-NEXT:    ]
171; CHECK:       bb0:
172; CHECK-NEXT:    call void @side_effects0()
173; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
174; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
175; CHECK-NEXT:    br label [[END:%.*]]
176; CHECK:       bb1:
177; CHECK-NEXT:    call void @no_side_effects0()
178; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[M]], align 2
179; CHECK-NEXT:    [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]]
180; CHECK-NEXT:    br label [[END]]
181; CHECK:       bb2:
182; CHECK-NEXT:    call void @no_side_effects0()
183; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[M]], align 2
184; CHECK-NEXT:    [[W:%.*]] = add i16 [[ADD_0]], [[TMP3]]
185; CHECK-NEXT:    br label [[END]]
186; CHECK:       end:
187; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
188; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
189; CHECK-NEXT:    ret void
190;
191entry:
192  switch i64 %i, label %bb0 [
193  i64 1, label %bb1
194  i64 2, label %bb2
195  ]
196
197bb0:
198  %0 = load i16, ptr %b, align 2
199  call void @side_effects0()
200  %add.0 = add nsw i16 %0, 1
201  %1 = load i16, ptr %m, align 2
202  %u = add i16 %add.0, %1
203  br label %end
204
205bb1:
206  %2 = load i16, ptr %b, align 2
207  call void @no_side_effects0()
208  %add.1 = add nsw i16 %2, 1
209  %3 = load i16, ptr %m, align 2
210  %v = add i16 %add.1, %3
211  br label %end
212
213bb2:
214  %4 = load i16, ptr %b, align 2
215  call void @no_side_effects0()
216  %add.2 = add nsw i16 %4, 1
217  %5 = load i16, ptr %m, align 2
218  %w = add i16 %add.2, %5
219  br label %end
220
221end:
222  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
223  store i16 %uv, ptr %d, align 2
224  ret void
225}
226
227;; Check indeed it was the side effects that prevented hoisting the load
228;; in the previous test.
229define void @f3(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
230; CHECK-LABEL: @f3(
231; CHECK-NEXT:  entry:
232; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
233; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
234; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
235; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
236; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
237; CHECK:       if.then:
238; CHECK-NEXT:    call void @no_side_effects0()
239; CHECK-NEXT:    br label [[IF_END:%.*]]
240; CHECK:       if.else:
241; CHECK-NEXT:    call void @no_side_effects1()
242; CHECK-NEXT:    br label [[IF_END]]
243; CHECK:       if.end:
244; CHECK-NEXT:    store i16 [[U]], ptr [[D:%.*]], align 2
245; CHECK-NEXT:    ret void
246;
247entry:
248  br i1 %c, label %if.then, label %if.else
249
250if.then:
251  %0 = load i16, ptr %b, align 2
252  call void @no_side_effects0()
253  %add.0 = add nsw i16 %0, 1
254  %1 = load i16, ptr %m, align 2
255  %u = add i16 %add.0, %1
256  br label %if.end
257
258if.else:
259  %2 = load i16, ptr %b, align 2
260  call void @no_side_effects1()
261  %add.1 = add nsw i16 %2, 1
262  %3 = load i16, ptr %m, align 2
263  %v = add i16 %add.1, %3
264  br label %if.end
265
266if.end:
267  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
268  store i16 %uv, ptr %d, align 2
269  ret void
270}
271
272define void @f3_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
273; CHECK-LABEL: @f3_switch(
274; CHECK-NEXT:  entry:
275; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
276; CHECK-NEXT:    [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1
277; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2
278; CHECK-NEXT:    [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]]
279; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
280; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
281; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
282; CHECK-NEXT:    ]
283; CHECK:       bb0:
284; CHECK-NEXT:    call void @no_side_effects0()
285; CHECK-NEXT:    br label [[END:%.*]]
286; CHECK:       bb1:
287; CHECK-NEXT:    call void @no_side_effects1()
288; CHECK-NEXT:    br label [[END]]
289; CHECK:       bb2:
290; CHECK-NEXT:    call void @no_side_effects1()
291; CHECK-NEXT:    br label [[END]]
292; CHECK:       end:
293; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
294; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
295; CHECK-NEXT:    ret void
296;
297entry:
298  switch i64 %i, label %bb0 [
299  i64 1, label %bb1
300  i64 2, label %bb2
301  ]
302
303bb0:
304  %0 = load i16, ptr %b, align 2
305  call void @no_side_effects0()
306  %add.0 = add nsw i16 %0, 1
307  %1 = load i16, ptr %m, align 2
308  %u = add i16 %add.0, %1
309  br label %end
310
311bb1:
312  %2 = load i16, ptr %b, align 2
313  call void @no_side_effects1()
314  %add.1 = add nsw i16 %2, 1
315  %3 = load i16, ptr %m, align 2
316  %v = add i16 %add.1, %3
317  br label %end
318
319bb2:
320  %4 = load i16, ptr %b, align 2
321  call void @no_side_effects1()
322  %add.2 = add nsw i16 %4, 1
323  %5 = load i16, ptr %m, align 2
324  %w = add i16 %add.2, %5
325  br label %end
326
327end:
328  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
329  store i16 %uv, ptr %d, align 2
330  ret void
331}
332
333;; Check some instructions (e.g. sdiv) are not speculatively executed.
334
335;; Division by non-zero constant OK to speculate ...
336define void @f4(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
337; CHECK-LABEL: @f4(
338; CHECK-NEXT:  entry:
339; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
340; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2
341; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
342; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
343; CHECK:       if.then:
344; CHECK-NEXT:    call void @side_effects0()
345; CHECK-NEXT:    br label [[IF_END:%.*]]
346; CHECK:       if.else:
347; CHECK-NEXT:    call void @side_effects1()
348; CHECK-NEXT:    br label [[IF_END]]
349; CHECK:       if.end:
350; CHECK-NEXT:    store i16 [[U]], ptr [[D:%.*]], align 2
351; CHECK-NEXT:    ret void
352;
353entry:
354  br i1 %c, label %if.then, label %if.else
355
356if.then:
357  %0 = load i16, ptr %b, align 2
358  call void @side_effects0()
359  %div.0 = sdiv i16 %0, 2
360  %u = add i16 %div.0, %0
361  br label %if.end
362
363if.else:
364  %1 = load i16, ptr %b, align 2
365  call void @side_effects1()
366  %div.1 = sdiv i16 %1, 2
367  %v = add i16 %div.1, %1
368  br label %if.end
369
370if.end:
371  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
372  store i16 %uv, ptr %d, align 2
373  ret void
374}
375
376define void @f4_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
377; CHECK-LABEL: @f4_switch(
378; CHECK-NEXT:  entry:
379; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
380; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2
381; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
382; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
383; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
384; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
385; CHECK-NEXT:    ]
386; CHECK:       bb0:
387; CHECK-NEXT:    call void @side_effects0()
388; CHECK-NEXT:    br label [[IF_END:%.*]]
389; CHECK:       bb1:
390; CHECK-NEXT:    call void @side_effects1()
391; CHECK-NEXT:    br label [[IF_END]]
392; CHECK:       bb2:
393; CHECK-NEXT:    call void @side_effects1()
394; CHECK-NEXT:    br label [[IF_END]]
395; CHECK:       if.end:
396; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
397; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
398; CHECK-NEXT:    ret void
399;
400entry:
401  switch i64 %i, label %bb0 [
402  i64 1, label %bb1
403  i64 2, label %bb2
404  ]
405
406bb0:
407  %0 = load i16, ptr %b, align 2
408  call void @side_effects0()
409  %div.0 = sdiv i16 %0, 2
410  %u = add i16 %div.0, %0
411  br label %if.end
412
413bb1:
414  %1 = load i16, ptr %b, align 2
415  call void @side_effects1()
416  %div.1 = sdiv i16 %1, 2
417  %v = add i16 %div.1, %1
418  br label %if.end
419
420bb2:
421  %2 = load i16, ptr %b, align 2
422  call void @side_effects1()
423  %div.2 = sdiv i16 %2, 2
424  %w = add i16 %div.2, %2
425  br label %if.end
426
427if.end:
428  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
429  store i16 %uv, ptr %d, align 2
430  ret void
431}
432
433;; ... but not a general division ...
434define void @f5(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
435; CHECK-LABEL: @f5(
436; CHECK-NEXT:  entry:
437; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
438; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
439; CHECK:       if.then:
440; CHECK-NEXT:    call void @side_effects0()
441; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
442; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
443; CHECK-NEXT:    br label [[IF_END:%.*]]
444; CHECK:       if.else:
445; CHECK-NEXT:    call void @side_effects1()
446; CHECK-NEXT:    [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]]
447; CHECK-NEXT:    [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]]
448; CHECK-NEXT:    br label [[IF_END]]
449; CHECK:       if.end:
450; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ]
451; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
452; CHECK-NEXT:    ret void
453;
454entry:
455  br i1 %c, label %if.then, label %if.else
456
457if.then:
458  %0 = load i16, ptr %b, align 2
459  call void @side_effects0()
460  %div.0 = sdiv i16 211, %0
461  %u = add i16 %div.0, %0
462  br label %if.end
463
464if.else:
465  %1 = load i16, ptr %b, align 2
466  call void @side_effects1()
467  %div.1 = sdiv i16 211, %1
468  %v = add i16 %div.1, %1
469  br label %if.end
470
471if.end:
472  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
473  store i16 %uv, ptr %d, align 2
474  ret void
475}
476
477define void @f5_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
478; CHECK-LABEL: @f5_switch(
479; CHECK-NEXT:  entry:
480; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
481; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
482; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
483; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
484; CHECK-NEXT:    ]
485; CHECK:       bb0:
486; CHECK-NEXT:    call void @side_effects0()
487; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
488; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
489; CHECK-NEXT:    br label [[END:%.*]]
490; CHECK:       bb1:
491; CHECK-NEXT:    call void @side_effects1()
492; CHECK-NEXT:    [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]]
493; CHECK-NEXT:    [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]]
494; CHECK-NEXT:    br label [[END]]
495; CHECK:       bb2:
496; CHECK-NEXT:    call void @side_effects1()
497; CHECK-NEXT:    [[DIV_2:%.*]] = sdiv i16 211, [[TMP0]]
498; CHECK-NEXT:    [[W:%.*]] = add i16 [[DIV_2]], [[TMP0]]
499; CHECK-NEXT:    br label [[END]]
500; CHECK:       end:
501; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ]
502; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
503; CHECK-NEXT:    ret void
504;
505entry:
506  switch i64 %i, label %bb0 [
507  i64 1, label %bb1
508  i64 2, label %bb2
509  ]
510
511bb0:
512  %0 = load i16, ptr %b, align 2
513  call void @side_effects0()
514  %div.0 = sdiv i16 211, %0
515  %u = add i16 %div.0, %0
516  br label %end
517
518bb1:
519  %1 = load i16, ptr %b, align 2
520  call void @side_effects1()
521  %div.1 = sdiv i16 211, %1
522  %v = add i16 %div.1, %1
523  br label %end
524
525bb2:
526  %2 = load i16, ptr %b, align 2
527  call void @side_effects1()
528  %div.2 = sdiv i16 211, %2
529  %w = add i16 %div.2, %2
530  br label %end
531
532end:
533  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
534  store i16 %uv, ptr %d, align 2
535  ret void
536}
537
538;; ... and it's also OK to hoist the division when there's no speculation happening.
539define void @f6(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
540; CHECK-LABEL: @f6(
541; CHECK-NEXT:  entry:
542; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
543; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
544; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
545; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
546; CHECK:       if.then:
547; CHECK-NEXT:    call void @no_side_effects0()
548; CHECK-NEXT:    br label [[IF_END:%.*]]
549; CHECK:       if.else:
550; CHECK-NEXT:    call void @no_side_effects1()
551; CHECK-NEXT:    br label [[IF_END]]
552; CHECK:       if.end:
553; CHECK-NEXT:    store i16 [[U]], ptr [[D:%.*]], align 2
554; CHECK-NEXT:    ret void
555;
556entry:
557  br i1 %c, label %if.then, label %if.else
558
559if.then:
560  %0 = load i16, ptr %b, align 2
561  call void @no_side_effects0()
562  %div.0 = sdiv i16 211, %0
563  %u = add i16 %div.0, %0
564  br label %if.end
565
566if.else:
567  %1 = load i16, ptr %b, align 2
568  call void @no_side_effects1()
569  %div.1 = sdiv i16 211, %1
570  %v = add i16 %div.1, %1
571  br label %if.end
572
573if.end:
574  %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
575  store i16 %uv, ptr %d, align 2
576  ret void
577}
578
579define void @f6_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) {
580; CHECK-LABEL: @f6_switch(
581; CHECK-NEXT:  entry:
582; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
583; CHECK-NEXT:    [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]]
584; CHECK-NEXT:    [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]]
585; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
586; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
587; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
588; CHECK-NEXT:    ]
589; CHECK:       bb0:
590; CHECK-NEXT:    call void @no_side_effects0()
591; CHECK-NEXT:    br label [[END:%.*]]
592; CHECK:       bb1:
593; CHECK-NEXT:    call void @no_side_effects1()
594; CHECK-NEXT:    br label [[END]]
595; CHECK:       bb2:
596; CHECK-NEXT:    call void @no_side_effects1()
597; CHECK-NEXT:    br label [[END]]
598; CHECK:       end:
599; CHECK-NEXT:    [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ]
600; CHECK-NEXT:    store i16 [[UV]], ptr [[D:%.*]], align 2
601; CHECK-NEXT:    ret void
602;
603entry:
604  switch i64 %i, label %bb0 [
605  i64 1, label %bb1
606  i64 2, label %bb2
607  ]
608
609bb0:
610  %0 = load i16, ptr %b, align 2
611  call void @no_side_effects0()
612  %div.0 = sdiv i16 211, %0
613  %u = add i16 %div.0, %0
614  br label %end
615
616bb1:
617  %1 = load i16, ptr %b, align 2
618  call void @no_side_effects1()
619  %div.1 = sdiv i16 211, %1
620  %v = add i16 %div.1, %1
621  br label %end
622
623bb2:
624  %2 = load i16, ptr %b, align 2
625  call void @no_side_effects1()
626  %div.2 = sdiv i16 211, %2
627  %w = add i16 %div.2, %2
628  br label %end
629
630end:
631  %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
632  store i16 %uv, ptr %d, align 2
633  ret void
634}
635
636;; No reorder of store over a load.
637define i16 @f7(i1 %c, ptr %a, ptr %b) {
638; CHECK-LABEL: @f7(
639; CHECK-NEXT:  entry:
640; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
641; CHECK:       if.then:
642; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
643; CHECK-NEXT:    store i16 0, ptr [[B:%.*]], align 2
644; CHECK-NEXT:    br label [[IF_END:%.*]]
645; CHECK:       if.else:
646; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B]], align 2
647; CHECK-NEXT:    store i16 0, ptr [[B]], align 2
648; CHECK-NEXT:    br label [[IF_END]]
649; CHECK:       if.end:
650; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ]
651; CHECK-NEXT:    ret i16 [[V]]
652;
653entry:
654  br i1 %c, label %if.then, label %if.else
655
656if.then:
657  %va = load i16, ptr %a, align 2
658  store i16 0, ptr %b, align 2
659  br label %if.end
660
661if.else:
662  %vb = load i16, ptr %b, align 2
663  store i16 0, ptr %b, align 2
664  br label %if.end
665
666if.end:
667  %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
668  ret i16 %v
669}
670
671define i16 @f7_switch(i64 %i, ptr %a, ptr %b) {
672; CHECK-LABEL: @f7_switch(
673; CHECK-NEXT:  entry:
674; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
675; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
676; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
677; CHECK-NEXT:    ]
678; CHECK:       bb0:
679; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
680; CHECK-NEXT:    store i16 0, ptr [[B:%.*]], align 2
681; CHECK-NEXT:    br label [[END:%.*]]
682; CHECK:       bb1:
683; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B]], align 2
684; CHECK-NEXT:    store i16 0, ptr [[B]], align 2
685; CHECK-NEXT:    br label [[END]]
686; CHECK:       bb2:
687; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
688; CHECK-NEXT:    store i16 0, ptr [[B]], align 2
689; CHECK-NEXT:    br label [[END]]
690; CHECK:       end:
691; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
692; CHECK-NEXT:    ret i16 [[V]]
693;
694entry:
695  switch i64 %i, label %bb0 [
696  i64 1, label %bb1
697  i64 2, label %bb2
698  ]
699
700bb0:
701  %va = load i16, ptr %a, align 2
702  store i16 0, ptr %b, align 2
703  br label %end
704
705bb1:
706  %vb = load i16, ptr %b, align 2
707  store i16 0, ptr %b, align 2
708  br label %end
709
710bb2:
711  %vc = load i16, ptr %b, align 2
712  store i16 0, ptr %b, align 2
713  br label %end
714
715end:
716  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
717  ret i16 %v
718}
719
720;; Can reorder load over another load
721define i16 @f8(i1 %cond, ptr %a, ptr %b, ptr %c) {
722; CHECK-LABEL: @f8(
723; CHECK-NEXT:  entry:
724; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
725; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
726; CHECK:       if.then:
727; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
728; CHECK-NEXT:    br label [[IF_END:%.*]]
729; CHECK:       if.else:
730; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
731; CHECK-NEXT:    br label [[IF_END]]
732; CHECK:       if.end:
733; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ]
734; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[IF_THEN]] ], [ [[C_0]], [[IF_ELSE]] ]
735; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
736; CHECK-NEXT:    ret i16 [[W]]
737;
738entry:
739  br i1 %cond, label %if.then, label %if.else
740
741if.then:
742  %va = load i16, ptr %a, align 2
743  %c.0 = load i16, ptr %c
744  br label %if.end
745
746if.else:
747  %vb = load i16, ptr %b, align 2
748  %c.1 = load i16, ptr %c
749  br label %if.end
750
751if.end:
752  %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
753  %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
754
755  %w = add i16 %v, %u
756
757  ret i16 %w
758}
759
760define i16 @f8_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
761; CHECK-LABEL: @f8_switch(
762; CHECK-NEXT:  entry:
763; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
764; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
765; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
766; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
767; CHECK-NEXT:    ]
768; CHECK:       bb0:
769; CHECK-NEXT:    [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
770; CHECK-NEXT:    br label [[END:%.*]]
771; CHECK:       bb1:
772; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
773; CHECK-NEXT:    br label [[END]]
774; CHECK:       bb2:
775; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
776; CHECK-NEXT:    br label [[END]]
777; CHECK:       end:
778; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
779; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_0]], [[BB1]] ], [ [[C_0]], [[BB2]] ]
780; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
781; CHECK-NEXT:    ret i16 [[W]]
782;
783entry:
784  switch i64 %i, label %bb0 [
785  i64 1, label %bb1
786  i64 2, label %bb2
787  ]
788
789bb0:
790  %va = load i16, ptr %a, align 2
791  %c.0 = load i16, ptr %c
792  br label %end
793
794bb1:
795  %vb = load i16, ptr %b, align 2
796  %c.1 = load i16, ptr %c
797  br label %end
798
799bb2:
800  %vc = load i16, ptr %b, align 2
801  %c.2 = load i16, ptr %c
802  br label %end
803
804end:
805  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
806  %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
807
808  %w = add i16 %v, %u
809
810  ret i16 %w
811}
812
813;; Currently won't reorder volatile and non-volatile loads.
814define i16 @f9(i1 %cond, ptr %a, ptr %b, ptr %c) {
815; CHECK-LABEL: @f9(
816; CHECK-NEXT:  entry:
817; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
818; CHECK:       if.then:
819; CHECK-NEXT:    [[VA:%.*]] = load volatile i16, ptr [[A:%.*]], align 2
820; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
821; CHECK-NEXT:    br label [[IF_END:%.*]]
822; CHECK:       if.else:
823; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
824; CHECK-NEXT:    [[C_1:%.*]] = load i16, ptr [[C]], align 2
825; CHECK-NEXT:    br label [[IF_END]]
826; CHECK:       if.end:
827; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ]
828; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[IF_THEN]] ], [ [[C_1]], [[IF_ELSE]] ]
829; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
830; CHECK-NEXT:    ret i16 [[W]]
831;
832entry:
833  br i1 %cond, label %if.then, label %if.else
834
835if.then:
836  %va = load volatile i16, ptr %a, align 2
837  %c.0 = load i16, ptr %c
838  br label %if.end
839
840if.else:
841  %vb = load i16, ptr %b, align 2
842  %c.1 = load i16, ptr %c
843  br label %if.end
844
845if.end:
846  %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
847  %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
848
849  %w = add i16 %v, %u
850
851  ret i16 %w
852}
853
854define i16 @f9_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
855; CHECK-LABEL: @f9_switch(
856; CHECK-NEXT:  entry:
857; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
858; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
859; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
860; CHECK-NEXT:    ]
861; CHECK:       bb0:
862; CHECK-NEXT:    [[VA:%.*]] = load volatile i16, ptr [[A:%.*]], align 2
863; CHECK-NEXT:    [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
864; CHECK-NEXT:    br label [[END:%.*]]
865; CHECK:       bb1:
866; CHECK-NEXT:    [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
867; CHECK-NEXT:    [[C_1:%.*]] = load i16, ptr [[C]], align 2
868; CHECK-NEXT:    br label [[END]]
869; CHECK:       bb2:
870; CHECK-NEXT:    [[VC:%.*]] = load i16, ptr [[B]], align 2
871; CHECK-NEXT:    [[C_2:%.*]] = load i16, ptr [[C]], align 2
872; CHECK-NEXT:    br label [[END]]
873; CHECK:       end:
874; CHECK-NEXT:    [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
875; CHECK-NEXT:    [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_1]], [[BB1]] ], [ [[C_2]], [[BB2]] ]
876; CHECK-NEXT:    [[W:%.*]] = add i16 [[V]], [[U]]
877; CHECK-NEXT:    ret i16 [[W]]
878;
879entry:
880  switch i64 %i, label %bb0 [
881  i64 1, label %bb1
882  i64 2, label %bb2
883  ]
884
885bb0:
886  %va = load volatile i16, ptr %a, align 2
887  %c.0 = load i16, ptr %c
888  br label %end
889
890bb1:
891  %vb = load i16, ptr %b, align 2
892  %c.1 = load i16, ptr %c
893  br label %end
894
895bb2:
896  %vc = load i16, ptr %b, align 2
897  %c.2 = load i16, ptr %c
898  br label %end
899
900end:
901  %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
902  %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
903
904  %w = add i16 %v, %u
905
906  ret i16 %w
907}
908
909;; Don't hoist stacksaves across inalloca allocas
910define void @f10(i1 %cond) {
911; CHECK-LABEL: @f10(
912; CHECK-NEXT:    [[SS:%.*]] = call ptr @llvm.stacksave.p0()
913; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
914; CHECK:       bb1:
915; CHECK-NEXT:    [[I1:%.*]] = alloca inalloca i32, align 4
916; CHECK-NEXT:    [[SS2:%.*]] = call ptr @llvm.stacksave.p0()
917; CHECK-NEXT:    [[I2:%.*]] = alloca inalloca i64, align 8
918; CHECK-NEXT:    call void @inalloca_i64(ptr inalloca(i64) [[I2]])
919; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS2]])
920; CHECK-NEXT:    call void @inalloca_i32(ptr inalloca(i32) [[I1]])
921; CHECK-NEXT:    br label [[END:%.*]]
922; CHECK:       bb2:
923; CHECK-NEXT:    [[I3:%.*]] = alloca inalloca i64, align 8
924; CHECK-NEXT:    [[SS3:%.*]] = call ptr @llvm.stacksave.p0()
925; CHECK-NEXT:    [[I4:%.*]] = alloca inalloca i64, align 8
926; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I4]])
927; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS3]])
928; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I3]])
929; CHECK-NEXT:    br label [[END]]
930; CHECK:       end:
931; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS]])
932; CHECK-NEXT:    ret void
933;
934  %ss = call ptr @llvm.stacksave()
935  br i1 %cond, label %bb1, label %bb2
936
937bb1:
938  %i1 = alloca inalloca i32
939  %ss2 = call ptr @llvm.stacksave()
940  %i2 = alloca inalloca i64
941  call void @inalloca_i64(ptr inalloca(i64) %i2)
942  call void @llvm.stackrestore(ptr %ss2)
943  call void @inalloca_i32(ptr inalloca(i32) %i1)
944  br label %end
945
946bb2:
947  %i3 = alloca inalloca i64
948  %ss3 = call ptr @llvm.stacksave()
949  %i4 = alloca inalloca i64
950  call ptr @inalloca_i64(ptr inalloca(i64) %i4)
951  call void @llvm.stackrestore(ptr %ss3)
952  call ptr @inalloca_i64(ptr inalloca(i64) %i3)
953  br label %end
954
955end:
956  call void @llvm.stackrestore(ptr %ss)
957  ret void
958}
959
960define void @f10_switch(i64 %i) {
961; CHECK-LABEL: @f10_switch(
962; CHECK-NEXT:    [[SS:%.*]] = call ptr @llvm.stacksave.p0()
963; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
964; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
965; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
966; CHECK-NEXT:    ]
967; CHECK:       bb0:
968; CHECK-NEXT:    [[I1:%.*]] = alloca inalloca i32, align 4
969; CHECK-NEXT:    [[SS2:%.*]] = call ptr @llvm.stacksave.p0()
970; CHECK-NEXT:    [[I2:%.*]] = alloca inalloca i64, align 8
971; CHECK-NEXT:    call void @inalloca_i64(ptr inalloca(i64) [[I2]])
972; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS2]])
973; CHECK-NEXT:    call void @inalloca_i32(ptr inalloca(i32) [[I1]])
974; CHECK-NEXT:    br label [[END:%.*]]
975; CHECK:       bb1:
976; CHECK-NEXT:    [[I3:%.*]] = alloca inalloca i64, align 8
977; CHECK-NEXT:    [[SS3:%.*]] = call ptr @llvm.stacksave.p0()
978; CHECK-NEXT:    [[I4:%.*]] = alloca inalloca i64, align 8
979; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I4]])
980; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS3]])
981; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I3]])
982; CHECK-NEXT:    br label [[END]]
983; CHECK:       bb2:
984; CHECK-NEXT:    [[I5:%.*]] = alloca inalloca i64, align 8
985; CHECK-NEXT:    [[SS4:%.*]] = call ptr @llvm.stacksave.p0()
986; CHECK-NEXT:    [[I6:%.*]] = alloca inalloca i64, align 8
987; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I6]])
988; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS4]])
989; CHECK-NEXT:    [[TMP4:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I5]])
990; CHECK-NEXT:    br label [[END]]
991; CHECK:       end:
992; CHECK-NEXT:    call void @llvm.stackrestore.p0(ptr [[SS]])
993; CHECK-NEXT:    ret void
994;
995  %ss = call ptr @llvm.stacksave()
996  switch i64 %i, label %bb0 [
997  i64 1, label %bb1
998  i64 2, label %bb2
999  ]
1000
1001bb0:
1002  %i1 = alloca inalloca i32
1003  %ss2 = call ptr @llvm.stacksave()
1004  %i2 = alloca inalloca i64
1005  call void @inalloca_i64(ptr inalloca(i64) %i2)
1006  call void @llvm.stackrestore(ptr %ss2)
1007  call void @inalloca_i32(ptr inalloca(i32) %i1)
1008  br label %end
1009
1010bb1:
1011  %i3 = alloca inalloca i64
1012  %ss3 = call ptr @llvm.stacksave()
1013  %i4 = alloca inalloca i64
1014  call ptr @inalloca_i64(ptr inalloca(i64) %i4)
1015  call void @llvm.stackrestore(ptr %ss3)
1016  call ptr @inalloca_i64(ptr inalloca(i64) %i3)
1017  br label %end
1018
1019bb2:
1020  %i5 = alloca inalloca i64
1021  %ss4 = call ptr @llvm.stacksave()
1022  %i6 = alloca inalloca i64
1023  call ptr @inalloca_i64(ptr inalloca(i64) %i6)
1024  call void @llvm.stackrestore(ptr %ss4)
1025  call ptr @inalloca_i64(ptr inalloca(i64) %i5)
1026  br label %end
1027
1028end:
1029  call void @llvm.stackrestore(ptr %ss)
1030  ret void
1031}
1032
1033declare void @side_effects0()
1034declare void @side_effects1()
1035declare void @no_side_effects0() readonly nounwind willreturn
1036declare void @no_side_effects1() readonly nounwind willreturn
1037declare void @inalloca_i64(ptr inalloca(i64))
1038declare void @inalloca_i32(ptr inalloca(i32))
1039declare ptr @llvm.stacksave()
1040declare void @llvm.stackrestore(ptr)
1041