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