@@ -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(
@@ -2151,3 +2158,234 @@ return: ; preds = %sw.default, %entry,
2151
2158
%retval.0 = phi { i8 , i8 } [ undef , %entry ], [ undef , %entry ], [ undef , %entry ], [ %1 , %sw.default ]
2152
2159
ret { i8 , i8 } %retval.0
2153
2160
}
2161
+
2162
+ ; The switch has a hole which falls through to an unreachable default case, but it can still be optimized into a constant load because
2163
+ ; the poison value used for the hole is ignored.
2164
+ define i32 @constant_hole_unreachable_default (i32 %x ) {
2165
+ ; CHECK-LABEL: @constant_hole_unreachable_default(
2166
+ ; CHECK-NEXT: entry:
2167
+ ; CHECK-NEXT: ret i32 1
2168
+ ;
2169
+ entry:
2170
+ switch i32 %x , label %sw.default [
2171
+ i32 0 , label %bb0
2172
+ i32 2 , label %bb0
2173
+ i32 3 , label %bb0
2174
+ i32 4 , label %bb0
2175
+ ]
2176
+
2177
+ sw.default: unreachable
2178
+ bb0: br label %return
2179
+
2180
+ return:
2181
+ %res = phi i32 [ 1 , %bb0 ]
2182
+ ret i32 %res
2183
+ }
2184
+
2185
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns undef, but it can still
2186
+ ; be optimized into a constant load because the undef values are ignored.
2187
+ define i32 @constant_hole_unreachable_default_firstundef (i32 %x ) {
2188
+ ; CHECK-LABEL: @constant_hole_unreachable_default_firstundef(
2189
+ ; CHECK-NEXT: entry:
2190
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_firstundef, i32 0, i32 [[X:%.*]]
2191
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2192
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2193
+ ;
2194
+ entry:
2195
+ switch i32 %x , label %sw.default [
2196
+ i32 0 , label %bb.undef
2197
+ i32 2 , label %bb0
2198
+ i32 3 , label %bb0
2199
+ i32 4 , label %bb0
2200
+ ]
2201
+
2202
+ sw.default: unreachable
2203
+ bb.undef: br label %return
2204
+ bb0: br label %return
2205
+
2206
+ return:
2207
+ %res = phi i32 [ undef , %bb.undef ], [ 1 , %bb0 ]
2208
+ ret i32 %res
2209
+ }
2210
+
2211
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns undef, but it can still
2212
+ ; be optimized into a constant load because the undef values are ignored.
2213
+ define i32 @constant_hole_unreachable_default_lastundef (i32 %x ) {
2214
+ ; CHECK-LABEL: @constant_hole_unreachable_default_lastundef(
2215
+ ; CHECK-NEXT: entry:
2216
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_lastundef, i32 0, i32 [[X:%.*]]
2217
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2218
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2219
+ ;
2220
+ entry:
2221
+ switch i32 %x , label %sw.default [
2222
+ i32 0 , label %bb0
2223
+ i32 2 , label %bb0
2224
+ i32 3 , label %bb0
2225
+ i32 4 , label %bb.undef
2226
+ ]
2227
+
2228
+ sw.default: unreachable
2229
+ bb.undef: br label %return
2230
+ bb0: br label %return
2231
+
2232
+ return:
2233
+ %res = phi i32 [ undef , %bb.undef ], [ 1 , %bb0 ]
2234
+ ret i32 %res
2235
+ }
2236
+
2237
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns poison, but it can still
2238
+ ; be optimized into a constant load because the poison values are ignored.
2239
+ define i32 @constant_hole_unreachable_default_firstpoison (i32 %x ) {
2240
+ ; CHECK-LABEL: @constant_hole_unreachable_default_firstpoison(
2241
+ ; CHECK-NEXT: entry:
2242
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_firstpoison, i32 0, i32 [[X:%.*]]
2243
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2244
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2245
+ ;
2246
+ entry:
2247
+ switch i32 %x , label %sw.default [
2248
+ i32 0 , label %bb.poison
2249
+ i32 2 , label %bb0
2250
+ i32 3 , label %bb0
2251
+ i32 4 , label %bb0
2252
+ ]
2253
+
2254
+ sw.default: unreachable
2255
+ bb.poison: br label %return
2256
+ bb0: br label %return
2257
+
2258
+ return:
2259
+ %res = phi i32 [ poison, %bb.poison ], [ 1 , %bb0 ]
2260
+ ret i32 %res
2261
+ }
2262
+
2263
+ ; The switch has a hole which falls through to an unreachable default case and the first case explicitly returns poison, but it can still
2264
+ ; be optimized into a constant load because the poison values are ignored.
2265
+ define i32 @constant_hole_unreachable_default_lastpoison (i32 %x ) {
2266
+ ; CHECK-LABEL: @constant_hole_unreachable_default_lastpoison(
2267
+ ; CHECK-NEXT: entry:
2268
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_lastpoison, i32 0, i32 [[X:%.*]]
2269
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2270
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2271
+ ;
2272
+ entry:
2273
+ switch i32 %x , label %sw.default [
2274
+ i32 0 , label %bb0
2275
+ i32 2 , label %bb0
2276
+ i32 3 , label %bb0
2277
+ i32 4 , label %bb.poison
2278
+ ]
2279
+
2280
+ sw.default: unreachable
2281
+ bb.poison: br label %return
2282
+ bb0: br label %return
2283
+
2284
+ return:
2285
+ %res = phi i32 [ poison, %bb.poison ], [ 1 , %bb0 ]
2286
+ ret i32 %res
2287
+ }
2288
+
2289
+ define i32 @constant_hole_unreachable_default_undef_poison (i32 %x ) {
2290
+ ; CHECK-LABEL: @constant_hole_unreachable_default_undef_poison(
2291
+ ; CHECK-NEXT: entry:
2292
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_undef_poison, i32 0, i32 [[X:%.*]]
2293
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2294
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2295
+ ;
2296
+ entry:
2297
+ switch i32 %x , label %sw.default [
2298
+ i32 0 , label %bb.undef
2299
+ i32 2 , label %bb.poison
2300
+ i32 3 , label %bb.poison
2301
+ i32 4 , label %bb.poison
2302
+ ]
2303
+
2304
+ sw.default: unreachable
2305
+ bb.undef: br label %return
2306
+ bb.poison: br label %return
2307
+
2308
+ return:
2309
+ %res = phi i32 [ undef , %bb.undef ], [ poison, %bb.poison ]
2310
+ ret i32 %res
2311
+ }
2312
+
2313
+ define i32 @constant_hole_unreachable_default_poison_undef (i32 %x ) {
2314
+ ; CHECK-LABEL: @constant_hole_unreachable_default_poison_undef(
2315
+ ; CHECK-NEXT: entry:
2316
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.constant_hole_unreachable_default_poison_undef, i32 0, i32 [[X:%.*]]
2317
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2318
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2319
+ ;
2320
+ entry:
2321
+ switch i32 %x , label %sw.default [
2322
+ i32 0 , label %bb.poison
2323
+ i32 2 , label %bb.poison
2324
+ i32 3 , label %bb.poison
2325
+ i32 4 , label %bb.undef
2326
+ ]
2327
+
2328
+ sw.default: unreachable
2329
+ bb.undef: br label %return
2330
+ bb.poison: br label %return
2331
+
2332
+ return:
2333
+ %res = phi i32 [ undef , %bb.undef ], [ poison, %bb.poison ]
2334
+ ret i32 %res
2335
+ }
2336
+
2337
+ ; 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.
2338
+ ; TODO: We should add support for this, at least in certain cases.
2339
+ define i32 @linearmap_hole_unreachable_default (i32 %x ) {
2340
+ ; CHECK-LABEL: @linearmap_hole_unreachable_default(
2341
+ ; CHECK-NEXT: entry:
2342
+ ; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [5 x i32], ptr @switch.table.linearmap_hole_unreachable_default, i32 0, i32 [[X:%.*]]
2343
+ ; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
2344
+ ; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
2345
+ ;
2346
+ entry:
2347
+ switch i32 %x , label %sw.default [
2348
+ i32 0 , label %bb0
2349
+ i32 2 , label %bb2
2350
+ i32 3 , label %bb3
2351
+ i32 4 , label %bb4
2352
+ ]
2353
+
2354
+ sw.default: unreachable
2355
+ bb0: br label %return
2356
+ bb2: br label %return
2357
+ bb3: br label %return
2358
+ bb4: br label %return
2359
+
2360
+ return:
2361
+ %res = phi i32 [ 1 , %bb0 ], [ 5 , %bb2 ], [ 7 , %bb3 ], [ 9 , %bb4 ]
2362
+ ret i32 %res
2363
+ }
2364
+
2365
+ ; The switch has a hole which falls through to an unreachable default case, but it can still be optimized into a bitmask extraction because
2366
+ ; the poison value used for the hole is simply replaced with zero.
2367
+ define i1 @bitset_hole_unreachable_default (i32 %x ) {
2368
+ ; CHECK-LABEL: @bitset_hole_unreachable_default(
2369
+ ; CHECK-NEXT: entry:
2370
+ ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[X:%.*]] to i5
2371
+ ; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i5 [[SWITCH_CAST]], 1
2372
+ ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i5 8, [[SWITCH_SHIFTAMT]]
2373
+ ; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i5 [[SWITCH_DOWNSHIFT]] to i1
2374
+ ; CHECK-NEXT: ret i1 [[SWITCH_MASKED]]
2375
+ ;
2376
+ entry:
2377
+ switch i32 %x , label %sw.default [
2378
+ i32 0 , label %bb0
2379
+ i32 2 , label %bb0
2380
+ i32 3 , label %bb1
2381
+ i32 4 , label %bb0
2382
+ ]
2383
+
2384
+ sw.default: unreachable
2385
+ bb0: br label %return
2386
+ bb1: br label %return
2387
+
2388
+ return:
2389
+ %res = phi i1 [ 0 , %bb0 ], [ 1 , %bb1 ]
2390
+ ret i1 %res
2391
+ }
0 commit comments