1; Test the behavior of GlobalDCE in conjunction with comdats.
2;
3; RUN: opt < %s -globaldce -S | FileCheck %s
4
5; First test checks that if one function in a comdat group is used, both other
6; functions and other globals even if unused will be preserved.
7$test1_c = comdat any
8; CHECK: $test1_c = comdat any
9
10; Second test checks that if one function in a comdat group is used, both other
11; functions and other globals even if unused will be preserved.
12$test2_c = comdat any
13; CHECK: $test2_c = comdat any
14
15; Third test checks that calling a function in a comdat group with an alias
16; preserves the alias.
17$test3_c = comdat any
18; CHECK: $test3_c = comdat any
19
20; Fourth test checks that calling an alias in a comdat group with a function
21; preserves the function. (This is the trivial case as the alias uses the
22; function.)
23$test4_c = comdat any
24; CHECK: $test4_c = comdat any
25
26; Fifth test checks that calling a function in a comdat group that is used as
27; the resolver of an ifunc doesn't preserve that ifunc. ifunc symbols don't
28; participate in the comdat group of their resolver function as they are
29; considered separate objects.
30$test5_c = comdat any
31; CHECK: $test5_c = comdat any
32
33; Sixth test checks that calling an ifunc whose resolver is in a comdat group
34; preserves the resolver. This is the trivial case as the ifunc uses the
35; resolver.
36$test6_c = comdat any
37; CHECK: $test6_c = comdat any
38
39; Seventh test checks that we can eliminate a comdat when it has only one dead function participant.
40$test7_c = comdat any
41; CHECK-NOT: $test7_c = comdat any
42
43; Eighth test checks that we can eliminate a comdat when it has only one dead global participant.
44$test8_c = comdat any
45; CHECK-NOT: $test8_c = comdat any
46
47; Ninth test checks that we can eliminate a comdat when there are multiple
48; dead participants.
49$test9_c = comdat any
50; CHECK-NOT: $test9_c = comdat any
51
52; Tenth test checks that we can eliminate a comdat when it has multiple
53; participants that form internal cyclic uses but are never used externally and
54; thus the entire ifunc can safely be eliminated.
55$test10_c = comdat any
56; CHECK-NOT: $test10_c = comdat any
57
58@test1_gv = linkonce_odr unnamed_addr global i32 42, comdat($test1_c)
59; CHECK: @test1_gv = linkonce_odr unnamed_addr global
60
61@test2_used = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
62; CHECK: @test2_used = linkonce_odr unnamed_addr global
63
64@test2_gv = linkonce_odr unnamed_addr global i32 42, comdat($test2_c)
65; CHECK: @test2_gv = linkonce_odr unnamed_addr global
66
67@test8_gv = linkonce_odr unnamed_addr global i32 42, comdat($test8_c)
68; CHECK-NOT: @test8_gv
69
70@test9_gv = linkonce_odr unnamed_addr global i32 42, comdat($test9_c)
71; CHECK-NOT: @test9_gv
72
73@test10_gv = linkonce_odr unnamed_addr global void ()* @test10_f, comdat($test10_c)
74; CHECK-NOT: @test10_gv
75
76@test3_a = linkonce_odr unnamed_addr alias void (), void ()* @test3_f
77; CHECK: @test3_a = linkonce_odr unnamed_addr alias
78
79@test4_a = linkonce_odr unnamed_addr alias void (), void ()* @test4_f
80; CHECK: @test4_a = linkonce_odr unnamed_addr alias
81
82@test10_a = linkonce_odr unnamed_addr alias void (), void ()* @test10_g
83; CHECK-NOT: @test10_a
84
85@test5_if = linkonce_odr ifunc void (), void ()* ()* @test5_f
86; CHECK-NOT: @test5_if
87
88@test6_if = linkonce_odr ifunc void (), void ()* ()* @test6_f
89; CHECK: @test6_if = linkonce_odr ifunc
90
91; This function is directly used and so cannot be eliminated.
92define linkonce_odr void @test1_used() comdat($test1_c) {
93; CHECK: define linkonce_odr void @test1_used()
94entry:
95  ret void
96}
97
98define linkonce_odr void @test1_f() comdat($test1_c) {
99; CHECK: define linkonce_odr void @test1_f()
100entry:
101  ret void
102}
103
104; Now test that a function, global variable, alias, and ifunc in the same
105; comdat are kept.
106define linkonce_odr void @test2_f() comdat($test2_c) {
107; CHECK: define linkonce_odr void @test2_f()
108entry:
109  ret void
110}
111
112define linkonce_odr void @test3_f() comdat($test3_c) {
113; CHECK: define linkonce_odr void @test3_f()
114entry:
115  ret void
116}
117
118define linkonce_odr void @test4_f() comdat($test4_c) {
119; CHECK: define linkonce_odr void @test4_f()
120entry:
121  ret void
122}
123
124declare void @test_external()
125
126define linkonce_odr void ()* @test5_f() comdat($test5_c) {
127; CHECK: define linkonce_odr void ()* @test5_f()
128entry:
129  ret void ()* @test_external
130}
131
132define linkonce_odr void ()* @test6_f() comdat($test6_c) {
133; CHECK: define linkonce_odr void ()* @test6_f()
134entry:
135  ret void ()* @test_external
136}
137
138define linkonce_odr void @test7_f() comdat($test7_c) {
139; CHECK-NOT: @test7_f
140entry:
141  ret void
142}
143
144define linkonce_odr void @test9_f() comdat($test9_c) {
145; CHECK-NOT: @test9_f
146entry:
147  ret void
148}
149
150define linkonce_odr void @test10_f() comdat($test10_c) {
151; CHECK-NOT: @test10_f
152entry:
153  %gv = load void ()*, void ()** @test10_gv
154  call void @test10_a()
155  ret void
156}
157
158define linkonce_odr void @test10_g() comdat($test10_c) {
159; CHECK-NOT: @test10_g
160entry:
161  call void @test10_f()
162  ret void
163}
164
165
166; An external function to pin as "used" various things above that shouldn't be
167; eliminated.
168define void @external_user() {
169  call void @test1_used()
170  %gv = load i32, i32* @test2_used
171
172  call void @test3_f()
173  call void @test4_a()
174
175  %fptr = call void() *@test5_f()
176  call void @test6_if()
177  ret void
178}
179