Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / SimplifyCFG / hoist-common-skip.ll
blobe2a32cf44474990d2cce7237b19fed477d035293
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S --passes='simplifycfg<hoist-common-insts>' %s | FileCheck %s
4 ;; Check that the two loads are hoisted to the common predecessor, skipping
5 ;; over the add/sub instructions.
7 define 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
27 entry:
28   br i1 %c, label %if.then, label %if.else
30 if.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
37 if.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
45 if.end:
46   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
47   store i16 %uv, ptr %d, align 2
48   ret void
51 define 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
79 entry:
80   switch i64 %i, label %bb0 [
81   i64 1, label %bb1
82   i64 2, label %bb2
83   ]
85 bb0:
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
92 bb1:
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
100 bb2:
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
108 end:
109   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
110   store i16 %uv, ptr %d, align 2
111   ret void
114 ;; Check some instructions (e.g. add) can be reordered across instructions with side
115 ;; effects, while others (e.g. load) can't.
116 define 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
137 entry:
138   br i1 %c, label %if.then, label %if.else
140 if.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
148 if.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
156 if.end:
157   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
158   store i16 %uv, ptr %d, align 2
159   ret void
162 define 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
191 entry:
192   switch i64 %i, label %bb0 [
193   i64 1, label %bb1
194   i64 2, label %bb2
195   ]
197 bb0:
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
205 bb1:
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
213 bb2:
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
221 end:
222   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
223   store i16 %uv, ptr %d, align 2
224   ret void
227 ;; Check indeed it was the side effects that prevented hoisting the load
228 ;; in the previous test.
229 define 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
247 entry:
248   br i1 %c, label %if.then, label %if.else
250 if.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
258 if.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
266 if.end:
267   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
268   store i16 %uv, ptr %d, align 2
269   ret void
272 define 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
297 entry:
298   switch i64 %i, label %bb0 [
299   i64 1, label %bb1
300   i64 2, label %bb2
301   ]
303 bb0:
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
311 bb1:
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
319 bb2:
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
327 end:
328   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
329   store i16 %uv, ptr %d, align 2
330   ret void
333 ;; Check some instructions (e.g. sdiv) are not speculatively executed.
335 ;; Division by non-zero constant OK to speculate ...
336 define 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
353 entry:
354   br i1 %c, label %if.then, label %if.else
356 if.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
363 if.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
370 if.end:
371   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
372   store i16 %uv, ptr %d, align 2
373   ret void
376 define 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
400 entry:
401   switch i64 %i, label %bb0 [
402   i64 1, label %bb1
403   i64 2, label %bb2
404   ]
406 bb0:
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
413 bb1:
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
420 bb2:
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
427 if.end:
428   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
429   store i16 %uv, ptr %d, align 2
430   ret void
433 ;; ... but not a general division ...
434 define 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
454 entry:
455   br i1 %c, label %if.then, label %if.else
457 if.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
464 if.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
471 if.end:
472   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
473   store i16 %uv, ptr %d, align 2
474   ret void
477 define 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
505 entry:
506   switch i64 %i, label %bb0 [
507   i64 1, label %bb1
508   i64 2, label %bb2
509   ]
511 bb0:
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
518 bb1:
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
525 bb2:
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
532 end:
533   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
534   store i16 %uv, ptr %d, align 2
535   ret void
538 ;; ... and it's also OK to hoist the division when there's no speculation happening.
539 define 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
556 entry:
557   br i1 %c, label %if.then, label %if.else
559 if.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
566 if.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
573 if.end:
574   %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
575   store i16 %uv, ptr %d, align 2
576   ret void
579 define 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
603 entry:
604   switch i64 %i, label %bb0 [
605   i64 1, label %bb1
606   i64 2, label %bb2
607   ]
609 bb0:
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
616 bb1:
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
623 bb2:
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
630 end:
631   %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
632   store i16 %uv, ptr %d, align 2
633   ret void
636 ;; No reorder of store over a load.
637 define 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]]
653 entry:
654   br i1 %c, label %if.then, label %if.else
656 if.then:
657   %va = load i16, ptr %a, align 2
658   store i16 0, ptr %b, align 2
659   br label %if.end
661 if.else:
662   %vb = load i16, ptr %b, align 2
663   store i16 0, ptr %b, align 2
664   br label %if.end
666 if.end:
667   %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
668   ret i16 %v
671 define 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]]
694 entry:
695   switch i64 %i, label %bb0 [
696   i64 1, label %bb1
697   i64 2, label %bb2
698   ]
700 bb0:
701   %va = load i16, ptr %a, align 2
702   store i16 0, ptr %b, align 2
703   br label %end
705 bb1:
706   %vb = load i16, ptr %b, align 2
707   store i16 0, ptr %b, align 2
708   br label %end
710 bb2:
711   %vc = load i16, ptr %b, align 2
712   store i16 0, ptr %b, align 2
713   br label %end
715 end:
716   %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
717   ret i16 %v
720 ;; Can reorder load over another load
721 define 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]]
738 entry:
739   br i1 %cond, label %if.then, label %if.else
741 if.then:
742   %va = load i16, ptr %a, align 2
743   %c.0 = load i16, ptr %c
744   br label %if.end
746 if.else:
747   %vb = load i16, ptr %b, align 2
748   %c.1 = load i16, ptr %c
749   br label %if.end
751 if.end:
752   %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
753   %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
755   %w = add i16 %v, %u
757   ret i16 %w
760 define 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]]
783 entry:
784   switch i64 %i, label %bb0 [
785   i64 1, label %bb1
786   i64 2, label %bb2
787   ]
789 bb0:
790   %va = load i16, ptr %a, align 2
791   %c.0 = load i16, ptr %c
792   br label %end
794 bb1:
795   %vb = load i16, ptr %b, align 2
796   %c.1 = load i16, ptr %c
797   br label %end
799 bb2:
800   %vc = load i16, ptr %b, align 2
801   %c.2 = load i16, ptr %c
802   br label %end
804 end:
805   %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
806   %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
808   %w = add i16 %v, %u
810   ret i16 %w
813 ;; Currently won't reorder volatile and non-volatile loads.
814 define 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]]
832 entry:
833   br i1 %cond, label %if.then, label %if.else
835 if.then:
836   %va = load volatile i16, ptr %a, align 2
837   %c.0 = load i16, ptr %c
838   br label %if.end
840 if.else:
841   %vb = load i16, ptr %b, align 2
842   %c.1 = load i16, ptr %c
843   br label %if.end
845 if.end:
846   %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
847   %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
849   %w = add i16 %v, %u
851   ret i16 %w
854 define 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]]
879 entry:
880   switch i64 %i, label %bb0 [
881   i64 1, label %bb1
882   i64 2, label %bb2
883   ]
885 bb0:
886   %va = load volatile i16, ptr %a, align 2
887   %c.0 = load i16, ptr %c
888   br label %end
890 bb1:
891   %vb = load i16, ptr %b, align 2
892   %c.1 = load i16, ptr %c
893   br label %end
895 bb2:
896   %vc = load i16, ptr %b, align 2
897   %c.2 = load i16, ptr %c
898   br label %end
900 end:
901   %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
902   %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
904   %w = add i16 %v, %u
906   ret i16 %w
909 ;; Don't hoist stacksaves across inalloca allocas
910 define 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
934   %ss = call ptr @llvm.stacksave()
935   br i1 %cond, label %bb1, label %bb2
937 bb1:
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
946 bb2:
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
955 end:
956   call void @llvm.stackrestore(ptr %ss)
957   ret void
960 define 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
995   %ss = call ptr @llvm.stacksave()
996   switch i64 %i, label %bb0 [
997   i64 1, label %bb1
998   i64 2, label %bb2
999   ]
1001 bb0:
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
1010 bb1:
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
1019 bb2:
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
1028 end:
1029   call void @llvm.stackrestore(ptr %ss)
1030   ret void
1033 declare void @side_effects0()
1034 declare void @side_effects1()
1035 declare void @no_side_effects0() readonly nounwind willreturn
1036 declare void @no_side_effects1() readonly nounwind willreturn
1037 declare void @inalloca_i64(ptr inalloca(i64))
1038 declare void @inalloca_i32(ptr inalloca(i32))
1039 declare ptr @llvm.stacksave()
1040 declare void @llvm.stackrestore(ptr)