|
4 | 4 | define i1 @common_instr_with_unreachable(i64 %a, i64 %b, i64 %c) {
|
5 | 5 | ; CHECK-LABEL: @common_instr_with_unreachable(
|
6 | 6 | ; CHECK-NEXT: start:
|
7 |
| -; CHECK-NEXT: switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [ |
8 |
| -; CHECK-NEXT: i64 0, label [[BB0:%.*]] |
9 |
| -; CHECK-NEXT: i64 1, label [[BB1:%.*]] |
10 |
| -; CHECK-NEXT: i64 2, label [[BB2:%.*]] |
11 |
| -; CHECK-NEXT: ] |
12 |
| -; CHECK: unreachable: |
13 |
| -; CHECK-NEXT: unreachable |
14 |
| -; CHECK: bb0: |
15 | 7 | ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
|
16 |
| -; CHECK-NEXT: br label [[EXIT:%.*]] |
17 |
| -; CHECK: bb1: |
18 |
| -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]] |
19 |
| -; CHECK-NEXT: br label [[EXIT]] |
20 |
| -; CHECK: bb2: |
21 |
| -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]] |
22 |
| -; CHECK-NEXT: br label [[EXIT]] |
23 |
| -; CHECK: exit: |
24 |
| -; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ] |
25 |
| -; CHECK-NEXT: ret i1 [[RESULT]] |
| 8 | +; CHECK-NEXT: ret i1 [[TMP0]] |
26 | 9 | ;
|
27 | 10 | start:
|
28 | 11 | switch i64 %a, label %unreachable [
|
@@ -54,46 +37,126 @@ exit: ; preds = %bb2, %bb1, %bb0
|
54 | 37 | define i1 @common_instr_with_unreachable_2(i64 %a, i64 %b, i64 %c) {
|
55 | 38 | ; CHECK-LABEL: @common_instr_with_unreachable_2(
|
56 | 39 | ; CHECK-NEXT: start:
|
57 |
| -; CHECK-NEXT: switch i64 [[A:%.*]], label [[BB1:%.*]] [ |
| 40 | +; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]] |
| 41 | +; CHECK-NEXT: ret i1 [[TMP0]] |
| 42 | +; |
| 43 | +start: |
| 44 | + switch i64 %a, label %bb1 [ |
| 45 | + i64 0, label %bb0 |
| 46 | + i64 1, label %unreachable |
| 47 | + i64 2, label %bb2 |
| 48 | + ] |
| 49 | + |
| 50 | +unreachable: |
| 51 | + unreachable |
| 52 | + |
| 53 | +bb0: ; preds = %start |
| 54 | + %0 = icmp eq i64 %b, %c |
| 55 | + br label %exit |
| 56 | + |
| 57 | +bb1: ; preds = %start |
| 58 | + %1 = icmp eq i64 %b, %c |
| 59 | + br label %exit |
| 60 | + |
| 61 | +bb2: ; preds = %start |
| 62 | + %2 = icmp eq i64 %b, %c |
| 63 | + br label %exit |
| 64 | + |
| 65 | +exit: ; preds = %bb2, %bb1, %bb0 |
| 66 | + %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ] |
| 67 | + ret i1 %result |
| 68 | +} |
| 69 | + |
| 70 | +define i1 @not_only_unreachable(i64 %a, i64 %b, i64 %c) { |
| 71 | +; CHECK-LABEL: @not_only_unreachable( |
| 72 | +; CHECK-NEXT: start: |
| 73 | +; CHECK-NEXT: switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [ |
58 | 74 | ; CHECK-NEXT: i64 0, label [[BB0:%.*]]
|
| 75 | +; CHECK-NEXT: i64 1, label [[BB1:%.*]] |
59 | 76 | ; CHECK-NEXT: i64 2, label [[BB2:%.*]]
|
60 | 77 | ; CHECK-NEXT: ]
|
| 78 | +; CHECK: unreachable: |
| 79 | +; CHECK-NEXT: call void @no_return() |
| 80 | +; CHECK-NEXT: unreachable |
61 | 81 | ; CHECK: bb0:
|
62 | 82 | ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
|
| 83 | +; CHECK-NEXT: call void @foo() |
63 | 84 | ; CHECK-NEXT: br label [[EXIT:%.*]]
|
64 | 85 | ; CHECK: bb1:
|
65 | 86 | ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
|
| 87 | +; CHECK-NEXT: call void @foo() |
66 | 88 | ; CHECK-NEXT: br label [[EXIT]]
|
67 | 89 | ; CHECK: bb2:
|
68 | 90 | ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
|
| 91 | +; CHECK-NEXT: call void @foo() |
69 | 92 | ; CHECK-NEXT: br label [[EXIT]]
|
70 | 93 | ; CHECK: exit:
|
71 | 94 | ; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
|
72 | 95 | ; CHECK-NEXT: ret i1 [[RESULT]]
|
73 | 96 | ;
|
74 | 97 | start:
|
75 |
| - switch i64 %a, label %bb1 [ |
| 98 | + switch i64 %a, label %unreachable [ |
76 | 99 | i64 0, label %bb0
|
77 |
| - i64 1, label %unreachable |
| 100 | + i64 1, label %bb1 |
78 | 101 | i64 2, label %bb2
|
79 | 102 | ]
|
80 | 103 |
|
81 | 104 | unreachable:
|
| 105 | + call void @no_return() |
82 | 106 | unreachable
|
83 | 107 |
|
84 | 108 | bb0: ; preds = %start
|
85 | 109 | %0 = icmp eq i64 %b, %c
|
| 110 | + call void @foo() |
86 | 111 | br label %exit
|
87 | 112 |
|
88 | 113 | bb1: ; preds = %start
|
89 | 114 | %1 = icmp eq i64 %b, %c
|
| 115 | + call void @foo() |
90 | 116 | br label %exit
|
91 | 117 |
|
92 | 118 | bb2: ; preds = %start
|
93 | 119 | %2 = icmp eq i64 %b, %c
|
| 120 | + call void @foo() |
94 | 121 | br label %exit
|
95 | 122 |
|
96 | 123 | exit: ; preds = %bb2, %bb1, %bb0
|
97 | 124 | %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
|
98 | 125 | ret i1 %result
|
99 | 126 | }
|
| 127 | + |
| 128 | +; If we can hoist a musttail call, |
| 129 | +; we can and have to hoist subsequent bitcast and ret instructions. |
| 130 | +define ptr @switch_musttail_call(ptr %arg) { |
| 131 | +; CHECK-LABEL: @switch_musttail_call( |
| 132 | +; CHECK-NEXT: bb: |
| 133 | +; CHECK-NEXT: [[P0:%.*]] = musttail call ptr @musttail_call(ptr [[ARG:%.*]]) |
| 134 | +; CHECK-NEXT: ret ptr [[P0]] |
| 135 | +; |
| 136 | +bb: |
| 137 | + %load = load i16, ptr %arg, align 2 |
| 138 | + switch i16 %load, label %unreachable [ |
| 139 | + i16 0, label %bb0 |
| 140 | + i16 1, label %bb1 |
| 141 | + i16 2, label %bb2 |
| 142 | + ] |
| 143 | + |
| 144 | +unreachable: |
| 145 | + unreachable |
| 146 | + |
| 147 | +bb0: |
| 148 | + %p0 = musttail call ptr @musttail_call(ptr %arg) |
| 149 | + ret ptr %p0 |
| 150 | + |
| 151 | +bb1: |
| 152 | + %p1 = musttail call ptr @musttail_call(ptr %arg) |
| 153 | + ret ptr %p1 |
| 154 | + |
| 155 | +bb2: |
| 156 | + %p2 = musttail call ptr @musttail_call(ptr %arg) |
| 157 | + ret ptr %p2 |
| 158 | +} |
| 159 | + |
| 160 | +declare void @no_return() |
| 161 | +declare void @foo() |
| 162 | +declare ptr @musttail_call(ptr) |
0 commit comments