@@ -34,11 +34,14 @@ target triple = "x86_64-unknown-linux-gnu"
3434; 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
3535; CHECK: @switch.table.unreachable_default = private unnamed_addr constant [4 x i32] [i32 42, i32 52, i32 1, i32 2], align 4
3636; 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
3838; 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
4040; 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
4245;.
4346define i32 @f (i32 %c ) {
4447; CHECK-LABEL: @f(
@@ -2184,3 +2187,226 @@ return: ; preds = %sw.default, %entry,
21842187 %retval.0 = phi { i8 , i8 } [ undef , %entry ], [ undef , %entry ], [ undef , %entry ], [ %1 , %sw.default ]
21852188 ret { i8 , i8 } %retval.0
21862189}
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