1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-to-lookup -S | FileCheck %s
3 ; RUN: opt < %s -passes='simplifycfg<switch-to-lookup>' -S | FileCheck %s
5 target datalayout = "e-n32"
7 define i32 @test1(i32 %a) {
9 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 97
10 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
11 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30
12 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
13 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 4
14 ; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
15 ; CHECK: switch.lookup:
16 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.test1, i32 0, i32 [[TMP4]]
17 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
18 ; CHECK-NEXT: br label [[COMMON_RET]]
20 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
21 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
23 switch i32 %a, label %def [
41 ; Optimization shouldn't trigger; bitwidth > 64
42 define i128 @test2(i128 %a) {
43 ; CHECK-LABEL: @test2(
44 ; CHECK-NEXT: switch i128 [[A:%.*]], label [[COMMON_RET:%.*]] [
45 ; CHECK-NEXT: i128 97, label [[ONE:%.*]]
46 ; CHECK-NEXT: i128 101, label [[TWO:%.*]]
47 ; CHECK-NEXT: i128 105, label [[THREE:%.*]]
48 ; CHECK-NEXT: i128 109, label [[THREE]]
51 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i128 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
52 ; CHECK-NEXT: ret i128 [[COMMON_RET_OP]]
54 ; CHECK-NEXT: br label [[COMMON_RET]]
56 ; CHECK-NEXT: br label [[COMMON_RET]]
58 ; CHECK-NEXT: br label [[COMMON_RET]]
60 switch i128 %a, label %def [
63 i128 105, label %three
64 i128 109, label %three
78 ; Optimization shouldn't trigger; no holes present
79 define i32 @test3(i32 %a) {
80 ; CHECK-LABEL: @test3(
81 ; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[A:%.*]], 97
82 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 3
83 ; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
84 ; CHECK: switch.lookup:
85 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], ptr @switch.table.test3, i32 0, i32 [[SWITCH_TABLEIDX]]
86 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
87 ; CHECK-NEXT: br label [[COMMON_RET]]
89 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
90 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
92 switch i32 %a, label %def [
109 ; Optimization shouldn't trigger; not an arithmetic progression
110 define i32 @test4(i32 %a) {
111 ; CHECK-LABEL: @test4(
112 ; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [
113 ; CHECK-NEXT: i32 97, label [[ONE:%.*]]
114 ; CHECK-NEXT: i32 102, label [[TWO:%.*]]
115 ; CHECK-NEXT: i32 105, label [[THREE:%.*]]
116 ; CHECK-NEXT: i32 109, label [[THREE]]
119 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
120 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
122 ; CHECK-NEXT: br label [[COMMON_RET]]
124 ; CHECK-NEXT: br label [[COMMON_RET]]
126 ; CHECK-NEXT: br label [[COMMON_RET]]
128 switch i32 %a, label %def [
131 i32 105, label %three
132 i32 109, label %three
146 ; Optimization shouldn't trigger; not a power of two
147 define i32 @test5(i32 %a) {
148 ; CHECK-LABEL: @test5(
149 ; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [
150 ; CHECK-NEXT: i32 97, label [[ONE:%.*]]
151 ; CHECK-NEXT: i32 102, label [[TWO:%.*]]
152 ; CHECK-NEXT: i32 107, label [[THREE:%.*]]
153 ; CHECK-NEXT: i32 112, label [[THREE]]
156 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
157 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
159 ; CHECK-NEXT: br label [[COMMON_RET]]
161 ; CHECK-NEXT: br label [[COMMON_RET]]
163 ; CHECK-NEXT: br label [[COMMON_RET]]
165 switch i32 %a, label %def [
168 i32 107, label %three
169 i32 112, label %three
183 define i32 @test6(i32 %a) optsize {
184 ; CHECK-LABEL: @test6(
185 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], -109
186 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
187 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30
188 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
189 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 4
190 ; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
191 ; CHECK: switch.lookup:
192 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.test6, i32 0, i32 [[TMP4]]
193 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
194 ; CHECK-NEXT: br label [[COMMON_RET]]
196 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
197 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
199 switch i32 %a, label %def [
202 i32 -105, label %three
203 i32 -109, label %three
217 define i8 @test7(i8 %a) optsize {
218 ; CHECK-LABEL: @test7(
219 ; CHECK-NEXT: common.ret:
220 ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[A:%.*]], -36
221 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[TMP0]], 2
222 ; CHECK-NEXT: [[TMP2:%.*]] = shl i8 [[TMP0]], 6
223 ; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP1]], [[TMP2]]
224 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i8 [[TMP3]], 4
225 ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[TMP3]] to i32
226 ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[SWITCH_CAST]], 8
227 ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -943228976, [[SWITCH_SHIFTAMT]]
228 ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
229 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[TMP4]], i8 [[SWITCH_MASKED]], i8 -93
230 ; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
232 switch i8 %a, label %def [
250 define i32 @test8(i32 %a) optsize {
251 ; CHECK-LABEL: @test8(
252 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 97
253 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 2
254 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 30
255 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
256 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 5
257 ; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
258 ; CHECK: switch.lookup:
259 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.test8, i32 0, i32 [[TMP4]]
260 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
261 ; CHECK-NEXT: br label [[COMMON_RET]]
263 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
264 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
266 switch i32 %a, label %def [
269 i32 105, label %three
270 i32 113, label %three
284 define i32 @test9(i32 %a) {
285 ; CHECK-LABEL: @test9(
286 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 6
287 ; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 1
288 ; CHECK-NEXT: [[TMP3:%.*]] = shl i32 [[TMP1]], 31
289 ; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[TMP2]], [[TMP3]]
290 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[TMP4]], 8
291 ; CHECK-NEXT: br i1 [[TMP5]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
292 ; CHECK: switch.lookup:
293 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], ptr @switch.table.test9, i32 0, i32 [[TMP4]]
294 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
295 ; CHECK-NEXT: br label [[COMMON_RET]]
297 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
298 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
300 switch i32 %a, label %def [