xref: /llvm-project/clang/test/CodeGen/attr-target-clones.c (revision 6c12fd91540fe2f86b5032b10f04b74910b4c411)
1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LINUX,CHECK
2 // RUN: %clang_cc1 -triple x86_64-apple-macos -emit-llvm %s -o - | FileCheck %s --check-prefixes=DARWIN,CHECK
3 // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefixes=WINDOWS,CHECK
4 
5 // LINUX: $foo.resolver = comdat any
6 // LINUX: $foo_dupes.resolver = comdat any
7 // LINUX: $unused.resolver = comdat any
8 // LINUX: $foo_inline.resolver = comdat any
9 // LINUX: $foo_inline2.resolver = comdat any
10 
11 // DARWIN-NOT: comdat any
12 
13 // WINDOWS: $foo = comdat any
14 // WINDOWS: $foo_dupes = comdat any
15 // WINDOWS: $unused = comdat any
16 // WINDOWS: $foo_inline = comdat any
17 // WINDOWS: $foo_inline2 = comdat any
18 
19 // LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
20 // LINUX: @__cpu_features2 = external dso_local global [3 x i32]
21 
22 // DARWIN: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
23 // DARWIN: @__cpu_features2 = external dso_local global [3 x i32]
24 
25 // LINUX: @internal.ifunc = internal alias i32 (), ptr @internal
26 // LINUX: @foo.ifunc = weak_odr alias i32 (), ptr @foo
27 // LINUX: @foo_dupes.ifunc = weak_odr alias void (), ptr @foo_dupes
28 // LINUX: @unused.ifunc = weak_odr alias void (), ptr @unused
29 // LINUX: @foo_inline.ifunc = weak_odr alias i32 (), ptr @foo_inline
30 // LINUX: @foo_inline2.ifunc = weak_odr alias i32 (), ptr @foo_inline2
31 // LINUX: @foo_used_no_defn.ifunc = weak_odr alias i32 (), ptr @foo_used_no_defn
32 // LINUX: @isa_level.ifunc = weak_odr alias i32 (i32), ptr @isa_level
33 
34 // LINUX: @internal = internal ifunc i32 (), ptr @internal.resolver
35 // LINUX: @foo = weak_odr ifunc i32 (), ptr @foo.resolver
36 // LINUX: @foo_dupes = weak_odr ifunc void (), ptr @foo_dupes.resolver
37 // LINUX: @unused = weak_odr ifunc void (), ptr @unused.resolver
38 // LINUX: @foo_inline = weak_odr ifunc i32 (), ptr @foo_inline.resolver
39 // LINUX: @foo_inline2 = weak_odr ifunc i32 (), ptr @foo_inline2.resolver
40 // LINUX: @foo_used_no_defn = weak_odr ifunc i32 (), ptr @foo_used_no_defn.resolver
41 // LINUX: @isa_level = weak_odr ifunc i32 (i32), ptr @isa_level.resolver
42 
43 
internal(void)44 static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }
use(void)45 int use(void) { return internal(); }
46 /// Internal linkage resolvers do not use comdat.
47 // LINUX: define internal ptr @internal.resolver() {
48 // DARWIN: define internal ptr @internal.resolver() {
49 // WINDOWS: define internal i32 @internal() {
50 
foo(void)51 int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
52 // LINUX: define {{.*}}i32 @foo.sse4.2.0()
53 // LINUX: define {{.*}}i32 @foo.default.1()
54 // LINUX: define weak_odr ptr @foo.resolver() comdat
55 // LINUX: ret ptr @foo.sse4.2.0
56 // LINUX: ret ptr @foo.default.1
57 
58 // DARWIN: define {{.*}}i32 @foo.sse4.2.0()
59 // DARWIN: define {{.*}}i32 @foo.default.1()
60 // DARWIN: define weak_odr ptr @foo.resolver() {
61 // DARWIN: ret ptr @foo.sse4.2.0
62 // DARWIN: ret ptr @foo.default.1
63 
64 // WINDOWS: define dso_local i32 @foo.sse4.2.0()
65 // WINDOWS: define dso_local i32 @foo.default.1()
66 // WINDOWS: define weak_odr dso_local i32 @foo() comdat
67 // WINDOWS: musttail call i32 @foo.sse4.2.0
68 // WINDOWS: musttail call i32 @foo.default.1
69 
foo_dupes(void)70 __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {}
71 // LINUX: define {{.*}}void @foo_dupes.default.1()
72 // LINUX: define {{.*}}void @foo_dupes.sse4.2.0()
73 // LINUX: define weak_odr ptr @foo_dupes.resolver() comdat
74 // LINUX: ret ptr @foo_dupes.sse4.2.0
75 // LINUX: ret ptr @foo_dupes.default.1
76 
77 // DARWIN: define {{.*}}void @foo_dupes.default.1()
78 // DARWIN: define {{.*}}void @foo_dupes.sse4.2.0()
79 // DARWIN: define weak_odr ptr @foo_dupes.resolver() {
80 // DARWIN: ret ptr @foo_dupes.sse4.2.0
81 // DARWIN: ret ptr @foo_dupes.default.1
82 
83 // WINDOWS: define dso_local void @foo_dupes.default.1()
84 // WINDOWS: define dso_local void @foo_dupes.sse4.2.0()
85 // WINDOWS: define weak_odr dso_local void @foo_dupes() comdat
86 // WINDOWS: musttail call void @foo_dupes.sse4.2.0
87 // WINDOWS: musttail call void @foo_dupes.default.1
88 
bar2(void)89 void bar2(void) {
90   // LINUX: define {{.*}}void @bar2()
91   // DARWIN: define {{.*}}void @bar2()
92   // WINDOWS: define dso_local void @bar2()
93   foo_dupes();
94   // LINUX: call void @foo_dupes()
95   // DARWIN: call void @foo_dupes()
96   // WINDOWS: call void @foo_dupes()
97 }
98 
bar(void)99 int bar(void) {
100   // LINUX: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]
101   // DARWIN: define {{.*}}i32 @bar() #[[DEF:[0-9]+]]
102   // WINDOWS: define dso_local i32 @bar() #[[DEF:[0-9]+]]
103   return foo();
104   // LINUX: call i32 @foo()
105   // DARWIN: call i32 @foo()
106   // WINDOWS: call i32 @foo()
107 }
108 
unused(void)109 void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}
110 // LINUX: define {{.*}}void @unused.default.1()
111 // LINUX: define {{.*}}void @unused.arch_ivybridge.0()
112 // LINUX: define weak_odr ptr @unused.resolver() comdat
113 // LINUX: ret ptr @unused.arch_ivybridge.0
114 // LINUX: ret ptr @unused.default.1
115 
116 // DARWIN: define {{.*}}void @unused.default.1()
117 // DARWIN: define {{.*}}void @unused.arch_ivybridge.0()
118 // DARWIN: define weak_odr ptr @unused.resolver() {
119 // DARWIN: ret ptr @unused.arch_ivybridge.0
120 // DARWIN: ret ptr @unused.default.1
121 
122 // WINDOWS: define dso_local void @unused.default.1()
123 // WINDOWS: define dso_local void @unused.arch_ivybridge.0()
124 // WINDOWS: define weak_odr dso_local void @unused() comdat
125 // WINDOWS: musttail call void @unused.arch_ivybridge.0
126 // WINDOWS: musttail call void @unused.default.1
127 
128 
129 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
foo_inline(void)130 foo_inline(void) { return 0; }
131 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
132 foo_inline2(void);
133 
bar3(void)134 int bar3(void) {
135   // LINUX: define {{.*}}i32 @bar3()
136   // DARWIN: define {{.*}}i32 @bar3()
137   // WINDOWS: define dso_local i32 @bar3()
138   return foo_inline() + foo_inline2();
139   // LINUX: call i32 @foo_inline()
140   // LINUX: call i32 @foo_inline2()
141   // DARWIN: call i32 @foo_inline()
142   // DARWIN: call i32 @foo_inline2()
143   // WINDOWS: call i32 @foo_inline()
144   // WINDOWS: call i32 @foo_inline2()
145 }
146 
147 // LINUX: define weak_odr ptr @foo_inline.resolver() comdat
148 // LINUX: ret ptr @foo_inline.arch_sandybridge.0
149 // LINUX: ret ptr @foo_inline.sse4.2.1
150 // LINUX: ret ptr @foo_inline.default.2
151 
152 // DARWIN: define weak_odr ptr @foo_inline.resolver() {
153 // DARWIN: ret ptr @foo_inline.arch_sandybridge.0
154 // DARWIN: ret ptr @foo_inline.sse4.2.1
155 // DARWIN: ret ptr @foo_inline.default.2
156 
157 // WINDOWS: define weak_odr dso_local i32 @foo_inline() comdat
158 // WINDOWS: musttail call i32 @foo_inline.arch_sandybridge.0
159 // WINDOWS: musttail call i32 @foo_inline.sse4.2.1
160 // WINDOWS: musttail call i32 @foo_inline.default.2
161 
162 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
foo_inline2(void)163 foo_inline2(void){ return 0; }
164 // LINUX: define weak_odr ptr @foo_inline2.resolver() comdat
165 // LINUX: ret ptr @foo_inline2.arch_sandybridge.0
166 // LINUX: ret ptr @foo_inline2.sse4.2.1
167 // LINUX: ret ptr @foo_inline2.default.2
168 
169 // DARWIN: define weak_odr ptr @foo_inline2.resolver() {
170 // DARWIN: ret ptr @foo_inline2.arch_sandybridge.0
171 // DARWIN: ret ptr @foo_inline2.sse4.2.1
172 // DARWIN: ret ptr @foo_inline2.default.2
173 
174 // WINDOWS: define weak_odr dso_local i32 @foo_inline2() comdat
175 // WINDOWS: musttail call i32 @foo_inline2.arch_sandybridge.0
176 // WINDOWS: musttail call i32 @foo_inline2.sse4.2.1
177 // WINDOWS: musttail call i32 @foo_inline2.default.2
178 
179 
180 int __attribute__((target_clones("default", "sse4.2")))
181 foo_unused_no_defn(void);
182 
183 int __attribute__((target_clones("default", "sse4.2")))
184 foo_used_no_defn(void);
185 
test_foo_used_no_defn(void)186 int test_foo_used_no_defn(void) {
187   // LINUX: define {{.*}}i32 @test_foo_used_no_defn()
188   // DARWIN: define {{.*}}i32 @test_foo_used_no_defn()
189   // WINDOWS: define dso_local i32 @test_foo_used_no_defn()
190   return foo_used_no_defn();
191   // LINUX: call i32 @foo_used_no_defn()
192   // DARWIN: call i32 @foo_used_no_defn()
193   // WINDOWS: call i32 @foo_used_no_defn()
194 }
195 
196 
197 // LINUX: define weak_odr ptr @foo_used_no_defn.resolver() comdat
198 // LINUX: ret ptr @foo_used_no_defn.sse4.2.0
199 // LINUX: ret ptr @foo_used_no_defn.default.1
200 
201 // DARWIN: define weak_odr ptr @foo_used_no_defn.resolver() {
202 // DARWIN: ret ptr @foo_used_no_defn.sse4.2.0
203 // DARWIN: ret ptr @foo_used_no_defn.default.1
204 
205 // WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() comdat
206 // WINDOWS: musttail call i32 @foo_used_no_defn.sse4.2.0
207 // WINDOWS: musttail call i32 @foo_used_no_defn.default.1
208 
209 __attribute__((target_clones("default", "arch=x86-64", "arch=x86-64-v2", "arch=x86-64-v3", "arch=x86-64-v4")))
isa_level(int)210 int isa_level(int) { return 0; }
211 // LINUX:      define{{.*}} i32 @isa_level.default.4(
212 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64.0(
213 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
214 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
215 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
216 // LINUX:      define weak_odr ptr @isa_level.resolver() comdat
217 // LINUX:        call void @__cpu_indicator_init()
218 // LINUX-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
219 // LINUX-NEXT:   and i32 %[[#]], 4
220 // LINUX:        ret ptr @isa_level.arch_x86-64-v4.3
221 // LINUX:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
222 // LINUX-NEXT:   and i32 %[[#]], 2
223 // LINUX:        ret ptr @isa_level.arch_x86-64-v3.2
224 // LINUX:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
225 // LINUX-NEXT:   and i32 %[[#]], 1
226 // LINUX:        ret ptr @isa_level.arch_x86-64-v2.1
227 // LINUX:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1)
228 // LINUX-NEXT:   and i32 %[[#]], -2147483648
229 // LINUX:        ret ptr @isa_level.arch_x86-64.0
230 // LINUX:        ret ptr @isa_level.default.4
231 
232 // DARWIN:      define{{.*}} i32 @isa_level.default.4(
233 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64.0(
234 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
235 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
236 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
237 // DARWIN:      define weak_odr ptr @isa_level.resolver() {
238 // DARWIN:        call void @__cpu_indicator_init()
239 // DARWIN-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
240 // DARWIN-NEXT:   and i32 %[[#]], 4
241 // DARWIN:        ret ptr @isa_level.arch_x86-64-v4.3
242 // DARWIN:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
243 // DARWIN-NEXT:   and i32 %[[#]], 2
244 // DARWIN:        ret ptr @isa_level.arch_x86-64-v3.2
245 // DARWIN:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
246 // DARWIN-NEXT:   and i32 %[[#]], 1
247 // DARWIN:        ret ptr @isa_level.arch_x86-64-v2.1
248 // DARWIN:        load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 1)
249 // DARWIN-NEXT:   and i32 %[[#]], -2147483648
250 // DARWIN:        ret ptr @isa_level.arch_x86-64.0
251 // DARWIN:        ret ptr @isa_level.default.4
252 
253 // Deferred emission of inline definitions.
254 
255 // LINUX: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
256 // LINUX: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]
257 // LINUX: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]
258 
259 // DARWIN: define linkonce i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
260 // DARWIN: define linkonce i32 @foo_inline.default.2() #[[DEF:[0-9]+]]
261 // DARWIN: define linkonce i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]
262 
263 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_sandybridge.0() #[[SB:[0-9]+]]
264 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline.default.2() #[[DEF]]
265 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2.1() #[[SSE42:[0-9]+]]
266 
267 
268 // LINUX: define linkonce i32 @foo_inline2.arch_sandybridge.0() #[[SB]]
269 // LINUX: define linkonce i32 @foo_inline2.default.2() #[[DEF]]
270 // LINUX: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]
271 
272 // DARWIN: define linkonce i32 @foo_inline2.arch_sandybridge.0() #[[SB]]
273 // DARWIN: define linkonce i32 @foo_inline2.default.2() #[[DEF]]
274 // DARWIN: define linkonce i32 @foo_inline2.sse4.2.1() #[[SSE42]]
275 
276 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.arch_sandybridge.0() #[[SB]]
277 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.default.2() #[[DEF]]
278 // WINDOWS: define linkonce_odr dso_local i32 @foo_inline2.sse4.2.1() #[[SSE42]]
279 
280 
281 // LINUX: declare i32 @foo_used_no_defn.default.1()
282 // LINUX: declare i32 @foo_used_no_defn.sse4.2.0()
283 
284 // DARWIN: declare i32 @foo_used_no_defn.default.1()
285 // DARWIN: declare i32 @foo_used_no_defn.sse4.2.0()
286 
287 // WINDOWS: declare dso_local i32 @foo_used_no_defn.default.1()
288 // WINDOWS: declare dso_local i32 @foo_used_no_defn.sse4.2.0()
289 
290 
291 // CHECK: attributes #[[SSE42]] =
292 // CHECK-SAME: "target-features"="+crc32,+cx8,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87"
293 // CHECK: attributes #[[SB]] =
294 // CHECK-SAME: "target-features"="+avx,+cmov,+crc32,+cx16,+cx8,+fxsr,+mmx,+pclmul,+popcnt,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt"
295