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) {
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:%.*]]
14 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1
15 ; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]]
16 ; CHECK-NEXT: br label [[IF_END:%.*]]
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]]
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
28 br i1 %c, label %if.then, label %if.else
31 %0 = load i16, ptr %b, align 2
32 %add = add nsw i16 %0, 1
33 %1 = load i16, ptr %m, align 2
38 %2 = load i16, ptr %b, align 2
39 %sub = sub nsw i16 %2, 1
40 %3 = load i16, ptr %m, align 2
46 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
47 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
61 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1
62 ; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]]
63 ; CHECK-NEXT: br label [[END:%.*]]
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]]
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]]
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
80 switch i64 %i, label %bb0 [
86 %0 = load i16, ptr %b, align 2
87 %add = add nsw i16 %0, 1
88 %1 = load i16, ptr %m, align 2
93 %2 = load i16, ptr %b, align 2
94 %sub = sub nsw i16 %2, 1
95 %3 = load i16, ptr %m, align 2
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
109 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
110 store i16 %uv, ptr %d, align 2
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) {
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:%.*]]
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:%.*]]
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]]
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
138 br i1 %c, label %if.then, label %if.else
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
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
157 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
158 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
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:%.*]]
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]]
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]]
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
192 switch i64 %i, label %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
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
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
222 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
223 store i16 %uv, ptr %d, align 2
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) {
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:%.*]]
238 ; CHECK-NEXT: call void @no_side_effects0()
239 ; CHECK-NEXT: br label [[IF_END:%.*]]
241 ; CHECK-NEXT: call void @no_side_effects1()
242 ; CHECK-NEXT: br label [[IF_END]]
244 ; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2
245 ; CHECK-NEXT: ret void
248 br i1 %c, label %if.then, label %if.else
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
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
267 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
268 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
284 ; CHECK-NEXT: call void @no_side_effects0()
285 ; CHECK-NEXT: br label [[END:%.*]]
287 ; CHECK-NEXT: call void @no_side_effects1()
288 ; CHECK-NEXT: br label [[END]]
290 ; CHECK-NEXT: call void @no_side_effects1()
291 ; CHECK-NEXT: br label [[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
298 switch i64 %i, label %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
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
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
328 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
329 store i16 %uv, ptr %d, align 2
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) {
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:%.*]]
344 ; CHECK-NEXT: call void @side_effects0()
345 ; CHECK-NEXT: br label [[IF_END:%.*]]
347 ; CHECK-NEXT: call void @side_effects1()
348 ; CHECK-NEXT: br label [[IF_END]]
350 ; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2
351 ; CHECK-NEXT: ret void
354 br i1 %c, label %if.then, label %if.else
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
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
371 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
372 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
387 ; CHECK-NEXT: call void @side_effects0()
388 ; CHECK-NEXT: br label [[IF_END:%.*]]
390 ; CHECK-NEXT: call void @side_effects1()
391 ; CHECK-NEXT: br label [[IF_END]]
393 ; CHECK-NEXT: call void @side_effects1()
394 ; CHECK-NEXT: br label [[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
401 switch i64 %i, label %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
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
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
428 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
429 store i16 %uv, ptr %d, align 2
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) {
437 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2
438 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
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:%.*]]
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]]
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
455 br i1 %c, label %if.then, label %if.else
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
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
472 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
473 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
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:%.*]]
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]]
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]]
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
506 switch i64 %i, label %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
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
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
533 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
534 store i16 %uv, ptr %d, align 2
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) {
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:%.*]]
547 ; CHECK-NEXT: call void @no_side_effects0()
548 ; CHECK-NEXT: br label [[IF_END:%.*]]
550 ; CHECK-NEXT: call void @no_side_effects1()
551 ; CHECK-NEXT: br label [[IF_END]]
553 ; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2
554 ; CHECK-NEXT: ret void
557 br i1 %c, label %if.then, label %if.else
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
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
574 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ]
575 store i16 %uv, ptr %d, align 2
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(
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:%.*]]
590 ; CHECK-NEXT: call void @no_side_effects0()
591 ; CHECK-NEXT: br label [[END:%.*]]
593 ; CHECK-NEXT: call void @no_side_effects1()
594 ; CHECK-NEXT: br label [[END]]
596 ; CHECK-NEXT: call void @no_side_effects1()
597 ; CHECK-NEXT: br label [[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
604 switch i64 %i, label %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
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
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
631 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ]
632 store i16 %uv, ptr %d, align 2
636 ;; No reorder of store over a load.
637 define i16 @f7(i1 %c, ptr %a, ptr %b) {
640 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
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:%.*]]
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]]
650 ; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ]
651 ; CHECK-NEXT: ret i16 [[V]]
654 br i1 %c, label %if.then, label %if.else
657 %va = load i16, ptr %a, align 2
658 store i16 0, ptr %b, align 2
662 %vb = load i16, ptr %b, align 2
663 store i16 0, ptr %b, align 2
667 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
671 define i16 @f7_switch(i64 %i, ptr %a, ptr %b) {
672 ; CHECK-LABEL: @f7_switch(
674 ; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [
675 ; CHECK-NEXT: i64 1, label [[BB1:%.*]]
676 ; CHECK-NEXT: i64 2, label [[BB2:%.*]]
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:%.*]]
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]]
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]]
691 ; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ]
692 ; CHECK-NEXT: ret i16 [[V]]
695 switch i64 %i, label %bb0 [
701 %va = load i16, ptr %a, align 2
702 store i16 0, ptr %b, align 2
706 %vb = load i16, ptr %b, align 2
707 store i16 0, ptr %b, align 2
711 %vc = load i16, ptr %b, align 2
712 store i16 0, ptr %b, align 2
716 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
720 ;; Can reorder load over another load
721 define i16 @f8(i1 %cond, ptr %a, ptr %b, ptr %c) {
724 ; CHECK-NEXT: [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2
725 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
727 ; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
728 ; CHECK-NEXT: br label [[IF_END:%.*]]
730 ; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
731 ; CHECK-NEXT: br label [[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]]
739 br i1 %cond, label %if.then, label %if.else
742 %va = load i16, ptr %a, align 2
743 %c.0 = load i16, ptr %c
747 %vb = load i16, ptr %b, align 2
748 %c.1 = load i16, ptr %c
752 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
753 %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
760 define i16 @f8_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
761 ; CHECK-LABEL: @f8_switch(
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:%.*]]
769 ; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2
770 ; CHECK-NEXT: br label [[END:%.*]]
772 ; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2
773 ; CHECK-NEXT: br label [[END]]
775 ; CHECK-NEXT: [[VC:%.*]] = load i16, ptr [[B]], align 2
776 ; CHECK-NEXT: br label [[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]]
784 switch i64 %i, label %bb0 [
790 %va = load i16, ptr %a, align 2
791 %c.0 = load i16, ptr %c
795 %vb = load i16, ptr %b, align 2
796 %c.1 = load i16, ptr %c
800 %vc = load i16, ptr %b, align 2
801 %c.2 = load i16, ptr %c
805 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
806 %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
813 ;; Currently won't reorder volatile and non-volatile loads.
814 define i16 @f9(i1 %cond, ptr %a, ptr %b, ptr %c) {
817 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
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:%.*]]
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]]
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]]
833 br i1 %cond, label %if.then, label %if.else
836 %va = load volatile i16, ptr %a, align 2
837 %c.0 = load i16, ptr %c
841 %vb = load i16, ptr %b, align 2
842 %c.1 = load i16, ptr %c
846 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ]
847 %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ]
854 define i16 @f9_switch(i64 %i, ptr %a, ptr %b, ptr %c) {
855 ; CHECK-LABEL: @f9_switch(
857 ; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [
858 ; CHECK-NEXT: i64 1, label [[BB1:%.*]]
859 ; CHECK-NEXT: i64 2, label [[BB2:%.*]]
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:%.*]]
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]]
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]]
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]]
880 switch i64 %i, label %bb0 [
886 %va = load volatile i16, ptr %a, align 2
887 %c.0 = load i16, ptr %c
891 %vb = load i16, ptr %b, align 2
892 %c.1 = load i16, ptr %c
896 %vc = load i16, ptr %b, align 2
897 %c.2 = load i16, ptr %c
901 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ]
902 %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ]
909 ;; Don't hoist stacksaves across inalloca allocas
910 define void @f10(i1 %cond) {
912 ; CHECK-NEXT: [[SS:%.*]] = call ptr @llvm.stacksave.p0()
913 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
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:%.*]]
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]]
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
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)
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)
956 call void @llvm.stackrestore(ptr %ss)
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:%.*]]
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:%.*]]
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]]
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]]
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 [
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)
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)
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)
1029 call void @llvm.stackrestore(ptr %ss)
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)