|
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