Checking OS support for AVX-512 (#1998)

* Adding support for AVX-512 on macOS.

* Fix.

* Fix.

* Minor fix

* Setting the variable to zero.

* Fixing include

* Checking if the OS supports AVX-512

* Tweaking.

---------

Co-authored-by: Daniel Lemire <dlemire@lemire.me>
This commit is contained in:
Daniel Lemire
2023-05-12 19:25:02 -04:00
committed by GitHub
parent 21a2ccaeb8
commit 2a68a32012
2 changed files with 48 additions and 16 deletions
+46 -14
View File
@@ -57,7 +57,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace simdjson {
namespace internal {
enum instruction_set {
DEFAULT = 0x0,
NEON = 0x1,
@@ -107,7 +106,10 @@ constexpr uint32_t cpuid_avx512cd_bit = 1 << 28; ///< @private bit 28 of EBX
constexpr uint32_t cpuid_avx512bw_bit = 1 << 30; ///< @private bit 30 of EBX for EAX=0x7
constexpr uint32_t cpuid_avx512vl_bit = 1U << 31; ///< @private bit 31 of EBX for EAX=0x7
constexpr uint32_t cpuid_avx512vbmi2_bit = 1 << 6; ///< @private bit 6 of ECX for EAX=0x7
constexpr uint64_t cpuid_avx256_saved = uint64_t(1) << 2; ///< @private bit 2 = AVX
constexpr uint64_t cpuid_avx512_saved = uint64_t(7) << 5; ///< @private bits 5,6,7 = opmask, ZMM_hi256, hi16_ZMM
constexpr uint32_t cpuid_sse42_bit = 1 << 20; ///< @private bit 20 of ECX for EAX=0x1
constexpr uint32_t cpuid_osxsave = (uint32_t(1) << 26) | (uint32_t(1) << 27); ///< @private bits 26+27 of ECX for EAX=0x1
constexpr uint32_t cpuid_pclmulqdq_bit = 1 << 1; ///< @private bit 1 of ECX for EAX=0x1
}
@@ -117,7 +119,7 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
#if defined(_MSC_VER)
int cpu_info[4];
__cpuid(cpu_info, *eax);
__cpuidex(cpu_info, *eax, *ecx);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
@@ -135,10 +137,48 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
#endif
}
static inline uint64_t xgetbv() {
#if defined(_MSC_VER)
return _xgetbv(0);
#else
uint32_t xcr0_lo, xcr0_hi;
asm volatile("xgetbv\n\t" : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0));
return xcr0_lo | (uint64_t(xcr0_hi) << 32);
#endif
}
static inline uint32_t detect_supported_architectures() {
uint32_t eax, ebx, ecx, edx;
uint32_t host_isa = 0x0;
// EBX for EAX=0x1
eax = 0x1;
ecx = 0x0;
cpuid(&eax, &ebx, &ecx, &edx);
if (ecx & cpuid_sse42_bit) {
host_isa |= instruction_set::SSE42;
} else {
return host_isa; // everything after is redundant
}
if (ecx & cpuid_pclmulqdq_bit) {
host_isa |= instruction_set::PCLMULQDQ;
}
if ((ecx & cpuid_osxsave) != cpuid_osxsave) {
return host_isa;
}
// xgetbv for checking if the OS saves registers
uint64_t xcr0 = xgetbv();
if ((xcr0 & cpuid_avx256_saved) == 0) {
return host_isa;
}
// ECX for EAX=0x7
eax = 0x7;
ecx = 0x0;
@@ -154,6 +194,10 @@ static inline uint32_t detect_supported_architectures() {
host_isa |= instruction_set::BMI2;
}
if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) {
return host_isa;
}
if (ebx & cpuid_avx512f_bit) {
host_isa |= instruction_set::AVX512F;
}
@@ -190,18 +234,6 @@ static inline uint32_t detect_supported_architectures() {
host_isa |= instruction_set::AVX512VBMI2;
}
// EBX for EAX=0x1
eax = 0x1;
cpuid(&eax, &ebx, &ecx, &edx);
if (ecx & cpuid_sse42_bit) {
host_isa |= instruction_set::SSE42;
}
if (ecx & cpuid_pclmulqdq_bit) {
host_isa |= instruction_set::PCLMULQDQ;
}
return host_isa;
}
#else // fallback
+2 -2
View File
@@ -81,13 +81,13 @@ void basics_error_3() {
dom::object innerobj;
if ((error = key_value.value.get(innerobj))) { cerr << error << endl; exit(1); }
double va, vb;
double va{}, vb{};
if ((error = innerobj["a"].get(va))) { cerr << error << endl; exit(1); }
cout << "a: " << va << ", ";
if ((error = innerobj["b"].get(vb))) { cerr << error << endl; exit(1); }
cout << "b: " << vb << ", ";
int64_t vc;
int64_t vc{};
if ((error = innerobj["c"].get(vc))) { cerr << error << endl; exit(1); }
cout << "c: " << vc << endl;
}