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:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP1]], i32 30)
11 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 4
12 ; CHECK-NEXT: br i1 [[TMP3]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
13 ; CHECK: switch.lookup:
14 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.test1, i32 0, i32 [[TMP2]]
15 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
16 ; CHECK-NEXT: br label [[COMMON_RET]]
18 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
19 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
21 switch i32 %a, label %def [
39 ; Optimization shouldn't trigger; bitwidth > 64
40 define i128 @test2(i128 %a) {
41 ; CHECK-LABEL: @test2(
42 ; CHECK-NEXT: switch i128 [[A:%.*]], label [[COMMON_RET:%.*]] [
43 ; CHECK-NEXT: i128 97, label [[ONE:%.*]]
44 ; CHECK-NEXT: i128 101, label [[TWO:%.*]]
45 ; CHECK-NEXT: i128 105, label [[THREE:%.*]]
46 ; CHECK-NEXT: i128 109, label [[THREE]]
49 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i128 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
50 ; CHECK-NEXT: ret i128 [[COMMON_RET_OP]]
52 ; CHECK-NEXT: br label [[COMMON_RET]]
54 ; CHECK-NEXT: br label [[COMMON_RET]]
56 ; CHECK-NEXT: br label [[COMMON_RET]]
58 switch i128 %a, label %def [
61 i128 105, label %three
62 i128 109, label %three
76 ; Optimization shouldn't trigger; no holes present
77 define i32 @test3(i32 %a) {
78 ; CHECK-LABEL: @test3(
79 ; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i32 [[A:%.*]], 97
80 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 3
81 ; CHECK-NEXT: br i1 [[TMP1]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
82 ; CHECK: switch.lookup:
83 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [3 x i32], ptr @switch.table.test3, i32 0, i32 [[SWITCH_TABLEIDX]]
84 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
85 ; CHECK-NEXT: br label [[COMMON_RET]]
87 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
88 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
90 switch i32 %a, label %def [
107 ; Optimization shouldn't trigger; not an arithmetic progression
108 define i32 @test4(i32 %a) {
109 ; CHECK-LABEL: @test4(
110 ; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [
111 ; CHECK-NEXT: i32 97, label [[ONE:%.*]]
112 ; CHECK-NEXT: i32 102, label [[TWO:%.*]]
113 ; CHECK-NEXT: i32 105, label [[THREE:%.*]]
114 ; CHECK-NEXT: i32 109, label [[THREE]]
117 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
118 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
120 ; CHECK-NEXT: br label [[COMMON_RET]]
122 ; CHECK-NEXT: br label [[COMMON_RET]]
124 ; CHECK-NEXT: br label [[COMMON_RET]]
126 switch i32 %a, label %def [
129 i32 105, label %three
130 i32 109, label %three
144 ; Optimization shouldn't trigger; not a power of two
145 define i32 @test5(i32 %a) {
146 ; CHECK-LABEL: @test5(
147 ; CHECK-NEXT: switch i32 [[A:%.*]], label [[COMMON_RET:%.*]] [
148 ; CHECK-NEXT: i32 97, label [[ONE:%.*]]
149 ; CHECK-NEXT: i32 102, label [[TWO:%.*]]
150 ; CHECK-NEXT: i32 107, label [[THREE:%.*]]
151 ; CHECK-NEXT: i32 112, label [[THREE]]
154 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 11984, [[ONE]] ], [ 1143, [[TWO]] ], [ 99783, [[THREE]] ], [ 8867, [[TMP0:%.*]] ]
155 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
157 ; CHECK-NEXT: br label [[COMMON_RET]]
159 ; CHECK-NEXT: br label [[COMMON_RET]]
161 ; CHECK-NEXT: br label [[COMMON_RET]]
163 switch i32 %a, label %def [
166 i32 107, label %three
167 i32 112, label %three
181 define i32 @test6(i32 %a) optsize {
182 ; CHECK-LABEL: @test6(
183 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], -109
184 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP1]], i32 30)
185 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 4
186 ; CHECK-NEXT: br i1 [[TMP3]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
187 ; CHECK: switch.lookup:
188 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.test6, i32 0, i32 [[TMP2]]
189 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
190 ; CHECK-NEXT: br label [[COMMON_RET]]
192 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
193 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
195 switch i32 %a, label %def [
198 i32 -105, label %three
199 i32 -109, label %three
213 define i8 @test7(i8 %a) optsize {
214 ; CHECK-LABEL: @test7(
215 ; CHECK-NEXT: common.ret:
216 ; CHECK-NEXT: [[TMP0:%.*]] = sub i8 [[A:%.*]], -36
217 ; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.fshl.i8(i8 [[TMP0]], i8 [[TMP0]], i8 6)
218 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 4
219 ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = zext i8 [[TMP1]] to i32
220 ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i32 [[SWITCH_CAST]], 8
221 ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i32 -943228976, [[SWITCH_SHIFTAMT]]
222 ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i32 [[SWITCH_DOWNSHIFT]] to i8
223 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = select i1 [[TMP2]], i8 [[SWITCH_MASKED]], i8 -93
224 ; CHECK-NEXT: ret i8 [[COMMON_RET_OP]]
226 switch i8 %a, label %def [
244 define i32 @test8(i32 %a) optsize {
245 ; CHECK-LABEL: @test8(
246 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 97
247 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP1]], i32 30)
248 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 5
249 ; CHECK-NEXT: br i1 [[TMP3]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
250 ; CHECK: switch.lookup:
251 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.test8, i32 0, i32 [[TMP2]]
252 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
253 ; CHECK-NEXT: br label [[COMMON_RET]]
255 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
256 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
258 switch i32 %a, label %def [
261 i32 105, label %three
262 i32 113, label %three
276 define i32 @test9(i32 %a) {
277 ; CHECK-LABEL: @test9(
278 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], 6
279 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.fshl.i32(i32 [[TMP1]], i32 [[TMP1]], i32 31)
280 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 8
281 ; CHECK-NEXT: br i1 [[TMP3]], label [[SWITCH_LOOKUP:%.*]], label [[COMMON_RET:%.*]]
282 ; CHECK: switch.lookup:
283 ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [8 x i32], ptr @switch.table.test9, i32 0, i32 [[TMP2]]
284 ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
285 ; CHECK-NEXT: br label [[COMMON_RET]]
287 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 8867, [[TMP0:%.*]] ]
288 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
290 switch i32 %a, label %def [