You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			179 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			LLVM
		
	
	
	
	
	
| ; Test the behavior of GlobalDCE in conjunction with comdats.
 | |
| ;
 | |
| ; RUN: opt < %s -globaldce -S | FileCheck %s
 | |
| 
 | |
| ; First test checks that if one function in a comdat group is used, both other
 | |
| ; functions and other globals even if unused will be preserved.
 | |
| $test1_c = comdat any
 | |
| ; CHECK: $test1_c = comdat any
 | |
| 
 | |
| ; Second test checks that if one function in a comdat group is used, both other
 | |
| ; functions and other globals even if unused will be preserved.
 | |
| $test2_c = comdat any
 | |
| ; CHECK: $test2_c = comdat any
 | |
| 
 | |
| ; Third test checks that calling a function in a comdat group with an alias
 | |
| ; preserves the alias.
 | |
| $test3_c = comdat any
 | |
| ; CHECK: $test3_c = comdat any
 | |
| 
 | |
| ; Fourth test checks that calling an alias in a comdat group with a function
 | |
| ; preserves the function. (This is the trivial case as the alias uses the
 | |
| ; function.)
 | |
| $test4_c = comdat any
 | |
| ; CHECK: $test4_c = comdat any
 | |
| 
 | |
| ; Fifth test checks that calling a function in a comdat group that is used as
 | |
| ; the resolver of an ifunc doesn't preserve that ifunc. ifunc symbols don't
 | |
| ; participate in the comdat group of their resolver function as they are
 | |
| ; considered separate objects.
 | |
| $test5_c = comdat any
 | |
| ; CHECK: $test5_c = comdat any
 | |
| 
 | |
| ; Sixth test checks that calling an ifunc whose resolver is in a comdat group
 | |
| ; preserves the resolver. This is the trivial case as the ifunc uses the
 | |
| ; resolver.
 | |
| $test6_c = comdat any
 | |
| ; CHECK: $test6_c = comdat any
 | |
| 
 | |
| ; Seventh test checks that we can eliminate a comdat when it has only one dead function participant.
 | |
| $test7_c = comdat any
 | |
| ; CHECK-NOT: $test7_c = comdat any
 | |
| 
 | |
| ; Eighth test checks that we can eliminate a comdat when it has only one dead global participant.
 | |
| $test8_c = comdat any
 | |
| ; CHECK-NOT: $test8_c = comdat any
 | |
| 
 | |
| ; Ninth test checks that we can eliminate a comdat when there are multiple
 | |
| ; dead participants.
 | |
| $test9_c = comdat any
 | |
| ; CHECK-NOT: $test9_c = comdat any
 | |
| 
 | |
| ; Tenth test checks that we can eliminate a comdat when it has multiple
 | |
| ; participants that form internal cyclic uses but are never used externally and
 | |
| ; thus the entire ifunc can safely be eliminated.
 | |
| $test10_c = comdat any
 | |
| ; CHECK-NOT: $test10_c = comdat any
 | |
| 
 | |
| @test1_gv = linkonce_odr unnamed_addr global i32 42, comdat($test1_c)
 | |
| ; CHECK: @test1_gv = linkonce_odr unnamed_addr global
 | |
| 
 | |
| @test2_used = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
 | |
| ; CHECK: @test2_used = linkonce_odr unnamed_addr global
 | |
| 
 | |
| @test2_gv = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
 | |
| ; CHECK: @test2_gv = linkonce_odr unnamed_addr global
 | |
| 
 | |
| @test8_gv = linkonce_odr unnamed_addr global i32 42, comdat($test8_c)
 | |
| ; CHECK-NOT: @test8_gv
 | |
| 
 | |
| @test9_gv = linkonce_odr unnamed_addr global i32 42, comdat($test9_c)
 | |
| ; CHECK-NOT: @test9_gv
 | |
| 
 | |
| @test10_gv = linkonce_odr unnamed_addr global void ()* @test10_f, comdat($test10_c)
 | |
| ; CHECK-NOT: @test10_gv
 | |
| 
 | |
| @test3_a = linkonce_odr unnamed_addr alias void (), void ()* @test3_f
 | |
| ; CHECK: @test3_a = linkonce_odr unnamed_addr alias
 | |
| 
 | |
| @test4_a = linkonce_odr unnamed_addr alias void (), void ()* @test4_f
 | |
| ; CHECK: @test4_a = linkonce_odr unnamed_addr alias
 | |
| 
 | |
| @test10_a = linkonce_odr unnamed_addr alias void (), void ()* @test10_g
 | |
| ; CHECK-NOT: @test10_a
 | |
| 
 | |
| @test5_if = linkonce_odr ifunc void (), void ()* ()* @test5_f
 | |
| ; CHECK-NOT: @test5_if
 | |
| 
 | |
| @test6_if = linkonce_odr ifunc void (), void ()* ()* @test6_f
 | |
| ; CHECK: @test6_if = linkonce_odr ifunc
 | |
| 
 | |
| ; This function is directly used and so cannot be eliminated.
 | |
| define linkonce_odr void @test1_used() comdat($test1_c) {
 | |
| ; CHECK: define linkonce_odr void @test1_used()
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test1_f() comdat($test1_c) {
 | |
| ; CHECK: define linkonce_odr void @test1_f()
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| ; Now test that a function, global variable, alias, and ifunc in the same
 | |
| ; comdat are kept.
 | |
| define linkonce_odr void @test2_f() comdat($test2_c) {
 | |
| ; CHECK: define linkonce_odr void @test2_f()
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test3_f() comdat($test3_c) {
 | |
| ; CHECK: define linkonce_odr void @test3_f()
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test4_f() comdat($test4_c) {
 | |
| ; CHECK: define linkonce_odr void @test4_f()
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| declare void @test_external()
 | |
| 
 | |
| define linkonce_odr void ()* @test5_f() comdat($test5_c) {
 | |
| ; CHECK: define linkonce_odr void ()* @test5_f()
 | |
| entry:
 | |
|   ret void ()* @test_external
 | |
| }
 | |
| 
 | |
| define linkonce_odr void ()* @test6_f() comdat($test6_c) {
 | |
| ; CHECK: define linkonce_odr void ()* @test6_f()
 | |
| entry:
 | |
|   ret void ()* @test_external
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test7_f() comdat($test7_c) {
 | |
| ; CHECK-NOT: @test7_f
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test9_f() comdat($test9_c) {
 | |
| ; CHECK-NOT: @test9_f
 | |
| entry:
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test10_f() comdat($test10_c) {
 | |
| ; CHECK-NOT: @test10_f
 | |
| entry:
 | |
|   %gv = load void ()*, void ()** @test10_gv
 | |
|   call void @test10_a()
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| define linkonce_odr void @test10_g() comdat($test10_c) {
 | |
| ; CHECK-NOT: @test10_g
 | |
| entry:
 | |
|   call void @test10_f()
 | |
|   ret void
 | |
| }
 | |
| 
 | |
| 
 | |
| ; An external function to pin as "used" various things above that shouldn't be
 | |
| ; eliminated.
 | |
| define void @external_user() {
 | |
|   call void @test1_used()
 | |
|   %gv = load i32, i32* @test2_used
 | |
| 
 | |
|   call void @test3_f()
 | |
|   call void @test4_a()
 | |
| 
 | |
|   %fptr = call void() *@test5_f()
 | |
|   call void @test6_if()
 | |
|   ret void
 | |
| }
 |