diff options
Diffstat (limited to 'clang/test/CodeGen/switch-dce.c')
-rw-r--r-- | clang/test/CodeGen/switch-dce.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/clang/test/CodeGen/switch-dce.c b/clang/test/CodeGen/switch-dce.c new file mode 100644 index 0000000..a18d3bc --- /dev/null +++ b/clang/test/CodeGen/switch-dce.c @@ -0,0 +1,234 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -O0 %s -emit-llvm -o - | FileCheck %s + +// PR9322 and rdar://6970405 + +// CHECK: @test1 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 {{.*}}, 1 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +int i; +void dead(); + +void test1() { + switch (1) + case 1: + ++i; + + switch (0) + case 1: + dead(); +} + + +// CHECK: @test2 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 {{.*}}, 2 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test2() { + switch (4) { + case 1: + dead(); + break; + case 4: + i += 2; + // Fall off the end of the switch. + } +} + + +// CHECK: @test3 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 {{.*}}, 2 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test3() { + switch (4) { + case 1: + dead(); + break; + case 4: { + i += 2; + break; + } + } +} + +// CHECK: @test4 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 {{.*}}, 2 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test4() { + switch (4) { + case 1: + dead(); + break; + default: { + i += 2; + break; + } + } +} + +// This shouldn't crash codegen, but we don't have to optimize out the switch +// in this case. +void test5() { + switch (1) { + int x; // eliding var decl? + case 1: + x = 4; + i = x; + break; + } +} + +// CHECK: @test6 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test6() { + // Neither case is reachable. + switch (40) { + case 1: + dead(); + break; + case 4: { + dead(); + break; + } + } +} + +// CHECK: @test7 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test7() { + switch (4) { + case 1: + dead(); + break; + { + case 4: // crazy brace scenario + ++i; + } + break; + } +} + +// CHECK: @test8 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test8() { + switch (4) { + case 1: + dead(); + break; + case 4: + ++i; + // Fall off the end of the switch. + } +} + +// CHECK: @test9 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: add nsw i32 +// CHECK: add nsw i32 +// CHECK-NOT: switch +// CHECK-NOT: @dead +// CHECK: ret void +void test9(int i) { + switch (1) { + case 5: + dead(); + case 1: + ++i; + // Fall through is fine. + case 4: + ++i; + break; + } +} + +// CHECK: @test10 +// CHECK-NOT: switch +// CHECK: ret i32 +int test10(void) { + switch(8) { + case 8: + break; + case 4: + break; + default: + dead(); + } + + return 0; +} + +// CHECK: @test11 +// CHECK-NOT: switch +// CHECK: ret void +void test11() { + switch (1) { + case 1: + break; + case 42: ; + int x; // eliding var decl? + x = 4; + break; + } +} + +// CHECK: @test12 +// CHECK-NOT: switch +// CHECK: ret void +void test12() { + switch (1) { + case 2: { + int a; // Ok to skip this vardecl. + a = 42; + } + case 1: + break; + case 42: ; + int x; // eliding var decl? + x = 4; + break; + } +} + +// Verify that case 42 only calls test14 once. +// CHECK: @test13 +// CHECK: call void @test13(i32 97) +// CHECK-NEXT: br label %[[EPILOG2:[0-9.a-z]+]] +// CHECK: [[EPILOG2]] +// CHECK-NEXT: br label [[EPILOG:%[0-9.a-z]+]] +// CHECK: call void @test13(i32 42) +// CHECK-NEXT: br label [[EPILOG]] +void test13(int x) { + switch (x) { + case 42: test13(97); // fallthrough + case 11: break; + default: test13(42); break; + } +} + |