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