1 /* This test checks if the __builtin_cpu_is and __builtin_cpu_supports calls
2 are recognized. It also independently uses CPUID to get cpu type and
3 features supported and checks if the builtins correctly identify the
4 platform. The code to do the identification is adapted from
5 libgcc/config/i386/cpuinfo.c. */
6
7 /* { dg-do run } */
8
9 #include <assert.h>
10 #include "cpuid.h"
11
12 /* Check if the Intel CPU model and sub-model are identified. */
13 static void
check_intel_cpu_model(unsigned int family,unsigned int model,unsigned int brand_id)14 check_intel_cpu_model (unsigned int family, unsigned int model,
15 unsigned int brand_id)
16 {
17 /* Parse family and model only if brand ID is 0. */
18 if (brand_id == 0)
19 {
20 switch (family)
21 {
22 case 0x5:
23 /* Pentium. */
24 break;
25 case 0x6:
26 switch (model)
27 {
28 case 0x1c:
29 case 0x26:
30 /* Atom. */
31 assert (__builtin_cpu_is ("atom"));
32 break;
33 case 0x37:
34 case 0x4a:
35 case 0x4d:
36 case 0x5a:
37 case 0x5d:
38 /* Silvermont. */
39 assert (__builtin_cpu_is ("silvermont"));
40 break;
41 case 0x5c:
42 case 0x5f:
43 /* Goldmont. */
44 assert (__builtin_cpu_is ("goldmont"));
45 break;
46 case 0x7a:
47 /* Goldmont Plus. */
48 assert (__builtin_cpu_is ("goldmont-plus"));
49 break;
50 case 0x57:
51 /* Knights Landing. */
52 assert (__builtin_cpu_is ("knl"));
53 break;
54 case 0x85:
55 /* Knights Mill */
56 assert (__builtin_cpu_is ("knm"));
57 break;
58 case 0x1a:
59 case 0x1e:
60 case 0x1f:
61 case 0x2e:
62 /* Nehalem. */
63 assert (__builtin_cpu_is ("corei7"));
64 assert (__builtin_cpu_is ("nehalem"));
65 break;
66 case 0x25:
67 case 0x2c:
68 case 0x2f:
69 /* Westmere. */
70 assert (__builtin_cpu_is ("corei7"));
71 assert (__builtin_cpu_is ("westmere"));
72 break;
73 case 0x2a:
74 case 0x2d:
75 /* Sandy Bridge. */
76 assert (__builtin_cpu_is ("corei7"));
77 assert (__builtin_cpu_is ("sandybridge"));
78 break;
79 case 0x3a:
80 case 0x3e:
81 /* Ivy Bridge. */
82 assert (__builtin_cpu_is ("corei7"));
83 assert (__builtin_cpu_is ("ivybridge"));
84 break;
85 case 0x3c:
86 case 0x3f:
87 case 0x45:
88 case 0x46:
89 /* Haswell. */
90 assert (__builtin_cpu_is ("corei7"));
91 assert (__builtin_cpu_is ("haswell"));
92 break;
93 case 0x3d:
94 case 0x47:
95 case 0x4f:
96 case 0x56:
97 /* Broadwell. */
98 assert (__builtin_cpu_is ("corei7"));
99 assert (__builtin_cpu_is ("broadwell"));
100 break;
101 case 0x4e:
102 case 0x5e:
103 /* Skylake. */
104 case 0x8e:
105 case 0x9e:
106 /* Kaby Lake. */
107 assert (__builtin_cpu_is ("corei7"));
108 assert (__builtin_cpu_is ("skylake"));
109 break;
110 case 0x55:
111 {
112 unsigned int eax, ebx, ecx, edx;
113 __cpuid_count (7, 0, eax, ebx, ecx, edx);
114 assert (__builtin_cpu_is ("corei7"));
115 if (ecx & bit_AVX512VNNI)
116 /* Cascade Lake. */
117 assert (__builtin_cpu_is ("cascadelake"));
118 else
119 /* Skylake with AVX-512 support. */
120 assert (__builtin_cpu_is ("skylake-avx512"));
121 break;
122 }
123 case 0x66:
124 /* Cannon Lake. */
125 assert (__builtin_cpu_is ("cannonlake"));
126 break;
127 case 0x17:
128 case 0x1d:
129 /* Penryn. */
130 case 0x0f:
131 /* Merom. */
132 assert (__builtin_cpu_is ("core2"));
133 break;
134 default:
135 break;
136 }
137 break;
138 default:
139 /* We have no idea. */
140 break;
141 }
142 }
143 }
144
145 /* Check if the AMD CPU model and sub-model are identified. */
146 static void
check_amd_cpu_model(unsigned int family,unsigned int model)147 check_amd_cpu_model (unsigned int family, unsigned int model)
148 {
149 switch (family)
150 {
151 /* AMD Family 10h. */
152 case 0x10:
153 switch (model)
154 {
155 case 0x2:
156 /* Barcelona. */
157 assert (__builtin_cpu_is ("amdfam10h"));
158 assert (__builtin_cpu_is ("barcelona"));
159 break;
160 case 0x4:
161 /* Shanghai. */
162 assert (__builtin_cpu_is ("amdfam10h"));
163 assert (__builtin_cpu_is ("shanghai"));
164 break;
165 case 0x8:
166 /* Istanbul. */
167 assert (__builtin_cpu_is ("amdfam10h"));
168 assert (__builtin_cpu_is ("istanbul"));
169 break;
170 default:
171 break;
172 }
173 break;
174 /* AMD Family 15h. */
175 case 0x15:
176 assert (__builtin_cpu_is ("amdfam15h"));
177 /* Bulldozer version 1. */
178 if ( model <= 0xf)
179 assert (__builtin_cpu_is ("bdver1"));
180 /* Bulldozer version 2. */
181 if (model >= 0x10 && model <= 0x1f)
182 assert (__builtin_cpu_is ("bdver2"));
183 break;
184 default:
185 break;
186 }
187 }
188
189 /* Check if the ISA features are identified. */
190 static void
check_features(unsigned int ecx,unsigned int edx,int max_cpuid_level)191 check_features (unsigned int ecx, unsigned int edx,
192 int max_cpuid_level)
193 {
194 unsigned int eax, ebx;
195 unsigned int ext_level;
196
197 if (edx & bit_CMOV)
198 assert (__builtin_cpu_supports ("cmov"));
199 if (edx & bit_MMX)
200 assert (__builtin_cpu_supports ("mmx"));
201 if (edx & bit_SSE)
202 assert (__builtin_cpu_supports ("sse"));
203 if (edx & bit_SSE2)
204 assert (__builtin_cpu_supports ("sse2"));
205 if (ecx & bit_POPCNT)
206 assert (__builtin_cpu_supports ("popcnt"));
207 if (ecx & bit_AES)
208 assert (__builtin_cpu_supports ("aes"));
209 if (ecx & bit_PCLMUL)
210 assert (__builtin_cpu_supports ("pclmul"));
211 if (ecx & bit_SSE3)
212 assert (__builtin_cpu_supports ("sse3"));
213 if (ecx & bit_SSSE3)
214 assert (__builtin_cpu_supports ("ssse3"));
215 if (ecx & bit_SSE4_1)
216 assert (__builtin_cpu_supports ("sse4.1"));
217 if (ecx & bit_SSE4_2)
218 assert (__builtin_cpu_supports ("sse4.2"));
219 if (ecx & bit_AVX)
220 assert (__builtin_cpu_supports ("avx"));
221 if (ecx & bit_FMA)
222 assert (__builtin_cpu_supports ("fma"));
223
224 /* Get advanced features at level 7 (eax = 7, ecx = 0). */
225 if (max_cpuid_level >= 7)
226 {
227 __cpuid_count (7, 0, eax, ebx, ecx, edx);
228 if (ebx & bit_BMI)
229 assert (__builtin_cpu_supports ("bmi"));
230 if (ebx & bit_AVX2)
231 assert (__builtin_cpu_supports ("avx2"));
232 if (ebx & bit_BMI2)
233 assert (__builtin_cpu_supports ("bmi2"));
234 if (ebx & bit_AVX512F)
235 assert (__builtin_cpu_supports ("avx512f"));
236 if (ebx & bit_AVX512VL)
237 assert (__builtin_cpu_supports ("avx512vl"));
238 if (ebx & bit_AVX512BW)
239 assert (__builtin_cpu_supports ("avx512bw"));
240 if (ebx & bit_AVX512DQ)
241 assert (__builtin_cpu_supports ("avx512dq"));
242 if (ebx & bit_AVX512CD)
243 assert (__builtin_cpu_supports ("avx512cd"));
244 if (ebx & bit_AVX512PF)
245 assert (__builtin_cpu_supports ("avx512pf"));
246 if (ebx & bit_AVX512ER)
247 assert (__builtin_cpu_supports ("avx512er"));
248 if (ebx & bit_AVX512IFMA)
249 assert (__builtin_cpu_supports ("avx512ifma"));
250 if (ecx & bit_AVX512VBMI)
251 assert (__builtin_cpu_supports ("avx512vbmi"));
252 if (ecx & bit_AVX512VBMI2)
253 assert (__builtin_cpu_supports ("avx512vbmi2"));
254 if (ecx & bit_GFNI)
255 assert (__builtin_cpu_supports ("gfni"));
256 if (ecx & bit_VPCLMULQDQ)
257 assert (__builtin_cpu_supports ("vpclmulqdq"));
258 if (ecx & bit_AVX512VNNI)
259 assert (__builtin_cpu_supports ("avx512vnni"));
260 if (ecx & bit_AVX512BITALG)
261 assert (__builtin_cpu_supports ("avx512bitalg"));
262 if (ecx & bit_AVX512VPOPCNTDQ)
263 assert (__builtin_cpu_supports ("avx512vpopcntdq"));
264 if (edx & bit_AVX5124VNNIW)
265 assert (__builtin_cpu_supports ("avx5124vnniw"));
266 if (edx & bit_AVX5124FMAPS)
267 assert (__builtin_cpu_supports ("avx5124fmaps"));
268 }
269
270 /* Check cpuid level of extended features. */
271 __cpuid (0x80000000, ext_level, ebx, ecx, edx);
272
273 if (ext_level >= 0x80000001)
274 {
275 __cpuid (0x80000001, eax, ebx, ecx, edx);
276
277 if (ecx & bit_SSE4a)
278 assert (__builtin_cpu_supports ("sse4a"));
279 if (ecx & bit_FMA4)
280 assert (__builtin_cpu_supports ("fma4"));
281 if (ecx & bit_XOP)
282 assert (__builtin_cpu_supports ("xop"));
283 }
284 }
285
286 static int __attribute__ ((noinline))
__get_cpuid_output(unsigned int __level,unsigned int * __eax,unsigned int * __ebx,unsigned int * __ecx,unsigned int * __edx)287 __get_cpuid_output (unsigned int __level,
288 unsigned int *__eax, unsigned int *__ebx,
289 unsigned int *__ecx, unsigned int *__edx)
290 {
291 return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
292 }
293
294 static int
check_detailed()295 check_detailed ()
296 {
297 unsigned int eax, ebx, ecx, edx;
298
299 int max_level;
300 unsigned int vendor;
301 unsigned int model, family, brand_id;
302 unsigned int extended_model, extended_family;
303
304 /* Assume cpuid insn present. Run in level 0 to get vendor id. */
305 if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
306 return 0;
307
308 vendor = ebx;
309 max_level = eax;
310
311 if (max_level < 1)
312 return 0;
313
314 if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
315 return 0;
316
317 model = (eax >> 4) & 0x0f;
318 family = (eax >> 8) & 0x0f;
319 brand_id = ebx & 0xff;
320 extended_model = (eax >> 12) & 0xf0;
321 extended_family = (eax >> 20) & 0xff;
322
323 if (vendor == signature_INTEL_ebx)
324 {
325 assert (__builtin_cpu_is ("intel"));
326 /* Adjust family and model for Intel CPUs. */
327 if (family == 0x0f)
328 {
329 family += extended_family;
330 model += extended_model;
331 }
332 else if (family == 0x06)
333 model += extended_model;
334 check_intel_cpu_model (family, model, brand_id);
335 check_features (ecx, edx, max_level);
336 }
337 else if (vendor == signature_AMD_ebx)
338 {
339 assert (__builtin_cpu_is ("amd"));
340 /* Adjust model and family for AMD CPUS. */
341 if (family == 0x0f)
342 {
343 family += extended_family;
344 model += (extended_model << 4);
345 }
346 check_amd_cpu_model (family, model);
347 check_features (ecx, edx, max_level);
348 }
349
350 return 0;
351 }
352
353 static int
quick_check()354 quick_check ()
355 {
356 /* Check CPU Features. */
357 assert (__builtin_cpu_supports ("cmov") >= 0);
358
359 assert (__builtin_cpu_supports ("mmx") >= 0);
360
361 assert (__builtin_cpu_supports ("popcnt") >= 0);
362
363 assert (__builtin_cpu_supports ("sse") >= 0);
364
365 assert (__builtin_cpu_supports ("sse2") >= 0);
366
367 assert (__builtin_cpu_supports ("sse3") >= 0);
368
369 assert (__builtin_cpu_supports ("ssse3") >= 0);
370
371 assert (__builtin_cpu_supports ("sse4.1") >= 0);
372
373 assert (__builtin_cpu_supports ("sse4.2") >= 0);
374
375 assert (__builtin_cpu_supports ("avx") >= 0);
376
377 assert (__builtin_cpu_supports ("avx2") >= 0);
378
379 assert (__builtin_cpu_supports ("avx512f") >= 0);
380
381 assert (__builtin_cpu_supports ("avx5124vnniw") >= 0);
382
383 assert (__builtin_cpu_supports ("avx5124fmaps") >= 0);
384
385 assert (__builtin_cpu_supports ("avx512vpopcntdq") >= 0);
386
387 /* Check CPU type. */
388 assert (__builtin_cpu_is ("amd") >= 0);
389
390 assert (__builtin_cpu_is ("intel") >= 0);
391
392 assert (__builtin_cpu_is ("atom") >= 0);
393
394 assert (__builtin_cpu_is ("core2") >= 0);
395
396 assert (__builtin_cpu_is ("corei7") >= 0);
397
398 assert (__builtin_cpu_is ("nehalem") >= 0);
399
400 assert (__builtin_cpu_is ("westmere") >= 0);
401
402 assert (__builtin_cpu_is ("sandybridge") >= 0);
403
404 assert (__builtin_cpu_is ("amdfam10h") >= 0);
405
406 assert (__builtin_cpu_is ("barcelona") >= 0);
407
408 assert (__builtin_cpu_is ("shanghai") >= 0);
409
410 assert (__builtin_cpu_is ("istanbul") >= 0);
411
412 assert (__builtin_cpu_is ("amdfam15h") >= 0);
413
414 assert (__builtin_cpu_is ("bdver1") >= 0);
415
416 assert (__builtin_cpu_is ("bdver2") >= 0);
417
418 return 0;
419 }
420
main()421 int main ()
422 {
423 __builtin_cpu_init ();
424 quick_check ();
425 check_detailed ();
426 return 0;
427 }
428