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