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