forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			235 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
| // 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;
 | |
|   }
 | |
| }
 | |
| 
 |