diff options
Diffstat (limited to 'test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll')
| -rw-r--r-- | test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll index 368732711a70..51ced4099ac9 100644 --- a/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ b/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -806,3 +806,170 @@ return: ; CHECK-NOT: @switch.table ; CHECK: switch i32 %c } + +; If we can build a lookup table without any holes, we don't need a default result. +declare void @exit(i32) +define i32 @nodefaultnoholes(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + ] + +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: call void @exit(i32 1) + unreachable +return: + %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] + ret i32 %x + +; CHECK-LABEL: @nodefaultnoholes( +; CHECK: @switch.table +; CHECK-NOT: switch i32 +} + +; This lookup table will have holes, so we need to test for the holes. +define i32 @nodefaultwithholes(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + i32 3, label %sw.bb3 + i32 5, label %sw.bb3 + ] + +sw.bb1: br label %return +sw.bb2: br label %return +sw.bb3: br label %return +sw.default: call void @exit(i32 1) + unreachable +return: + %x = phi i32 [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ] + ret i32 %x + +; CHECK-LABEL: @nodefaultwithholes( +; CHECK: entry: +; CHECK: br i1 %{{.*}}, label %switch.hole_check, label %sw.default +; CHECK: switch.hole_check: +; CHECK-NEXT: %switch.maskindex = trunc i32 %switch.tableidx to i6 +; CHECK-NEXT: %switch.shifted = lshr i6 -17, %switch.maskindex +; The mask is binary 101111. +; CHECK-NEXT: %switch.lobit = trunc i6 %switch.shifted to i1 +; CHECK-NEXT: br i1 %switch.lobit, label %switch.lookup, label %sw.default +; CHECK-NOT: switch i32 +} + +; We don't build lookup tables with holes for switches with less than four cases. +define i32 @threecasesholes(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 3, label %sw.bb2 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.default: br label %return +return: + %x = phi i32 [ %c, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 9, %entry ] + ret i32 %x +; CHECK-LABEL: @threecasesholes( +; CHECK: switch i32 +; CHECK-NOT: @switch.table +} + +; We build lookup tables for switches with three or more cases. +define i32 @threecases(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + ] +sw.bb1: br label %return +sw.bb2: br label %return +sw.default: br label %return +return: + %x = phi i32 [ 3, %sw.default ], [ 5, %sw.bb2 ], [ 7, %sw.bb1 ], [ 9, %entry ] + ret i32 %x +; CHECK-LABEL: @threecases( +; CHECK-NOT: switch i32 +; CHECK: @switch.table +} + +; We don't build tables for switches with two cases. +define i32 @twocases(i32 %c) { +entry: + switch i32 %c, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + ] +sw.bb1: br label %return +sw.default: br label %return +return: + %x = phi i32 [ 3, %sw.default ], [ 7, %sw.bb1 ], [ 9, %entry ] + ret i32 %x +; CHECK-LABEL: @twocases( +; CHECK: switch i32 +; CHECK-NOT: @switch.table +} + +; Don't build tables for switches with TLS variables. +@tls_a = thread_local global i32 0 +@tls_b = thread_local global i32 0 +@tls_c = thread_local global i32 0 +@tls_d = thread_local global i32 0 +define i32* @tls(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + ] +sw.bb1: + br label %return +sw.bb2: + br label %return +sw.default: + br label %return +return: + %retval.0 = phi i32* [ @tls_d, %sw.default ], [ @tls_c, %sw.bb2 ], [ @tls_b, %sw.bb1 ], [ @tls_a, %entry ] + ret i32* %retval.0 +; CHECK-LABEL: @tls( +; CHECK: switch i32 +; CHECK-NOT: @switch.table +} + +; Don't build tables for switches with dllimport variables. +@dllimport_a = external dllimport global [3x i32] +@dllimport_b = external dllimport global [3x i32] +@dllimport_c = external dllimport global [3x i32] +@dllimport_d = external dllimport global [3x i32] +define i32* @dllimport(i32 %x) { +entry: + switch i32 %x, label %sw.default [ + i32 0, label %return + i32 1, label %sw.bb1 + i32 2, label %sw.bb2 + ] +sw.bb1: + br label %return +sw.bb2: + br label %return +sw.default: + br label %return +return: + %retval.0 = phi i32* [ getelementptr inbounds ([3 x i32]* @dllimport_d, i32 0, i32 0), %sw.default ], + [ getelementptr inbounds ([3 x i32]* @dllimport_c, i32 0, i32 0), %sw.bb2 ], + [ getelementptr inbounds ([3 x i32]* @dllimport_b, i32 0, i32 0), %sw.bb1 ], + [ getelementptr inbounds ([3 x i32]* @dllimport_a, i32 0, i32 0), %entry ] + ret i32* %retval.0 +; CHECK-LABEL: @dllimport( +; CHECK: switch i32 +; CHECK-NOT: @switch.table +} |
