Compare commits

...

10 Commits

Author SHA1 Message Date
Daniel Lemire 15e378af3c Adding explicit popcnt 2023-06-05 08:59:36 -04:00
Daniel Lemire fbc9b7e3fb Tweaking. 2023-05-12 16:36:21 -04:00
Daniel Lemire 1b5a9267d6 Checking if the OS supports AVX-512 2023-05-12 14:32:09 -04:00
Daniel Lemire e3c795072c Fixing include 2023-05-05 22:28:58 -04:00
Daniel Lemire fb98cbdb3a Merge branch 'master' into dlemire/support 2023-05-05 22:13:39 -04:00
Daniel Lemire b98883b5ae Setting the variable to zero. 2023-05-05 22:05:04 -04:00
Daniel Lemire d39ef515a0 Minor fix 2023-05-05 21:55:28 -04:00
Daniel Lemire 5bbf124690 Fix. 2023-05-05 18:44:28 -04:00
Daniel Lemire f51a32ebcd Fix. 2023-05-05 18:05:55 -04:00
Daniel Lemire e9b943bf32 Adding support for AVX-512 on macOS. 2023-05-05 18:02:21 -04:00
3 changed files with 49 additions and 17 deletions
+46 -14
View File
@@ -57,7 +57,6 @@ POSSIBILITY OF SUCH DAMAGE.
namespace simdjson { namespace simdjson {
namespace internal { namespace internal {
enum instruction_set { enum instruction_set {
DEFAULT = 0x0, DEFAULT = 0x0,
NEON = 0x1, 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_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_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 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_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 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) { uint32_t *edx) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
int cpu_info[4]; int cpu_info[4];
__cpuid(cpu_info, *eax); __cpuidex(cpu_info, *eax, *ecx);
*eax = cpu_info[0]; *eax = cpu_info[0];
*ebx = cpu_info[1]; *ebx = cpu_info[1];
*ecx = cpu_info[2]; *ecx = cpu_info[2];
@@ -135,10 +137,48 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
#endif #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() { static inline uint32_t detect_supported_architectures() {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
uint32_t host_isa = 0x0; 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 // ECX for EAX=0x7
eax = 0x7; eax = 0x7;
ecx = 0x0; ecx = 0x0;
@@ -154,6 +194,10 @@ static inline uint32_t detect_supported_architectures() {
host_isa |= instruction_set::BMI2; host_isa |= instruction_set::BMI2;
} }
if (!((xcr0 & cpuid_avx512_saved) == cpuid_avx512_saved)) {
return host_isa;
}
if (ebx & cpuid_avx512f_bit) { if (ebx & cpuid_avx512f_bit) {
host_isa |= instruction_set::AVX512F; host_isa |= instruction_set::AVX512F;
} }
@@ -190,18 +234,6 @@ static inline uint32_t detect_supported_architectures() {
host_isa |= instruction_set::AVX512VBMI2; 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; return host_isa;
} }
#else // fallback #else // fallback
+1 -1
View File
@@ -13758,7 +13758,7 @@ simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(c
#define SIMDJSON_TARGET_ICELAKE #define SIMDJSON_TARGET_ICELAKE
#define SIMDJSON_UNTARGET_ICELAKE #define SIMDJSON_UNTARGET_ICELAKE
#else #else
#define SIMDJSON_TARGET_ICELAKE SIMDJSON_TARGET_REGION("avx512f,avx512dq,avx512cd,avx512bw,avx512vbmi,avx512vbmi2,avx512vl,avx2,bmi,pclmul,lzcnt") #define SIMDJSON_TARGET_ICELAKE SIMDJSON_TARGET_REGION("avx512f,avx512dq,avx512cd,avx512bw,avx512vbmi,avx512vbmi2,avx512vl,avx2,bmi,pclmul,lzcnt,popcnt")
#define SIMDJSON_UNTARGET_ICELAKE SIMDJSON_UNTARGET_REGION #define SIMDJSON_UNTARGET_ICELAKE SIMDJSON_UNTARGET_REGION
#endif #endif
+2 -2
View File
@@ -81,13 +81,13 @@ void basics_error_3() {
dom::object innerobj; dom::object innerobj;
if ((error = key_value.value.get(innerobj))) { cerr << error << endl; exit(1); } 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); } if ((error = innerobj["a"].get(va))) { cerr << error << endl; exit(1); }
cout << "a: " << va << ", "; cout << "a: " << va << ", ";
if ((error = innerobj["b"].get(vb))) { cerr << error << endl; exit(1); } if ((error = innerobj["b"].get(vb))) { cerr << error << endl; exit(1); }
cout << "b: " << vb << ", "; cout << "b: " << vb << ", ";
int64_t vc; int64_t vc{};
if ((error = innerobj["c"].get(vc))) { cerr << error << endl; exit(1); } if ((error = innerobj["c"].get(vc))) { cerr << error << endl; exit(1); }
cout << "c: " << vc << endl; cout << "c: " << vc << endl;
} }