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
5 #define ATTR(X) __declspec(X)
7 #define ATTR(X) __attribute__((X))
10 // Each version should have an IFunc and an alias.
11 // LINUX: @SingleVersion = weak_odr alias void (), ptr @SingleVersion.ifunc
12 // LINUX: @TwoVersions = weak_odr alias void (), ptr @TwoVersions.ifunc
13 // LINUX: @OrderDispatchUsageSpecific = weak_odr alias void (), ptr @OrderDispatchUsageSpecific.ifunc
14 // LINUX: @TwoVersionsSameAttr = weak_odr alias void (), ptr @TwoVersionsSameAttr.ifunc
15 // LINUX: @ThreeVersionsSameAttr = weak_odr alias void (), ptr @ThreeVersionsSameAttr.ifunc
16 // LINUX: @OrderSpecificUsageDispatch = weak_odr alias void (), ptr @OrderSpecificUsageDispatch.ifunc
17 // LINUX: @NoSpecifics = weak_odr alias void (), ptr @NoSpecifics.ifunc
18 // LINUX: @HasGeneric = weak_odr alias void (), ptr @HasGeneric.ifunc
19 // LINUX: @HasParams = weak_odr alias void (i32, double), ptr @HasParams.ifunc
20 // LINUX: @HasParamsAndReturn = weak_odr alias i32 (i32, double), ptr @HasParamsAndReturn.ifunc
21 // LINUX: @GenericAndPentium = weak_odr alias i32 (i32, double), ptr @GenericAndPentium.ifunc
22 // LINUX: @DispatchFirst = weak_odr alias i32 (), ptr @DispatchFirst.ifunc
24 // LINUX: @SingleVersion.ifunc = weak_odr ifunc void (), ptr @SingleVersion.resolver
25 // LINUX: @TwoVersions.ifunc = weak_odr ifunc void (), ptr @TwoVersions.resolver
26 // LINUX: @OrderDispatchUsageSpecific.ifunc = weak_odr ifunc void (), ptr @OrderDispatchUsageSpecific.resolver
27 // LINUX: @TwoVersionsSameAttr.ifunc = weak_odr ifunc void (), ptr @TwoVersionsSameAttr.resolver
28 // LINUX: @ThreeVersionsSameAttr.ifunc = weak_odr ifunc void (), ptr @ThreeVersionsSameAttr.resolver
29 // LINUX: @OrderSpecificUsageDispatch.ifunc = weak_odr ifunc void (), ptr @OrderSpecificUsageDispatch.resolver
30 // LINUX: @NoSpecifics.ifunc = weak_odr ifunc void (), ptr @NoSpecifics.resolver
31 // LINUX: @HasGeneric.ifunc = weak_odr ifunc void (), ptr @HasGeneric.resolver
32 // LINUX: @HasParams.ifunc = weak_odr ifunc void (i32, double), ptr @HasParams.resolver
33 // LINUX: @HasParamsAndReturn.ifunc = weak_odr ifunc i32 (i32, double), ptr @HasParamsAndReturn.resolver
34 // LINUX: @GenericAndPentium.ifunc = weak_odr ifunc i32 (i32, double), ptr @GenericAndPentium.resolver
35 // LINUX: @DispatchFirst.ifunc = weak_odr ifunc i32 (), ptr @DispatchFirst.resolver
37 ATTR(cpu_specific(ivybridge
))
38 void SingleVersion(void){}
39 // LINUX: define{{.*}} void @SingleVersion.S() #[[S:[0-9]+]]
40 // WINDOWS: define dso_local void @SingleVersion.S() #[[S:[0-9]+]]
42 ATTR(cpu_dispatch(ivybridge
))
43 void SingleVersion(void);
44 // LINUX: define weak_odr ptr @SingleVersion.resolver()
45 // LINUX: call void @__cpu_indicator_init
46 // LINUX: ret ptr @SingleVersion.S
47 // LINUX: call void @llvm.trap
50 // WINDOWS: define weak_odr dso_local void @SingleVersion() comdat
51 // WINDOWS: call void @__cpu_indicator_init()
52 // WINDOWS: call void @SingleVersion.S()
53 // WINDOWS-NEXT: ret void
54 // WINDOWS: call void @llvm.trap
55 // WINDOWS: unreachable
57 ATTR(cpu_specific(ivybridge
))
58 void NotCalled(void){}
59 // LINUX: define{{.*}} void @NotCalled.S() #[[S]]
60 // WINDOWS: define dso_local void @NotCalled.S() #[[S:[0-9]+]]
62 // Done before any of the implementations. Also has an undecorated forward
64 void TwoVersions(void);
66 ATTR(cpu_dispatch(ivybridge
, knl
))
67 void TwoVersions(void);
68 // LINUX: define weak_odr ptr @TwoVersions.resolver()
69 // LINUX: call void @__cpu_indicator_init
70 // LINUX: ret ptr @TwoVersions.Z
71 // LINUX: ret ptr @TwoVersions.S
72 // LINUX: call void @llvm.trap
75 // WINDOWS: define weak_odr dso_local void @TwoVersions() comdat
76 // WINDOWS: call void @__cpu_indicator_init()
77 // WINDOWS: call void @TwoVersions.Z()
78 // WINDOWS-NEXT: ret void
79 // WINDOWS: call void @TwoVersions.S()
80 // WINDOWS-NEXT: ret void
81 // WINDOWS: call void @llvm.trap
82 // WINDOWS: unreachable
84 ATTR(cpu_specific(ivybridge
))
85 void TwoVersions(void){}
86 // CHECK: define {{.*}}void @TwoVersions.S() #[[S]]
88 ATTR(cpu_specific(knl
))
89 void TwoVersions(void){}
90 // CHECK: define {{.*}}void @TwoVersions.Z() #[[K:[0-9]+]]
92 ATTR(cpu_specific(ivybridge
, knl
))
93 void TwoVersionsSameAttr(void){}
94 // CHECK: define {{.*}}void @TwoVersionsSameAttr.S() #[[S]]
95 // CHECK: define {{.*}}void @TwoVersionsSameAttr.Z() #[[K]]
97 ATTR(cpu_specific(atom
, ivybridge
, knl
))
98 void ThreeVersionsSameAttr(void){}
99 // CHECK: define {{.*}}void @ThreeVersionsSameAttr.O() #[[O:[0-9]+]]
100 // CHECK: define {{.*}}void @ThreeVersionsSameAttr.S() #[[S]]
101 // CHECK: define {{.*}}void @ThreeVersionsSameAttr.Z() #[[K]]
103 ATTR(cpu_specific(knl
))
104 void CpuSpecificNoDispatch(void) {}
105 // CHECK: define {{.*}}void @CpuSpecificNoDispatch.Z() #[[K:[0-9]+]]
107 ATTR(cpu_dispatch(knl
))
108 void OrderDispatchUsageSpecific(void);
109 // LINUX: define weak_odr ptr @OrderDispatchUsageSpecific.resolver()
110 // LINUX: call void @__cpu_indicator_init
111 // LINUX: ret ptr @OrderDispatchUsageSpecific.Z
112 // LINUX: call void @llvm.trap
113 // LINUX: unreachable
115 // WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() comdat
116 // WINDOWS: call void @__cpu_indicator_init()
117 // WINDOWS: call void @OrderDispatchUsageSpecific.Z()
118 // WINDOWS-NEXT: ret void
119 // WINDOWS: call void @llvm.trap
120 // WINDOWS: unreachable
122 // CHECK: define {{.*}}void @OrderDispatchUsageSpecific.Z()
124 ATTR(cpu_specific(knl
))
125 void OrderSpecificUsageDispatch(void) {}
126 // CHECK: define {{.*}}void @OrderSpecificUsageDispatch.Z() #[[K:[0-9]+]]
130 // LINUX: @SingleVersion.ifunc()
131 // WINDOWS: @SingleVersion()
133 // LINUX: @TwoVersions.ifunc()
134 // WINDOWS: @TwoVersions()
135 TwoVersionsSameAttr();
136 // LINUX: @TwoVersionsSameAttr.ifunc()
137 // WINDOWS: @TwoVersionsSameAttr()
138 ThreeVersionsSameAttr();
139 // LINUX: @ThreeVersionsSameAttr.ifunc()
140 // WINDOWS: @ThreeVersionsSameAttr()
141 CpuSpecificNoDispatch();
142 // LINUX: @CpuSpecificNoDispatch.ifunc()
143 // WINDOWS: @CpuSpecificNoDispatch()
144 OrderDispatchUsageSpecific();
145 // LINUX: @OrderDispatchUsageSpecific.ifunc()
146 // WINDOWS: @OrderDispatchUsageSpecific()
147 OrderSpecificUsageDispatch();
148 // LINUX: @OrderSpecificUsageDispatch.ifunc()
149 // WINDOWS: @OrderSpecificUsageDispatch()
152 // LINUX: declare void @CpuSpecificNoDispatch.ifunc()
154 // has an extra config to emit!
155 ATTR(cpu_dispatch(ivybridge
, knl
, atom
))
156 void TwoVersionsSameAttr(void);
157 // LINUX: define weak_odr ptr @TwoVersionsSameAttr.resolver()
158 // LINUX: ret ptr @TwoVersionsSameAttr.Z
159 // LINUX: ret ptr @TwoVersionsSameAttr.S
160 // LINUX: ret ptr @TwoVersionsSameAttr.O
161 // LINUX: call void @llvm.trap
162 // LINUX: unreachable
164 // WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() comdat
165 // WINDOWS: call void @TwoVersionsSameAttr.Z
166 // WINDOWS-NEXT: ret void
167 // WINDOWS: call void @TwoVersionsSameAttr.S
168 // WINDOWS-NEXT: ret void
169 // WINDOWS: call void @TwoVersionsSameAttr.O
170 // WINDOWS-NEXT: ret void
171 // WINDOWS: call void @llvm.trap
172 // WINDOWS: unreachable
174 ATTR(cpu_dispatch(atom
, ivybridge
, knl
))
175 void ThreeVersionsSameAttr(void){}
176 // LINUX: define weak_odr ptr @ThreeVersionsSameAttr.resolver()
177 // LINUX: call void @__cpu_indicator_init
178 // LINUX: ret ptr @ThreeVersionsSameAttr.Z
179 // LINUX: ret ptr @ThreeVersionsSameAttr.S
180 // LINUX: ret ptr @ThreeVersionsSameAttr.O
181 // LINUX: call void @llvm.trap
182 // LINUX: unreachable
184 // WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() comdat
185 // WINDOWS: call void @__cpu_indicator_init
186 // WINDOWS: call void @ThreeVersionsSameAttr.Z
187 // WINDOWS-NEXT: ret void
188 // WINDOWS: call void @ThreeVersionsSameAttr.S
189 // WINDOWS-NEXT: ret void
190 // WINDOWS: call void @ThreeVersionsSameAttr.O
191 // WINDOWS-NEXT: ret void
192 // WINDOWS: call void @llvm.trap
193 // WINDOWS: unreachable
195 ATTR(cpu_dispatch(knl
))
196 void OrderSpecificUsageDispatch(void);
197 // LINUX: define weak_odr ptr @OrderSpecificUsageDispatch.resolver()
198 // LINUX: ret ptr @OrderSpecificUsageDispatch.Z
200 // WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() comdat
201 // WINDOWS: call void @__cpu_indicator_init
202 // WINDOWS: call void @OrderSpecificUsageDispatch.Z
203 // WINDOWS-NEXT: ret void
205 // No Cpu Specific options.
206 ATTR(cpu_dispatch(atom
, ivybridge
, knl
))
207 void NoSpecifics(void);
208 // LINUX: define weak_odr ptr @NoSpecifics.resolver()
209 // LINUX: call void @__cpu_indicator_init
210 // LINUX: ret ptr @NoSpecifics.Z
211 // LINUX: ret ptr @NoSpecifics.S
212 // LINUX: ret ptr @NoSpecifics.O
213 // LINUX: call void @llvm.trap
214 // LINUX: unreachable
216 // WINDOWS: define weak_odr dso_local void @NoSpecifics() comdat
217 // WINDOWS: call void @__cpu_indicator_init
218 // WINDOWS: call void @NoSpecifics.Z
219 // WINDOWS-NEXT: ret void
220 // WINDOWS: call void @NoSpecifics.S
221 // WINDOWS-NEXT: ret void
222 // WINDOWS: call void @NoSpecifics.O
223 // WINDOWS-NEXT: ret void
224 // WINDOWS: call void @llvm.trap
225 // WINDOWS: unreachable
227 ATTR(cpu_dispatch(atom
, generic
, ivybridge
, knl
))
228 void HasGeneric(void);
229 // LINUX: define weak_odr ptr @HasGeneric.resolver()
230 // LINUX: call void @__cpu_indicator_init
231 // LINUX: ret ptr @HasGeneric.Z
232 // LINUX: ret ptr @HasGeneric.S
233 // LINUX: ret ptr @HasGeneric.O
234 // LINUX: ret ptr @HasGeneric.A
235 // LINUX-NOT: call void @llvm.trap
237 // WINDOWS: define weak_odr dso_local void @HasGeneric() comdat
238 // WINDOWS: call void @__cpu_indicator_init
239 // WINDOWS: call void @HasGeneric.Z
240 // WINDOWS-NEXT: ret void
241 // WINDOWS: call void @HasGeneric.S
242 // WINDOWS-NEXT: ret void
243 // WINDOWS: call void @HasGeneric.O
244 // WINDOWS-NEXT: ret void
245 // WINDOWS: call void @HasGeneric.A
246 // WINDOWS-NEXT: ret void
247 // WINDOWS-NOT: call void @llvm.trap
249 ATTR(cpu_dispatch(atom
, generic
, ivybridge
, knl
))
250 void HasParams(int i
, double d
);
251 // LINUX: define weak_odr ptr @HasParams.resolver()
252 // LINUX: call void @__cpu_indicator_init
253 // LINUX: ret ptr @HasParams.Z
254 // LINUX: ret ptr @HasParams.S
255 // LINUX: ret ptr @HasParams.O
256 // LINUX: ret ptr @HasParams.A
257 // LINUX-NOT: call void @llvm.trap
259 // WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) comdat
260 // WINDOWS: call void @__cpu_indicator_init
261 // WINDOWS: call void @HasParams.Z(i32 %0, double %1)
262 // WINDOWS-NEXT: ret void
263 // WINDOWS: call void @HasParams.S(i32 %0, double %1)
264 // WINDOWS-NEXT: ret void
265 // WINDOWS: call void @HasParams.O(i32 %0, double %1)
266 // WINDOWS-NEXT: ret void
267 // WINDOWS: call void @HasParams.A(i32 %0, double %1)
268 // WINDOWS-NEXT: ret void
269 // WINDOWS-NOT: call void @llvm.trap
271 ATTR(cpu_dispatch(atom
, generic
, ivybridge
, knl
))
272 int HasParamsAndReturn(int i
, double d
);
273 // LINUX: define weak_odr ptr @HasParamsAndReturn.resolver()
274 // LINUX: call void @__cpu_indicator_init
275 // LINUX: ret ptr @HasParamsAndReturn.Z
276 // LINUX: ret ptr @HasParamsAndReturn.S
277 // LINUX: ret ptr @HasParamsAndReturn.O
278 // LINUX: ret ptr @HasParamsAndReturn.A
279 // LINUX-NOT: call void @llvm.trap
281 // WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) comdat
282 // WINDOWS: call void @__cpu_indicator_init
283 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)
284 // WINDOWS-NEXT: ret i32 %[[RET]]
285 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.S(i32 %0, double %1)
286 // WINDOWS-NEXT: ret i32 %[[RET]]
287 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.O(i32 %0, double %1)
288 // WINDOWS-NEXT: ret i32 %[[RET]]
289 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.A(i32 %0, double %1)
290 // WINDOWS-NEXT: ret i32 %[[RET]]
291 // WINDOWS-NOT: call void @llvm.trap
293 ATTR(cpu_dispatch(atom
, generic
, pentium
))
294 int GenericAndPentium(int i
, double d
);
295 // LINUX: define weak_odr ptr @GenericAndPentium.resolver()
296 // LINUX: call void @__cpu_indicator_init
297 // LINUX: ret ptr @GenericAndPentium.O
298 // LINUX: ret ptr @GenericAndPentium.B
299 // LINUX-NOT: ret ptr @GenericAndPentium.A
300 // LINUX-NOT: call void @llvm.trap
302 // WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) comdat
303 // WINDOWS: call void @__cpu_indicator_init
304 // WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
305 // WINDOWS-NEXT: ret i32 %[[RET]]
306 // WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.B(i32 %0, double %1)
307 // WINDOWS-NEXT: ret i32 %[[RET]]
308 // WINDOWS-NOT: call i32 @GenericAndPentium.A
309 // WINDOWS-NOT: call void @llvm.trap
311 ATTR(cpu_dispatch(atom
, pentium
))
312 int DispatchFirst(void);
313 // LINUX: define weak_odr ptr @DispatchFirst.resolver
314 // LINUX: ret ptr @DispatchFirst.O
315 // LINUX: ret ptr @DispatchFirst.B
317 // WINDOWS: define weak_odr dso_local i32 @DispatchFirst() comdat
318 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()
319 // WINDOWS-NEXT: ret i32 %[[RET]]
320 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()
321 // WINDOWS-NEXT: ret i32 %[[RET]]
323 ATTR(cpu_specific(atom
))
324 int DispatchFirst(void) {return 0;}
325 // LINUX: define{{.*}} i32 @DispatchFirst.O
328 // WINDOWS: define dso_local i32 @DispatchFirst.O()
329 // WINDOWS: ret i32 0
331 ATTR(cpu_specific(pentium
))
332 int DispatchFirst(void) {return 1;}
333 // LINUX: define{{.*}} i32 @DispatchFirst.B
336 // WINDOWS: define dso_local i32 @DispatchFirst.B
337 // WINDOWS: ret i32 1
339 ATTR(cpu_specific(knl
))
340 void OrderDispatchUsageSpecific(void) {}
342 // CHECK: attributes #[[S]] = {{.*}}"target-features"="+avx,+cmov,+crc32,+cx8,+f16c,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
343 // CHECK-SAME: "tune-cpu"="ivybridge"
344 // CHECK: attributes #[[K]] = {{.*}}"target-features"="+adx,+avx,+avx2,+avx512cd,+avx512er,+avx512f,+avx512pf,+bmi,+cmov,+crc32,+cx8,+f16c,+fma,+lzcnt,+mmx,+movbe,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave"
345 // CHECK-SAME: "tune-cpu"="knl"
346 // CHECK: attributes #[[O]] = {{.*}}"target-features"="+cmov,+cx8,+mmx,+movbe,+sse,+sse2,+sse3,+ssse3,+x87"
347 // CHECK-SAME: "tune-cpu"="atom"