[llvm] 0da3671 - [RISCV] Add some tests for SimplifyCFG's switch to lookup table transform

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 31 16:34:16 PDT 2021


Author: Craig Topper
Date: 2021-07-31T16:33:53-07:00
New Revision: 0da367145cb32f45a192e6f758a7474297730fc4

URL: https://github.com/llvm/llvm-project/commit/0da367145cb32f45a192e6f758a7474297730fc4
DIFF: https://github.com/llvm/llvm-project/commit/0da367145cb32f45a192e6f758a7474297730fc4.diff

LOG: [RISCV] Add some tests for SimplifyCFG's switch to lookup table transform

These are some of the basic cases taken from X86.

We currently fail to use lookup tables on many of these cases
because SimplifyCFG requires a legal type to do the transform and
RISCV only has one legal integer type.

Added: 
    llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll
    llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll
new file mode 100644
index 0000000000000..5321c08a569e7
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv32.ll
@@ -0,0 +1,212 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -switch-to-lookup=true -keep-loops=false -S -mattr=+f | FileCheck %s
+; RUN: opt < %s -passes='simplifycfg<no-keep-loops;switch-to-lookup>' -S -mattr=+f | FileCheck %s
+target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
+target triple = "riscv32-unknown-elf"
+
+; The table for @f
+; CHECK: @switch.table.f = private unnamed_addr constant [7 x i32] [i32 55, i32 123, i32 0, i32 -1, i32 27, i32 62, i32 1], align 4
+
+; The table for @foostring
+; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0)], align 4
+
+; A simple int-to-int selection switch.
+; It is dense enough to be replaced by table lookup.
+; The result is directly by a ret from an otherwise empty bb,
+; so we return early, directly from the lookup bb.
+
+define i32 @f(i32 %c) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SWITCH_TABLEIDX:%.*]] = sub i32 [[C:%.*]], 42
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 7
+; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
+; CHECK:       switch.lookup:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], [7 x i32]* @switch.table.f, i32 0, i32 [[SWITCH_TABLEIDX]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i32, i32* [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ 15, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[RETVAL_0]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 42, label %return
+  i32 43, label %sw.bb1
+  i32 44, label %sw.bb2
+  i32 45, label %sw.bb3
+  i32 46, label %sw.bb4
+  i32 47, label %sw.bb5
+  i32 48, label %sw.bb6
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+
+}
+
+; Same thing, but with i8's
+
+define i8 @char(i32 %c) {
+; CHECK-LABEL: @char(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 42, label [[RETURN:%.*]]
+; CHECK-NEXT:    i32 43, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 44, label [[SW_BB2:%.*]]
+; CHECK-NEXT:    i32 45, label [[SW_BB3:%.*]]
+; CHECK-NEXT:    i32 46, label [[SW_BB4:%.*]]
+; CHECK-NEXT:    i32 47, label [[SW_BB5:%.*]]
+; CHECK-NEXT:    i32 48, label [[SW_BB6:%.*]]
+; CHECK-NEXT:    i32 49, label [[SW_BB7:%.*]]
+; CHECK-NEXT:    i32 50, label [[SW_BB8:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb3:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb4:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb5:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb6:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb7:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb8:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i8 [ 15, [[SW_DEFAULT]] ], [ 84, [[SW_BB8]] ], [ 33, [[SW_BB7]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i8 [[RETVAL_0]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 42, label %return
+  i32 43, label %sw.bb1
+  i32 44, label %sw.bb2
+  i32 45, label %sw.bb3
+  i32 46, label %sw.bb4
+  i32 47, label %sw.bb5
+  i32 48, label %sw.bb6
+  i32 49, label %sw.bb7
+  i32 50, label %sw.bb8
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.bb7: br label %return
+sw.bb8: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i8 [ 15, %sw.default ], [ 84, %sw.bb8 ], [ 33, %sw.bb7 ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i8 %retval.0
+
+}
+
+; A switch used to initialize two variables, an i8 and a float.
+
+declare void @dummy(i8 signext, float)
+define void @h(i32 %x) {
+; CHECK-LABEL: @h(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 0, label [[SW_EPILOG:%.*]]
+; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT:    i32 3, label [[SW_BB3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb3:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.epilog:
+; CHECK-NEXT:    [[A_0:%.*]] = phi i8 [ 7, [[SW_DEFAULT]] ], [ 5, [[SW_BB3]] ], [ 88, [[SW_BB2]] ], [ 9, [[SW_BB1]] ], [ 42, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[B_0:%.*]] = phi float [ 0x4023FAE140000000, [[SW_DEFAULT]] ], [ 0x4001AE1480000000, [[SW_BB3]] ], [ 0x4012449BA0000000, [[SW_BB2]] ], [ 0x3FF3BE76C0000000, [[SW_BB1]] ], [ 0x40091EB860000000, [[ENTRY]] ]
+; CHECK-NEXT:    call void @dummy(i8 signext [[A_0]], float [[B_0]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %x, label %sw.default [
+  i32 0, label %sw.epilog
+  i32 1, label %sw.bb1
+  i32 2, label %sw.bb2
+  i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+
+sw.epilog:
+  %a.0 = phi i8 [ 7, %sw.default ], [ 5, %sw.bb3 ], [ 88, %sw.bb2 ], [ 9, %sw.bb1 ], [ 42, %entry ]
+  %b.0 = phi float [ 0x4023FAE140000000, %sw.default ], [ 0x4001AE1480000000, %sw.bb3 ], [ 0x4012449BA0000000, %sw.bb2 ], [ 0x3FF3BE76C0000000, %sw.bb1 ], [ 0x40091EB860000000, %entry ]
+  call void @dummy(i8 signext %a.0, float %b.0)
+  ret void
+
+}
+
+
+; Switch used to return a string.
+
+ at .str = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+ at .str1 = private unnamed_addr constant [4 x i8] c"bar\00", align 1
+ at .str2 = private unnamed_addr constant [4 x i8] c"baz\00", align 1
+ at .str3 = private unnamed_addr constant [4 x i8] c"qux\00", align 1
+ at .str4 = private unnamed_addr constant [6 x i8] c"error\00", align 1
+
+define i8* @foostring(i32 %x)  {
+; CHECK-LABEL: @foostring(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
+; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
+; CHECK:       switch.lookup:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i8*], [4 x i8*]* @switch.table.foostring, i32 0, i32 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i8*, i8** [[SWITCH_GEP]], align 4
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i8* [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i8* [[RETVAL_0]]
+;
+entry:
+  switch i32 %x, 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: br label %return
+
+return:
+  %retval.0 = phi i8* [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), %sw.default ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0), %sw.bb3 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), %sw.bb2 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), %sw.bb1 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ]
+  ret i8* %retval.0
+
+}

diff  --git a/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll
new file mode 100644
index 0000000000000..867b84d974c2d
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/RISCV/switch_to_lookup_table-rv64.ll
@@ -0,0 +1,225 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -simplifycfg -switch-to-lookup=true -keep-loops=false -S -mattr=+f | FileCheck %s
+; RUN: opt < %s -passes='simplifycfg<no-keep-loops;switch-to-lookup>' -S -mattr=+f | FileCheck %s
+target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
+target triple = "riscv64-unknown-elf"
+
+; The table for @foostring
+; CHECK: @switch.table.foostring = private unnamed_addr constant [4 x i8*] [i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0)], align 8
+
+; A simple int-to-int selection switch.
+; It is dense enough to be replaced by table lookup.
+; The result is directly by a ret from an otherwise empty bb,
+; so we return early, directly from the lookup bb.
+
+define i32 @f(i32 %c) {
+; CHECK-LABEL: @f(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 42, label [[RETURN:%.*]]
+; CHECK-NEXT:    i32 43, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 44, label [[SW_BB2:%.*]]
+; CHECK-NEXT:    i32 45, label [[SW_BB3:%.*]]
+; CHECK-NEXT:    i32 46, label [[SW_BB4:%.*]]
+; CHECK-NEXT:    i32 47, label [[SW_BB5:%.*]]
+; CHECK-NEXT:    i32 48, label [[SW_BB6:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb3:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb4:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb5:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb6:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 15, [[SW_DEFAULT]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[RETVAL_0]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 42, label %return
+  i32 43, label %sw.bb1
+  i32 44, label %sw.bb2
+  i32 45, label %sw.bb3
+  i32 46, label %sw.bb4
+  i32 47, label %sw.bb5
+  i32 48, label %sw.bb6
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i32 [ 15, %sw.default ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i32 %retval.0
+
+}
+
+; Same thing, but with i8's
+
+define i8 @char(i32 %c) {
+; CHECK-LABEL: @char(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[C:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 42, label [[RETURN:%.*]]
+; CHECK-NEXT:    i32 43, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 44, label [[SW_BB2:%.*]]
+; CHECK-NEXT:    i32 45, label [[SW_BB3:%.*]]
+; CHECK-NEXT:    i32 46, label [[SW_BB4:%.*]]
+; CHECK-NEXT:    i32 47, label [[SW_BB5:%.*]]
+; CHECK-NEXT:    i32 48, label [[SW_BB6:%.*]]
+; CHECK-NEXT:    i32 49, label [[SW_BB7:%.*]]
+; CHECK-NEXT:    i32 50, label [[SW_BB8:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb3:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb4:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb5:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb6:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb7:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.bb8:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i8 [ 15, [[SW_DEFAULT]] ], [ 84, [[SW_BB8]] ], [ 33, [[SW_BB7]] ], [ 1, [[SW_BB6]] ], [ 62, [[SW_BB5]] ], [ 27, [[SW_BB4]] ], [ -1, [[SW_BB3]] ], [ 0, [[SW_BB2]] ], [ 123, [[SW_BB1]] ], [ 55, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i8 [[RETVAL_0]]
+;
+entry:
+  switch i32 %c, label %sw.default [
+  i32 42, label %return
+  i32 43, label %sw.bb1
+  i32 44, label %sw.bb2
+  i32 45, label %sw.bb3
+  i32 46, label %sw.bb4
+  i32 47, label %sw.bb5
+  i32 48, label %sw.bb6
+  i32 49, label %sw.bb7
+  i32 50, label %sw.bb8
+  ]
+
+sw.bb1: br label %return
+sw.bb2: br label %return
+sw.bb3: br label %return
+sw.bb4: br label %return
+sw.bb5: br label %return
+sw.bb6: br label %return
+sw.bb7: br label %return
+sw.bb8: br label %return
+sw.default: br label %return
+return:
+  %retval.0 = phi i8 [ 15, %sw.default ], [ 84, %sw.bb8 ], [ 33, %sw.bb7 ], [ 1, %sw.bb6 ], [ 62, %sw.bb5 ], [ 27, %sw.bb4 ], [ -1, %sw.bb3 ], [ 0, %sw.bb2 ], [ 123, %sw.bb1 ], [ 55, %entry ]
+  ret i8 %retval.0
+
+}
+
+; A switch used to initialize two variables, an i8 and a float.
+
+declare void @dummy(i8 signext, float)
+define void @h(i32 %x) {
+; CHECK-LABEL: @h(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
+; CHECK-NEXT:    i32 0, label [[SW_EPILOG:%.*]]
+; CHECK-NEXT:    i32 1, label [[SW_BB1:%.*]]
+; CHECK-NEXT:    i32 2, label [[SW_BB2:%.*]]
+; CHECK-NEXT:    i32 3, label [[SW_BB3:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       sw.bb1:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb2:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.bb3:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.default:
+; CHECK-NEXT:    br label [[SW_EPILOG]]
+; CHECK:       sw.epilog:
+; CHECK-NEXT:    [[A_0:%.*]] = phi i8 [ 7, [[SW_DEFAULT]] ], [ 5, [[SW_BB3]] ], [ 88, [[SW_BB2]] ], [ 9, [[SW_BB1]] ], [ 42, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[B_0:%.*]] = phi float [ 0x4023FAE140000000, [[SW_DEFAULT]] ], [ 0x4001AE1480000000, [[SW_BB3]] ], [ 0x4012449BA0000000, [[SW_BB2]] ], [ 0x3FF3BE76C0000000, [[SW_BB1]] ], [ 0x40091EB860000000, [[ENTRY]] ]
+; CHECK-NEXT:    call void @dummy(i8 signext [[A_0]], float [[B_0]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  switch i32 %x, label %sw.default [
+  i32 0, label %sw.epilog
+  i32 1, label %sw.bb1
+  i32 2, label %sw.bb2
+  i32 3, label %sw.bb3
+  ]
+
+sw.bb1: br label %sw.epilog
+sw.bb2: br label %sw.epilog
+sw.bb3: br label %sw.epilog
+sw.default: br label %sw.epilog
+
+sw.epilog:
+  %a.0 = phi i8 [ 7, %sw.default ], [ 5, %sw.bb3 ], [ 88, %sw.bb2 ], [ 9, %sw.bb1 ], [ 42, %entry ]
+  %b.0 = phi float [ 0x4023FAE140000000, %sw.default ], [ 0x4001AE1480000000, %sw.bb3 ], [ 0x4012449BA0000000, %sw.bb2 ], [ 0x3FF3BE76C0000000, %sw.bb1 ], [ 0x40091EB860000000, %entry ]
+  call void @dummy(i8 signext %a.0, float %b.0)
+  ret void
+
+}
+
+
+; Switch used to return a string.
+
+ at .str = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+ at .str1 = private unnamed_addr constant [4 x i8] c"bar\00", align 1
+ at .str2 = private unnamed_addr constant [4 x i8] c"baz\00", align 1
+ at .str3 = private unnamed_addr constant [4 x i8] c"qux\00", align 1
+ at .str4 = private unnamed_addr constant [6 x i8] c"error\00", align 1
+
+define i8* @foostring(i32 %x)  {
+; CHECK-LABEL: @foostring(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[X:%.*]], 4
+; CHECK-NEXT:    br i1 [[TMP0]], label [[SWITCH_LOOKUP:%.*]], label [[RETURN:%.*]]
+; CHECK:       switch.lookup:
+; CHECK-NEXT:    [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i8*], [4 x i8*]* @switch.table.foostring, i32 0, i32 [[X]]
+; CHECK-NEXT:    [[SWITCH_LOAD:%.*]] = load i8*, i8** [[SWITCH_GEP]], align 8
+; CHECK-NEXT:    br label [[RETURN]]
+; CHECK:       return:
+; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i8* [ [[SWITCH_LOAD]], [[SWITCH_LOOKUP]] ], [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i8* [[RETVAL_0]]
+;
+entry:
+  switch i32 %x, 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: br label %return
+
+return:
+  %retval.0 = phi i8* [ getelementptr inbounds ([6 x i8], [6 x i8]* @.str4, i64 0, i64 0), %sw.default ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str3, i64 0, i64 0), %sw.bb3 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str2, i64 0, i64 0), %sw.bb2 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), %sw.bb1 ],
+  [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ]
+  ret i8* %retval.0
+
+}


        


More information about the llvm-commits mailing list