Detect the widest SIMD level available on the executing CPU.
Detect the widest SIMD level available on the executing CPU.The result is computed once on first call and cached in a function-local static, so subsequent calls are effectively free (a single load).
This function never panics.
#pragma once
#include <cstdint>
#if defined(_MSC_VER)
# include <intrin.h>
# include <immintrin.h>
#elif defined(__GNUC__) || defined(__clang__)
# include <cpuid.h>
# include <immintrin.h>
#endif
};
namespace detail {
inline void cpuid(std::uint32_t leaf, std::uint32_t subleaf,
std::uint32_t out[4]) noexcept {
#if defined(_MSC_VER)
int regs[4] = {0};
__cpuidex(regs, static_cast<int>(leaf), static_cast<int>(subleaf));
for (int i = 0; i < 4; ++i)
out[i] = static_cast<std::uint32_t>(regs[i]);
#elif defined(__GNUC__) || defined(__clang__)
__cpuid_count(leaf, subleaf, out[0], out[1], out[2], out[3]);
#else
out[0] = out[1] = out[2] = out[3] = 0u;
#endif
}
inline std::uint64_t
xgetbv(std::uint32_t xcr)
noexcept {
#if defined(_MSC_VER)
return _xgetbv(xcr);
#elif (defined(__GNUC__) || defined(__clang__)) && defined(__XSAVE__)
std::uint32_t lo, hi;
__asm__ volatile("xgetbv" : "=a"(lo), "=d"(hi) : "c"(xcr));
return (static_cast<std::uint64_t>(hi) << 32u) | lo;
#else
(void)xcr;
return 0u;
#endif
}
std::uint32_t regs[4] = {};
const bool osxsave = (regs[2] >> 27u) & 1u;
if (!osxsave) return false;
const std::uint64_t xcr0 =
xgetbv(0u);
return (xcr0 & 0x6u) == 0x6u;
}
const std::uint64_t xcr0 =
xgetbv(0u);
return (xcr0 & 0xE0u) == 0xE0u;
}
}
std::uint32_t max_leaf[4] = {};
const std::uint32_t max_func = max_leaf[0];
std::uint32_t leaf1[4] = {};
const bool sse42 = (leaf1[2] >> 20u) & 1u;
std::uint32_t leaf7[4] = {};
const bool avx2 = (leaf7[1] >> 5u) & 1u;
const bool avx512f = (leaf7[1] >> 16u) & 1u;
}();
return kLevel;
}
}
[[nodiscard]]
inline bool has_avx2()
noexcept {
}
[[nodiscard]]
inline bool has_sse42()
noexcept {
}
switch (level) {
default: return "UNKNOWN";
}
}
}
bool os_saves_zmm() noexcept
Probe OS support for ZMM (AVX-512) register save/restore.
void cpuid(std::uint32_t leaf, std::uint32_t subleaf, std::uint32_t out[4]) noexcept
std::uint64_t xgetbv(std::uint32_t xcr) noexcept
Read XCR0 (used to verify OS XSAVE support for YMM/ZMM state).
bool os_saves_ymm() noexcept
Probe OS support for YMM (AVX) register save/restore.
bool has_avx2() noexcept
Returns true when AVX2 is available on this CPU/OS.
const char * simd_level_name(SimdLevel level) noexcept
Human-readable name for a SimdLevel value.
bool has_avx512f() noexcept
Returns true when AVX-512F is available on this CPU/OS.
SimdLevel
Ordered enumeration of SIMD capability tiers.
@ SCALAR
No SIMD; pure scalar C++ path.
@ SSE42
SSE 4.2 — 128-bit; 2 doubles per YMM half.
@ AVX2
AVX2 — 256-bit; 4 doubles per YMM register.
bool has_sse42() noexcept
Returns true when SSE 4.2 is available on this CPU/OS.