@@ -39,6 +39,13 @@ target triple = "x86_64-unknown-linux-gnu"
39
39
; CHECK: @switch.table.covered_switch_with_bit_tests = private unnamed_addr constant [8 x i32] [i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 1, i32 1], align 4
40
40
; CHECK: @switch.table.signed_overflow1 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 1111, i32 2222], align 4
41
41
; CHECK: @switch.table.signed_overflow2 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 2222, i32 2222], align 4
42
+ ; CHECK: @switch.table.constant_hole_unreachable_default_firstundef = private unnamed_addr constant [5 x i32] [i32 undef, i32 undef, i32 1, i32 1, i32 1], align 4
43
+ ; CHECK: @switch.table.constant_hole_unreachable_default_lastundef = private unnamed_addr constant [5 x i32] [i32 1, i32 1, i32 1, i32 1, i32 undef], align 4
44
+ ; CHECK: @switch.table.constant_hole_unreachable_default_firstpoison = private unnamed_addr constant [5 x i32] [i32 poison, i32 poison, i32 1, i32 1, i32 1], align 4
45
+ ; CHECK: @switch.table.constant_hole_unreachable_default_lastpoison = private unnamed_addr constant [5 x i32] [i32 1, i32 1, i32 1, i32 1, i32 poison], align 4
46
+ ; CHECK: @switch.table.constant_hole_unreachable_default_undef_poison = private unnamed_addr constant [5 x i32] [i32 undef, i32 undef, i32 poison, i32 poison, i32 poison], align 4
47
+ ; CHECK: @switch.table.constant_hole_unreachable_default_poison_undef = private unnamed_addr constant [5 x i32] [i32 poison, i32 poison, i32 poison, i32 poison, i32 undef], align 4
48
+ ; CHECK: @switch.table.linearmap_hole_unreachable_default = private unnamed_addr constant [5 x i32] [i32 1, i32 1, i32 5, i32 7, i32 9], align 4
42
49
;.
43
50
define i32 @f (i32 %c ) {
44
51
; CHECK-LABEL: @f(
@@ -2184,3 +2191,234 @@ return: ; preds = %sw.default, %entry,
2184
2191
%retval.0 = phi { i8 , i8 } [ undef , %entry ], [ undef , %entry ], [ undef , %entry ], [ %1 , %sw.default ]
2185
2192
ret { i8 , i8 } %retval.0
2186
2193
}
2194
+
2195
+ ; The switch has a hole which falls through to an unreachable default case, but it can still be optimized into a constant load because
2196
+ ; the poison value used for the hole is ignored.
2197
+ define i32 @constant_hole_unreachable_default (i32 %x ) {
2198
+ ; CHECK-LABEL: @constant_hole_unreachable_default(
2199
+ ; CHECK-NEXT: entry:
2200
+ ; CHECK-NEXT: ret i32 1
2201
+ ;
2202
+ entry:
2203
+ switch i32 %x , label %sw.default [
2204
+ i32 0 , label %bb0
2205
+ i32 2 , label %bb0
2206
+ i32 3 , label %bb0
2207
+ i32 4 , label %bb0
2208
+ ]
2209
+
2210
+ sw.default: unreachable
2211
+ bb0: br label %return
2212
+
2213
+ return:
2214
+ %res = phi i32 [ 1 , %bb0 ]
2215
+ ret i32 %res
2216
+ }
2217
+
2218
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns undef, but it can still
2219
+ ; be optimized into a constant load because the undef values are ignored.
2220
+ define i32 @constant_hole_unreachable_default_firstundef (i32 %x ) {
2221
+ ; CHECK-LABEL: @constant_hole_unreachable_default_firstundef(
2222
+ ; CHECK-NEXT: entry:
2223
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_firstundef, i32 0, i32 [[X:%.*]]
2224
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2225
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2226
+ ;
2227
+ entry:
2228
+ switch i32 %x , label %sw.default [
2229
+ i32 0 , label %bb.undef
2230
+ i32 2 , label %bb0
2231
+ i32 3 , label %bb0
2232
+ i32 4 , label %bb0
2233
+ ]
2234
+
2235
+ sw.default: unreachable
2236
+ bb.undef: br label %return
2237
+ bb0: br label %return
2238
+
2239
+ return:
2240
+ %res = phi i32 [ undef , %bb.undef ], [ 1 , %bb0 ]
2241
+ ret i32 %res
2242
+ }
2243
+
2244
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns undef, but it can still
2245
+ ; be optimized into a constant load because the undef values are ignored.
2246
+ define i32 @constant_hole_unreachable_default_lastundef (i32 %x ) {
2247
+ ; CHECK-LABEL: @constant_hole_unreachable_default_lastundef(
2248
+ ; CHECK-NEXT: entry:
2249
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_lastundef, i32 0, i32 [[X:%.*]]
2250
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2251
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2252
+ ;
2253
+ entry:
2254
+ switch i32 %x , label %sw.default [
2255
+ i32 0 , label %bb0
2256
+ i32 2 , label %bb0
2257
+ i32 3 , label %bb0
2258
+ i32 4 , label %bb.undef
2259
+ ]
2260
+
2261
+ sw.default: unreachable
2262
+ bb.undef: br label %return
2263
+ bb0: br label %return
2264
+
2265
+ return:
2266
+ %res = phi i32 [ undef , %bb.undef ], [ 1 , %bb0 ]
2267
+ ret i32 %res
2268
+ }
2269
+
2270
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns poison, but it can still
2271
+ ; be optimized into a constant load because the poison values are ignored.
2272
+ define i32 @constant_hole_unreachable_default_firstpoison (i32 %x ) {
2273
+ ; CHECK-LABEL: @constant_hole_unreachable_default_firstpoison(
2274
+ ; CHECK-NEXT: entry:
2275
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_firstpoison, i32 0, i32 [[X:%.*]]
2276
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2277
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2278
+ ;
2279
+ entry:
2280
+ switch i32 %x , label %sw.default [
2281
+ i32 0 , label %bb.poison
2282
+ i32 2 , label %bb0
2283
+ i32 3 , label %bb0
2284
+ i32 4 , label %bb0
2285
+ ]
2286
+
2287
+ sw.default: unreachable
2288
+ bb.poison: br label %return
2289
+ bb0: br label %return
2290
+
2291
+ return:
2292
+ %res = phi i32 [ poison, %bb.poison ], [ 1 , %bb0 ]
2293
+ ret i32 %res
2294
+ }
2295
+
2296
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns poison, but it can still
2297
+ ; be optimized into a constant load because the poison values are ignored.
2298
+ define i32 @constant_hole_unreachable_default_lastpoison (i32 %x ) {
2299
+ ; CHECK-LABEL: @constant_hole_unreachable_default_lastpoison(
2300
+ ; CHECK-NEXT: entry:
2301
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_lastpoison, i32 0, i32 [[X:%.*]]
2302
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2303
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2304
+ ;
2305
+ entry:
2306
+ switch i32 %x , label %sw.default [
2307
+ i32 0 , label %bb0
2308
+ i32 2 , label %bb0
2309
+ i32 3 , label %bb0
2310
+ i32 4 , label %bb.poison
2311
+ ]
2312
+
2313
+ sw.default: unreachable
2314
+ bb.poison: br label %return
2315
+ bb0: br label %return
2316
+
2317
+ return:
2318
+ %res = phi i32 [ poison, %bb.poison ], [ 1 , %bb0 ]
2319
+ ret i32 %res
2320
+ }
2321
+
2322
+ define i32 @constant_hole_unreachable_default_undef_poison (i32 %x ) {
2323
+ ; CHECK-LABEL: @constant_hole_unreachable_default_undef_poison(
2324
+ ; CHECK-NEXT: entry:
2325
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_undef_poison, i32 0, i32 [[X:%.*]]
2326
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2327
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2328
+ ;
2329
+ entry:
2330
+ switch i32 %x , label %sw.default [
2331
+ i32 0 , label %bb.undef
2332
+ i32 2 , label %bb.poison
2333
+ i32 3 , label %bb.poison
2334
+ i32 4 , label %bb.poison
2335
+ ]
2336
+
2337
+ sw.default: unreachable
2338
+ bb.undef: br label %return
2339
+ bb.poison: br label %return
2340
+
2341
+ return:
2342
+ %res = phi i32 [ undef , %bb.undef ], [ poison, %bb.poison ]
2343
+ ret i32 %res
2344
+ }
2345
+
2346
+ define i32 @constant_hole_unreachable_default_poison_undef (i32 %x ) {
2347
+ ; CHECK-LABEL: @constant_hole_unreachable_default_poison_undef(
2348
+ ; CHECK-NEXT: entry:
2349
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_poison_undef, i32 0, i32 [[X:%.*]]
2350
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2351
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2352
+ ;
2353
+ entry:
2354
+ switch i32 %x , label %sw.default [
2355
+ i32 0 , label %bb.poison
2356
+ i32 2 , label %bb.poison
2357
+ i32 3 , label %bb.poison
2358
+ i32 4 , label %bb.undef
2359
+ ]
2360
+
2361
+ sw.default: unreachable
2362
+ bb.undef: br label %return
2363
+ bb.poison: br label %return
2364
+
2365
+ return:
2366
+ %res = phi i32 [ undef , %bb.undef ], [ poison, %bb.poison ]
2367
+ ret i32 %res
2368
+ }
2369
+
2370
+ ; The switch has a hole which falls through to an unreachable default case, which prevents it from being optimized into a linear mapping 2*x+1.
2371
+ ; TODO: We should add support for this, at least in certain cases.
2372
+ define i32 @linearmap_hole_unreachable_default (i32 %x ) {
2373
+ ; CHECK-LABEL: @linearmap_hole_unreachable_default(
2374
+ ; CHECK-NEXT: entry:
2375
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.linearmap_hole_unreachable_default, i32 0, i32 [[X:%.*]]
2376
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2377
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2378
+ ;
2379
+ entry:
2380
+ switch i32 %x , label %sw.default [
2381
+ i32 0 , label %bb0
2382
+ i32 2 , label %bb2
2383
+ i32 3 , label %bb3
2384
+ i32 4 , label %bb4
2385
+ ]
2386
+
2387
+ sw.default: unreachable
2388
+ bb0: br label %return
2389
+ bb2: br label %return
2390
+ bb3: br label %return
2391
+ bb4: br label %return
2392
+
2393
+ return:
2394
+ %res = phi i32 [ 1 , %bb0 ], [ 5 , %bb2 ], [ 7 , %bb3 ], [ 9 , %bb4 ]
2395
+ ret i32 %res
2396
+ }
2397
+
2398
+ ; The switch has a hole which falls through to an unreachable default case, but it can still be optimized into a bitmask extraction because
2399
+ ; the poison value used for the hole is simply replaced with zero.
2400
+ define i1 @bitset_hole_unreachable_default (i32 %x ) {
2401
+ ; CHECK-LABEL: @bitset_hole_unreachable_default(
2402
+ ; CHECK-NEXT: entry:
2403
+ ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[X:%.*]] to i5
2404
+ ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i5 [[SWITCH_CAST]], 1
2405
+ ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i5 8, [[SWITCH_SHIFTAMT]]
2406
+ ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i5 [[SWITCH_DOWNSHIFT]] to i1
2407
+ ; CHECK-NEXT: ret i1 [[SWITCH_MASKED]]
2408
+ ;
2409
+ entry:
2410
+ switch i32 %x , label %sw.default [
2411
+ i32 0 , label %bb0
2412
+ i32 2 , label %bb0
2413
+ i32 3 , label %bb1
2414
+ i32 4 , label %bb0
2415
+ ]
2416
+
2417
+ sw.default: unreachable
2418
+ bb0: br label %return
2419
+ bb1: br label %return
2420
+
2421
+ return:
2422
+ %res = phi i1 [ 0 , %bb0 ], [ 1 , %bb1 ]
2423
+ ret i1 %res
2424
+ }
0 commit comments