Clang Project

clang_source_code/test/CodeGen/attr-cpuspecific.c
1// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LINUX
2// RUN: %clang_cc1 -triple x86_64-windows-pc -fms-compatibility -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WINDOWS
3
4#ifdef _WIN64
5#define ATTR(X) __declspec(X)
6#else
7#define ATTR(X) __attribute__((X))
8#endif // _MSC_VER
9
10// Each called version should have an IFunc.
11// LINUX: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver
12// LINUX: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver
13// LINUX: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
14// LINUX: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
15
16ATTR(cpu_specific(ivybridge))
17void SingleVersion(void){}
18// LINUX: define void @SingleVersion.S() #[[S:[0-9]+]]
19// WINDOWS: define dso_local void @SingleVersion.S() #[[S:[0-9]+]]
20
21ATTR(cpu_specific(ivybridge))
22void NotCalled(void){}
23// LINUX: define void @NotCalled.S() #[[S]]
24// WINDOWS: define dso_local void @NotCalled.S() #[[S:[0-9]+]]
25
26// Done before any of the implementations.  Also has an undecorated forward
27// declaration.
28void TwoVersions(void);
29
30ATTR(cpu_dispatch(ivybridge, knl))
31void TwoVersions(void);
32// LINUX: define void ()* @TwoVersions.resolver()
33// LINUX: call void @__cpu_indicator_init
34// LINUX: ret void ()* @TwoVersions.Z
35// LINUX: ret void ()* @TwoVersions.S
36// LINUX: call void @llvm.trap
37// LINUX: unreachable
38
39// WINDOWS: define dso_local void @TwoVersions()
40// WINDOWS: call void @__cpu_indicator_init()
41// WINDOWS: call void @TwoVersions.Z()
42// WINDOWS-NEXT: ret void
43// WINDOWS: call void @TwoVersions.S()
44// WINDOWS-NEXT: ret void
45// WINDOWS: call void @llvm.trap
46// WINDOWS: unreachable
47
48ATTR(cpu_specific(ivybridge))
49void TwoVersions(void){}
50// CHECK: define {{.*}}void @TwoVersions.S() #[[S]]
51
52ATTR(cpu_specific(knl))
53void TwoVersions(void){}
54// CHECK: define {{.*}}void @TwoVersions.Z() #[[K:[0-9]+]]
55
56ATTR(cpu_specific(ivybridge, knl))
57void TwoVersionsSameAttr(void){}
58// CHECK: define {{.*}}void @TwoVersionsSameAttr.S() #[[S]]
59// CHECK: define {{.*}}void @TwoVersionsSameAttr.Z() #[[K]]
60
61ATTR(cpu_specific(atom, ivybridge, knl))
62void ThreeVersionsSameAttr(void){}
63// CHECK: define {{.*}}void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]
64// CHECK: define {{.*}}void @ThreeVersionsSameAttr.S() #[[S]]
65// CHECK: define {{.*}}void @ThreeVersionsSameAttr.Z() #[[K]]
66
67void usages() {
68  SingleVersion();
69  // LINUX: @SingleVersion.ifunc()
70  // WINDOWS: @SingleVersion()
71  TwoVersions();
72  // LINUX: @TwoVersions.ifunc()
73  // WINDOWS: @TwoVersions()
74  TwoVersionsSameAttr();
75  // LINUX: @TwoVersionsSameAttr.ifunc()
76  // WINDOWS: @TwoVersionsSameAttr()
77  ThreeVersionsSameAttr();
78  // LINUX: @ThreeVersionsSameAttr.ifunc()
79  // WINDOWS: @ThreeVersionsSameAttr()
80}
81
82// has an extra config to emit!
83ATTR(cpu_dispatch(ivybridge, knl, atom))
84void TwoVersionsSameAttr(void);
85// LINUX: define void ()* @TwoVersionsSameAttr.resolver()
86// LINUX: ret void ()* @TwoVersionsSameAttr.Z
87// LINUX: ret void ()* @TwoVersionsSameAttr.S
88// LINUX: ret void ()* @TwoVersionsSameAttr.O
89// LINUX: call void @llvm.trap
90// LINUX: unreachable
91
92// WINDOWS: define dso_local void @TwoVersionsSameAttr()
93// WINDOWS: call void @TwoVersionsSameAttr.Z
94// WINDOWS-NEXT: ret void
95// WINDOWS: call void @TwoVersionsSameAttr.S
96// WINDOWS-NEXT: ret void
97// WINDOWS: call void @TwoVersionsSameAttr.O
98// WINDOWS-NEXT: ret void
99// WINDOWS: call void @llvm.trap
100// WINDOWS: unreachable
101
102ATTR(cpu_dispatch(atom, ivybridge, knl))
103void ThreeVersionsSameAttr(void){}
104// LINUX: define void ()* @ThreeVersionsSameAttr.resolver()
105// LINUX: call void @__cpu_indicator_init
106// LINUX: ret void ()* @ThreeVersionsSameAttr.Z
107// LINUX: ret void ()* @ThreeVersionsSameAttr.S
108// LINUX: ret void ()* @ThreeVersionsSameAttr.O
109// LINUX: call void @llvm.trap
110// LINUX: unreachable
111
112// WINDOWS: define dso_local void @ThreeVersionsSameAttr()
113// WINDOWS: call void @__cpu_indicator_init
114// WINDOWS: call void @ThreeVersionsSameAttr.Z
115// WINDOWS-NEXT: ret void
116// WINDOWS: call void @ThreeVersionsSameAttr.S
117// WINDOWS-NEXT: ret void
118// WINDOWS: call void @ThreeVersionsSameAttr.O
119// WINDOWS-NEXT: ret void
120// WINDOWS: call void @llvm.trap
121// WINDOWS: unreachable
122
123// No Cpu Specific options.
124ATTR(cpu_dispatch(atom, ivybridge, knl))
125void NoSpecifics(void);
126// LINUX: define void ()* @NoSpecifics.resolver()
127// LINUX: call void @__cpu_indicator_init
128// LINUX: ret void ()* @NoSpecifics.Z
129// LINUX: ret void ()* @NoSpecifics.S
130// LINUX: ret void ()* @NoSpecifics.O
131// LINUX: call void @llvm.trap
132// LINUX: unreachable
133
134// WINDOWS: define dso_local void @NoSpecifics()
135// WINDOWS: call void @__cpu_indicator_init
136// WINDOWS: call void @NoSpecifics.Z
137// WINDOWS-NEXT: ret void
138// WINDOWS: call void @NoSpecifics.S
139// WINDOWS-NEXT: ret void
140// WINDOWS: call void @NoSpecifics.O
141// WINDOWS-NEXT: ret void
142// WINDOWS: call void @llvm.trap
143// WINDOWS: unreachable
144
145ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
146void HasGeneric(void);
147// LINUX: define void ()* @HasGeneric.resolver()
148// LINUX: call void @__cpu_indicator_init
149// LINUX: ret void ()* @HasGeneric.Z
150// LINUX: ret void ()* @HasGeneric.S
151// LINUX: ret void ()* @HasGeneric.O
152// LINUX: ret void ()* @HasGeneric.A
153// LINUX-NOT: call void @llvm.trap
154
155// WINDOWS: define dso_local void @HasGeneric()
156// WINDOWS: call void @__cpu_indicator_init
157// WINDOWS: call void @HasGeneric.Z
158// WINDOWS-NEXT: ret void
159// WINDOWS: call void @HasGeneric.S
160// WINDOWS-NEXT: ret void
161// WINDOWS: call void @HasGeneric.O
162// WINDOWS-NEXT: ret void
163// WINDOWS: call void @HasGeneric.A
164// WINDOWS-NEXT: ret void
165// WINDOWS-NOT: call void @llvm.trap
166
167ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
168void HasParams(int i, double d);
169// LINUX: define void (i32, double)* @HasParams.resolver()
170// LINUX: call void @__cpu_indicator_init
171// LINUX: ret void (i32, double)* @HasParams.Z
172// LINUX: ret void (i32, double)* @HasParams.S
173// LINUX: ret void (i32, double)* @HasParams.O
174// LINUX: ret void (i32, double)* @HasParams.A
175// LINUX-NOT: call void @llvm.trap
176
177// WINDOWS: define dso_local void @HasParams(i32, double)
178// WINDOWS: call void @__cpu_indicator_init
179// WINDOWS: call void @HasParams.Z(i32 %0, double %1)
180// WINDOWS-NEXT: ret void
181// WINDOWS: call void @HasParams.S(i32 %0, double %1)
182// WINDOWS-NEXT: ret void
183// WINDOWS: call void @HasParams.O(i32 %0, double %1)
184// WINDOWS-NEXT: ret void
185// WINDOWS: call void @HasParams.A(i32 %0, double %1)
186// WINDOWS-NEXT: ret void
187// WINDOWS-NOT: call void @llvm.trap
188
189ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
190int HasParamsAndReturn(int i, double d);
191// LINUX: define i32 (i32, double)* @HasParamsAndReturn.resolver()
192// LINUX: call void @__cpu_indicator_init
193// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.Z
194// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.S
195// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.O
196// LINUX: ret i32 (i32, double)* @HasParamsAndReturn.A
197// LINUX-NOT: call void @llvm.trap
198
199// WINDOWS: define dso_local i32 @HasParamsAndReturn(i32, double)
200// WINDOWS: call void @__cpu_indicator_init
201// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)
202// WINDOWS-NEXT: ret i32 %[[RET]]
203// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.S(i32 %0, double %1)
204// WINDOWS-NEXT: ret i32 %[[RET]]
205// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.O(i32 %0, double %1)
206// WINDOWS-NEXT: ret i32 %[[RET]]
207// WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.A(i32 %0, double %1)
208// WINDOWS-NEXT: ret i32 %[[RET]]
209// WINDOWS-NOT: call void @llvm.trap
210
211ATTR(cpu_dispatch(atom, generic, pentium))
212int GenericAndPentium(int i, double d);
213// LINUX: define i32 (i32, double)* @GenericAndPentium.resolver()
214// LINUX: call void @__cpu_indicator_init
215// LINUX: ret i32 (i32, double)* @GenericAndPentium.O
216// LINUX: ret i32 (i32, double)* @GenericAndPentium.B
217// LINUX-NOT: ret i32 (i32, double)* @GenericAndPentium.A
218// LINUX-NOT: call void @llvm.trap
219
220// WINDOWS: define dso_local i32 @GenericAndPentium(i32, double)
221// WINDOWS: call void @__cpu_indicator_init
222// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
223// WINDOWS-NEXT: ret i32 %[[RET]]
224// WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.B(i32 %0, double %1)
225// WINDOWS-NEXT: ret i32 %[[RET]]
226// WINDOWS-NOT: call i32 @GenericAndPentium.A
227// WINDOWS-NOT: call void @llvm.trap
228
229ATTR(cpu_dispatch(atom, pentium))
230int DispatchFirst(void);
231// LINUX: define i32 ()* @DispatchFirst.resolver
232// LINUX: ret i32 ()* @DispatchFirst.O
233// LINUX: ret i32 ()* @DispatchFirst.B
234
235// WINDOWS: define dso_local i32 @DispatchFirst()
236// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()
237// WINDOWS-NEXT: ret i32 %[[RET]]
238// WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()
239// WINDOWS-NEXT: ret i32 %[[RET]]
240
241ATTR(cpu_specific(atom))
242int DispatchFirst(void) {return 0;}
243// LINUX: define i32 @DispatchFirst.O
244// LINUX: ret i32 0
245
246// WINDOWS: define dso_local i32 @DispatchFirst.O()
247// WINDOWS: ret i32 0
248
249ATTR(cpu_specific(pentium))
250int DispatchFirst(void) {return 1;}
251// LINUX: define i32 @DispatchFirst.B
252// LINUX: ret i32 1
253
254// WINDOWS: define dso_local i32 @DispatchFirst.B
255// WINDOWS: ret i32 1
256
257// CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+cx8,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
258// CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+cx8,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
259// CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+cx8,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"
260