]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/builtins/cpu_model.c
Initial import from vendor-sys branch of openzfs
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / builtins / cpu_model.c
1 //===-- cpu_model.c - Support for __cpu_model builtin  ------------*- C -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file is based on LLVM's lib/Support/Host.cpp.
10 //  It implements the operating system Host concept and builtin
11 //  __cpu_model for the compiler_rt library, for x86 only.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) ||           \
16      defined(_M_X64)) &&                                                       \
17     (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER))
18
19 #include <assert.h>
20
21 #define bool int
22 #define true 1
23 #define false 0
24
25 #ifdef _MSC_VER
26 #include <intrin.h>
27 #endif
28
29 #ifndef __has_attribute
30 #define __has_attribute(attr) 0
31 #endif
32
33 enum VendorSignatures {
34   SIG_INTEL = 0x756e6547, // Genu
35   SIG_AMD = 0x68747541,   // Auth
36 };
37
38 enum ProcessorVendors {
39   VENDOR_INTEL = 1,
40   VENDOR_AMD,
41   VENDOR_OTHER,
42   VENDOR_MAX
43 };
44
45 enum ProcessorTypes {
46   INTEL_BONNELL = 1,
47   INTEL_CORE2,
48   INTEL_COREI7,
49   AMDFAM10H,
50   AMDFAM15H,
51   INTEL_SILVERMONT,
52   INTEL_KNL,
53   AMD_BTVER1,
54   AMD_BTVER2,
55   AMDFAM17H,
56   INTEL_KNM,
57   INTEL_GOLDMONT,
58   INTEL_GOLDMONT_PLUS,
59   INTEL_TREMONT,
60   CPU_TYPE_MAX
61 };
62
63 enum ProcessorSubtypes {
64   INTEL_COREI7_NEHALEM = 1,
65   INTEL_COREI7_WESTMERE,
66   INTEL_COREI7_SANDYBRIDGE,
67   AMDFAM10H_BARCELONA,
68   AMDFAM10H_SHANGHAI,
69   AMDFAM10H_ISTANBUL,
70   AMDFAM15H_BDVER1,
71   AMDFAM15H_BDVER2,
72   AMDFAM15H_BDVER3,
73   AMDFAM15H_BDVER4,
74   AMDFAM17H_ZNVER1,
75   INTEL_COREI7_IVYBRIDGE,
76   INTEL_COREI7_HASWELL,
77   INTEL_COREI7_BROADWELL,
78   INTEL_COREI7_SKYLAKE,
79   INTEL_COREI7_SKYLAKE_AVX512,
80   INTEL_COREI7_CANNONLAKE,
81   INTEL_COREI7_ICELAKE_CLIENT,
82   INTEL_COREI7_ICELAKE_SERVER,
83   AMDFAM17H_ZNVER2,
84   INTEL_COREI7_CASCADELAKE,
85   INTEL_COREI7_TIGERLAKE,
86   INTEL_COREI7_COOPERLAKE,
87   CPU_SUBTYPE_MAX
88 };
89
90 enum ProcessorFeatures {
91   FEATURE_CMOV = 0,
92   FEATURE_MMX,
93   FEATURE_POPCNT,
94   FEATURE_SSE,
95   FEATURE_SSE2,
96   FEATURE_SSE3,
97   FEATURE_SSSE3,
98   FEATURE_SSE4_1,
99   FEATURE_SSE4_2,
100   FEATURE_AVX,
101   FEATURE_AVX2,
102   FEATURE_SSE4_A,
103   FEATURE_FMA4,
104   FEATURE_XOP,
105   FEATURE_FMA,
106   FEATURE_AVX512F,
107   FEATURE_BMI,
108   FEATURE_BMI2,
109   FEATURE_AES,
110   FEATURE_PCLMUL,
111   FEATURE_AVX512VL,
112   FEATURE_AVX512BW,
113   FEATURE_AVX512DQ,
114   FEATURE_AVX512CD,
115   FEATURE_AVX512ER,
116   FEATURE_AVX512PF,
117   FEATURE_AVX512VBMI,
118   FEATURE_AVX512IFMA,
119   FEATURE_AVX5124VNNIW,
120   FEATURE_AVX5124FMAPS,
121   FEATURE_AVX512VPOPCNTDQ,
122   FEATURE_AVX512VBMI2,
123   FEATURE_GFNI,
124   FEATURE_VPCLMULQDQ,
125   FEATURE_AVX512VNNI,
126   FEATURE_AVX512BITALG,
127   FEATURE_AVX512BF16,
128   FEATURE_AVX512VP2INTERSECT,
129   CPU_FEATURE_MAX
130 };
131
132 // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
133 // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
134 // support. Consequently, for i386, the presence of CPUID is checked first
135 // via the corresponding eflags bit.
136 static bool isCpuIdSupported() {
137 #if defined(__GNUC__) || defined(__clang__)
138 #if defined(__i386__)
139   int __cpuid_supported;
140   __asm__("  pushfl\n"
141           "  popl   %%eax\n"
142           "  movl   %%eax,%%ecx\n"
143           "  xorl   $0x00200000,%%eax\n"
144           "  pushl  %%eax\n"
145           "  popfl\n"
146           "  pushfl\n"
147           "  popl   %%eax\n"
148           "  movl   $0,%0\n"
149           "  cmpl   %%eax,%%ecx\n"
150           "  je     1f\n"
151           "  movl   $1,%0\n"
152           "1:"
153           : "=r"(__cpuid_supported)
154           :
155           : "eax", "ecx");
156   if (!__cpuid_supported)
157     return false;
158 #endif
159   return true;
160 #endif
161   return true;
162 }
163
164 // This code is copied from lib/Support/Host.cpp.
165 // Changes to either file should be mirrored in the other.
166
167 /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
168 /// the specified arguments.  If we can't run cpuid on the host, return true.
169 static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
170                                unsigned *rECX, unsigned *rEDX) {
171 #if defined(__GNUC__) || defined(__clang__)
172 #if defined(__x86_64__)
173   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
174   // FIXME: should we save this for Clang?
175   __asm__("movq\t%%rbx, %%rsi\n\t"
176           "cpuid\n\t"
177           "xchgq\t%%rbx, %%rsi\n\t"
178           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
179           : "a"(value));
180   return false;
181 #elif defined(__i386__)
182   __asm__("movl\t%%ebx, %%esi\n\t"
183           "cpuid\n\t"
184           "xchgl\t%%ebx, %%esi\n\t"
185           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
186           : "a"(value));
187   return false;
188 #else
189   return true;
190 #endif
191 #elif defined(_MSC_VER)
192   // The MSVC intrinsic is portable across x86 and x64.
193   int registers[4];
194   __cpuid(registers, value);
195   *rEAX = registers[0];
196   *rEBX = registers[1];
197   *rECX = registers[2];
198   *rEDX = registers[3];
199   return false;
200 #else
201   return true;
202 #endif
203 }
204
205 /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return
206 /// the 4 values in the specified arguments.  If we can't run cpuid on the host,
207 /// return true.
208 static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
209                                  unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
210                                  unsigned *rEDX) {
211 #if defined(__GNUC__) || defined(__clang__)
212 #if defined(__x86_64__)
213   // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
214   // FIXME: should we save this for Clang?
215   __asm__("movq\t%%rbx, %%rsi\n\t"
216           "cpuid\n\t"
217           "xchgq\t%%rbx, %%rsi\n\t"
218           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
219           : "a"(value), "c"(subleaf));
220   return false;
221 #elif defined(__i386__)
222   __asm__("movl\t%%ebx, %%esi\n\t"
223           "cpuid\n\t"
224           "xchgl\t%%ebx, %%esi\n\t"
225           : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX)
226           : "a"(value), "c"(subleaf));
227   return false;
228 #else
229   return true;
230 #endif
231 #elif defined(_MSC_VER)
232   int registers[4];
233   __cpuidex(registers, value, subleaf);
234   *rEAX = registers[0];
235   *rEBX = registers[1];
236   *rECX = registers[2];
237   *rEDX = registers[3];
238   return false;
239 #else
240   return true;
241 #endif
242 }
243
244 // Read control register 0 (XCR0). Used to detect features such as AVX.
245 static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) {
246 #if defined(__GNUC__) || defined(__clang__)
247   // Check xgetbv; this uses a .byte sequence instead of the instruction
248   // directly because older assemblers do not include support for xgetbv and
249   // there is no easy way to conditionally compile based on the assembler used.
250   __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0));
251   return false;
252 #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
253   unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
254   *rEAX = Result;
255   *rEDX = Result >> 32;
256   return false;
257 #else
258   return true;
259 #endif
260 }
261
262 static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
263                                  unsigned *Model) {
264   *Family = (EAX >> 8) & 0xf; // Bits 8 - 11
265   *Model = (EAX >> 4) & 0xf;  // Bits 4 - 7
266   if (*Family == 6 || *Family == 0xf) {
267     if (*Family == 0xf)
268       // Examine extended family ID if family ID is F.
269       *Family += (EAX >> 20) & 0xff; // Bits 20 - 27
270     // Examine extended model ID if family ID is 6 or F.
271     *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
272   }
273 }
274
275 static const char *
276 getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model,
277                                 const unsigned *Features,
278                                 unsigned *Type, unsigned *Subtype) {
279 #define testFeature(F)                                                         \
280   (Features[F / 32] & (F % 32)) != 0
281
282   // We select CPU strings to match the code in Host.cpp, but we don't use them
283   // in compiler-rt.
284   const char *CPU = 0;
285
286   switch (Family) {
287   case 6:
288     switch (Model) {
289     case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
290                // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
291                // mobile processor, Intel Core 2 Extreme processor, Intel
292                // Pentium Dual-Core processor, Intel Xeon processor, model
293                // 0Fh. All processors are manufactured using the 65 nm process.
294     case 0x16: // Intel Celeron processor model 16h. All processors are
295                // manufactured using the 65 nm process
296       CPU = "core2";
297       *Type = INTEL_CORE2;
298       break;
299     case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model
300                // 17h. All processors are manufactured using the 45 nm process.
301                //
302                // 45nm: Penryn , Wolfdale, Yorkfield (XE)
303     case 0x1d: // Intel Xeon processor MP. All processors are manufactured using
304                // the 45 nm process.
305       CPU = "penryn";
306       *Type = INTEL_CORE2;
307       break;
308     case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All
309                // processors are manufactured using the 45 nm process.
310     case 0x1e: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
311                // As found in a Summer 2010 model iMac.
312     case 0x1f:
313     case 0x2e:              // Nehalem EX
314       CPU = "nehalem";
315       *Type = INTEL_COREI7;
316       *Subtype = INTEL_COREI7_NEHALEM;
317       break;
318     case 0x25: // Intel Core i7, laptop version.
319     case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All
320                // processors are manufactured using the 32 nm process.
321     case 0x2f: // Westmere EX
322       CPU = "westmere";
323       *Type = INTEL_COREI7;
324       *Subtype = INTEL_COREI7_WESTMERE;
325       break;
326     case 0x2a: // Intel Core i7 processor. All processors are manufactured
327                // using the 32 nm process.
328     case 0x2d:
329       CPU = "sandybridge";
330       *Type = INTEL_COREI7;
331       *Subtype = INTEL_COREI7_SANDYBRIDGE;
332       break;
333     case 0x3a:
334     case 0x3e:              // Ivy Bridge EP
335       CPU = "ivybridge";
336       *Type = INTEL_COREI7;
337       *Subtype = INTEL_COREI7_IVYBRIDGE;
338       break;
339
340     // Haswell:
341     case 0x3c:
342     case 0x3f:
343     case 0x45:
344     case 0x46:
345       CPU = "haswell";
346       *Type = INTEL_COREI7;
347       *Subtype = INTEL_COREI7_HASWELL;
348       break;
349
350     // Broadwell:
351     case 0x3d:
352     case 0x47:
353     case 0x4f:
354     case 0x56:
355       CPU = "broadwell";
356       *Type = INTEL_COREI7;
357       *Subtype = INTEL_COREI7_BROADWELL;
358       break;
359
360     // Skylake:
361     case 0x4e:              // Skylake mobile
362     case 0x5e:              // Skylake desktop
363     case 0x8e:              // Kaby Lake mobile
364     case 0x9e:              // Kaby Lake desktop
365     case 0xa5:              // Comet Lake-H/S
366     case 0xa6:              // Comet Lake-U
367       CPU = "skylake";
368       *Type = INTEL_COREI7;
369       *Subtype = INTEL_COREI7_SKYLAKE;
370       break;
371
372     // Skylake Xeon:
373     case 0x55:
374       *Type = INTEL_COREI7;
375       if (testFeature(FEATURE_AVX512BF16)) {
376         CPU = "cooperlake";
377         *Subtype = INTEL_COREI7_COOPERLAKE;
378       } else if (testFeature(FEATURE_AVX512VNNI)) {
379         CPU = "cascadelake";
380         *Subtype = INTEL_COREI7_CASCADELAKE;
381       } else {
382         CPU = "skylake-avx512";
383         *Subtype = INTEL_COREI7_SKYLAKE_AVX512;
384       }
385       break;
386
387     // Cannonlake:
388     case 0x66:
389       CPU = "cannonlake";
390       *Type = INTEL_COREI7;
391       *Subtype = INTEL_COREI7_CANNONLAKE;
392       break;
393
394     // Icelake:
395     case 0x7d:
396     case 0x7e:
397       CPU = "icelake-client";
398       *Type = INTEL_COREI7;
399       *Subtype = INTEL_COREI7_ICELAKE_CLIENT;
400       break;
401
402     // Icelake Xeon:
403     case 0x6a:
404     case 0x6c:
405       CPU = "icelake-server";
406       *Type = INTEL_COREI7;
407       *Subtype = INTEL_COREI7_ICELAKE_SERVER;
408       break;
409
410     case 0x1c: // Most 45 nm Intel Atom processors
411     case 0x26: // 45 nm Atom Lincroft
412     case 0x27: // 32 nm Atom Medfield
413     case 0x35: // 32 nm Atom Midview
414     case 0x36: // 32 nm Atom Midview
415       CPU = "bonnell";
416       *Type = INTEL_BONNELL;
417       break;
418
419     // Atom Silvermont codes from the Intel software optimization guide.
420     case 0x37:
421     case 0x4a:
422     case 0x4d:
423     case 0x5a:
424     case 0x5d:
425     case 0x4c: // really airmont
426       CPU = "silvermont";
427       *Type = INTEL_SILVERMONT;
428       break;
429     // Goldmont:
430     case 0x5c: // Apollo Lake
431     case 0x5f: // Denverton
432       CPU = "goldmont";
433       *Type = INTEL_GOLDMONT;
434       break; // "goldmont"
435     case 0x7a:
436       CPU = "goldmont-plus";
437       *Type = INTEL_GOLDMONT_PLUS;
438       break;
439     case 0x86:
440       CPU = "tremont";
441       *Type = INTEL_TREMONT;
442       break;
443
444     case 0x57:
445       CPU = "knl";
446       *Type = INTEL_KNL;
447       break;
448
449     case 0x85:
450       CPU = "knm";
451       *Type = INTEL_KNM;
452       break;
453
454     default: // Unknown family 6 CPU.
455       break;
456     }
457     break;
458   default:
459     break; // Unknown.
460   }
461
462   return CPU;
463 }
464
465 static const char *
466 getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model,
467                               const unsigned *Features,
468                               unsigned *Type, unsigned *Subtype) {
469   // We select CPU strings to match the code in Host.cpp, but we don't use them
470   // in compiler-rt.
471   const char *CPU = 0;
472
473   switch (Family) {
474   case 16:
475     CPU = "amdfam10";
476     *Type = AMDFAM10H;
477     switch (Model) {
478     case 2:
479       *Subtype = AMDFAM10H_BARCELONA;
480       break;
481     case 4:
482       *Subtype = AMDFAM10H_SHANGHAI;
483       break;
484     case 8:
485       *Subtype = AMDFAM10H_ISTANBUL;
486       break;
487     }
488     break;
489   case 20:
490     CPU = "btver1";
491     *Type = AMD_BTVER1;
492     break;
493   case 21:
494     CPU = "bdver1";
495     *Type = AMDFAM15H;
496     if (Model >= 0x60 && Model <= 0x7f) {
497       CPU = "bdver4";
498       *Subtype = AMDFAM15H_BDVER4;
499       break; // 60h-7Fh: Excavator
500     }
501     if (Model >= 0x30 && Model <= 0x3f) {
502       CPU = "bdver3";
503       *Subtype = AMDFAM15H_BDVER3;
504       break; // 30h-3Fh: Steamroller
505     }
506     if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) {
507       CPU = "bdver2";
508       *Subtype = AMDFAM15H_BDVER2;
509       break; // 02h, 10h-1Fh: Piledriver
510     }
511     if (Model <= 0x0f) {
512       *Subtype = AMDFAM15H_BDVER1;
513       break; // 00h-0Fh: Bulldozer
514     }
515     break;
516   case 22:
517     CPU = "btver2";
518     *Type = AMD_BTVER2;
519     break;
520   case 23:
521     CPU = "znver1";
522     *Type = AMDFAM17H;
523     if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) {
524       CPU = "znver2";
525       *Subtype = AMDFAM17H_ZNVER2;
526       break; // 30h-3fh, 71h: Zen2
527     }
528     if (Model <= 0x0f) {
529       *Subtype = AMDFAM17H_ZNVER1;
530       break; // 00h-0Fh: Zen1
531     }
532     break;
533   default:
534     break; // Unknown AMD CPU.
535   }
536
537   return CPU;
538 }
539
540 static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
541                                  unsigned *Features) {
542   unsigned EAX, EBX;
543
544 #define setFeature(F)                                                          \
545   Features[F / 32] |= 1U << (F % 32)
546
547   if ((EDX >> 15) & 1)
548     setFeature(FEATURE_CMOV);
549   if ((EDX >> 23) & 1)
550     setFeature(FEATURE_MMX);
551   if ((EDX >> 25) & 1)
552     setFeature(FEATURE_SSE);
553   if ((EDX >> 26) & 1)
554     setFeature(FEATURE_SSE2);
555
556   if ((ECX >> 0) & 1)
557     setFeature(FEATURE_SSE3);
558   if ((ECX >> 1) & 1)
559     setFeature(FEATURE_PCLMUL);
560   if ((ECX >> 9) & 1)
561     setFeature(FEATURE_SSSE3);
562   if ((ECX >> 12) & 1)
563     setFeature(FEATURE_FMA);
564   if ((ECX >> 19) & 1)
565     setFeature(FEATURE_SSE4_1);
566   if ((ECX >> 20) & 1)
567     setFeature(FEATURE_SSE4_2);
568   if ((ECX >> 23) & 1)
569     setFeature(FEATURE_POPCNT);
570   if ((ECX >> 25) & 1)
571     setFeature(FEATURE_AES);
572
573   // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
574   // indicates that the AVX registers will be saved and restored on context
575   // switch, then we have full AVX support.
576   const unsigned AVXBits = (1 << 27) | (1 << 28);
577   bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
578                 ((EAX & 0x6) == 0x6);
579 #if defined(__APPLE__)
580   // Darwin lazily saves the AVX512 context on first use: trust that the OS will
581   // save the AVX512 context if we use AVX512 instructions, even the bit is not
582   // set right now.
583   bool HasAVX512Save = true;
584 #else
585   // AVX512 requires additional context to be saved by the OS.
586   bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
587 #endif
588
589   if (HasAVX)
590     setFeature(FEATURE_AVX);
591
592   bool HasLeaf7 =
593       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
594
595   if (HasLeaf7 && ((EBX >> 3) & 1))
596     setFeature(FEATURE_BMI);
597   if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
598     setFeature(FEATURE_AVX2);
599   if (HasLeaf7 && ((EBX >> 8) & 1))
600     setFeature(FEATURE_BMI2);
601   if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
602     setFeature(FEATURE_AVX512F);
603   if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
604     setFeature(FEATURE_AVX512DQ);
605   if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
606     setFeature(FEATURE_AVX512IFMA);
607   if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
608     setFeature(FEATURE_AVX512PF);
609   if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
610     setFeature(FEATURE_AVX512ER);
611   if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
612     setFeature(FEATURE_AVX512CD);
613   if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
614     setFeature(FEATURE_AVX512BW);
615   if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
616     setFeature(FEATURE_AVX512VL);
617
618   if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
619     setFeature(FEATURE_AVX512VBMI);
620   if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
621     setFeature(FEATURE_AVX512VBMI2);
622   if (HasLeaf7 && ((ECX >> 8) & 1))
623     setFeature(FEATURE_GFNI);
624   if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
625     setFeature(FEATURE_VPCLMULQDQ);
626   if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
627     setFeature(FEATURE_AVX512VNNI);
628   if (HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save)
629     setFeature(FEATURE_AVX512BITALG);
630   if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
631     setFeature(FEATURE_AVX512VPOPCNTDQ);
632
633   if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
634     setFeature(FEATURE_AVX5124VNNIW);
635   if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
636     setFeature(FEATURE_AVX5124FMAPS);
637   if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
638     setFeature(FEATURE_AVX512VP2INTERSECT);
639
640   bool HasLeaf7Subleaf1 =
641       MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
642   if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
643     setFeature(FEATURE_AVX512BF16);
644
645   unsigned MaxExtLevel;
646   getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
647
648   bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 &&
649                      !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
650   if (HasExtLeaf1 && ((ECX >> 6) & 1))
651     setFeature(FEATURE_SSE4_A);
652   if (HasExtLeaf1 && ((ECX >> 11) & 1))
653     setFeature(FEATURE_XOP);
654   if (HasExtLeaf1 && ((ECX >> 16) & 1))
655     setFeature(FEATURE_FMA4);
656 #undef setFeature
657 }
658
659 #if defined(HAVE_INIT_PRIORITY)
660 #define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__ 101))
661 #elif __has_attribute(__constructor__)
662 #define CONSTRUCTOR_ATTRIBUTE __attribute__((__constructor__))
663 #else
664 // FIXME: For MSVC, we should make a function pointer global in .CRT$X?? so that
665 // this runs during initialization.
666 #define CONSTRUCTOR_ATTRIBUTE
667 #endif
668
669 #ifndef _WIN32
670 __attribute__((visibility("hidden")))
671 #endif
672 int __cpu_indicator_init(void) CONSTRUCTOR_ATTRIBUTE;
673
674 #ifndef _WIN32
675 __attribute__((visibility("hidden")))
676 #endif
677 struct __processor_model {
678   unsigned int __cpu_vendor;
679   unsigned int __cpu_type;
680   unsigned int __cpu_subtype;
681   unsigned int __cpu_features[1];
682 } __cpu_model = {0, 0, 0, {0}};
683
684 #ifndef _WIN32
685 __attribute__((visibility("hidden")))
686 #endif
687 unsigned int __cpu_features2 = 0;
688
689 // A constructor function that is sets __cpu_model and __cpu_features2 with
690 // the right values.  This needs to run only once.  This constructor is
691 // given the highest priority and it should run before constructors without
692 // the priority set.  However, it still runs after ifunc initializers and
693 // needs to be called explicitly there.
694
695 int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) {
696   unsigned EAX, EBX, ECX, EDX;
697   unsigned MaxLeaf = 5;
698   unsigned Vendor;
699   unsigned Model, Family;
700   unsigned Features[(CPU_FEATURE_MAX + 31) / 32] = {0};
701
702   // This function needs to run just once.
703   if (__cpu_model.__cpu_vendor)
704     return 0;
705
706   if (!isCpuIdSupported() ||
707       getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1) {
708     __cpu_model.__cpu_vendor = VENDOR_OTHER;
709     return -1;
710   }
711
712   getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX);
713   detectX86FamilyModel(EAX, &Family, &Model);
714
715   // Find available features.
716   getAvailableFeatures(ECX, EDX, MaxLeaf, &Features[0]);
717
718   assert((sizeof(Features)/sizeof(Features[0])) == 2);
719   __cpu_model.__cpu_features[0] = Features[0];
720   __cpu_features2 = Features[1];
721
722   if (Vendor == SIG_INTEL) {
723     // Get CPU type.
724     getIntelProcessorTypeAndSubtype(Family, Model, &Features[0],
725                                     &(__cpu_model.__cpu_type),
726                                     &(__cpu_model.__cpu_subtype));
727     __cpu_model.__cpu_vendor = VENDOR_INTEL;
728   } else if (Vendor == SIG_AMD) {
729     // Get CPU type.
730     getAMDProcessorTypeAndSubtype(Family, Model, &Features[0],
731                                   &(__cpu_model.__cpu_type),
732                                   &(__cpu_model.__cpu_subtype));
733     __cpu_model.__cpu_vendor = VENDOR_AMD;
734   } else
735     __cpu_model.__cpu_vendor = VENDOR_OTHER;
736
737   assert(__cpu_model.__cpu_vendor < VENDOR_MAX);
738   assert(__cpu_model.__cpu_type < CPU_TYPE_MAX);
739   assert(__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX);
740
741   return 0;
742 }
743
744 #endif