#pragma once #include "types.h" #include "compiler.h" #include <util/generic/singleton.h> #define Y_CPU_ID_ENUMERATE(F) \ F(SSE) \ F(SSE2) \ F(SSE3) \ F(SSSE3) \ F(SSE41) \ F(SSE42) \ F(F16C) \ F(POPCNT) \ F(BMI1) \ F(BMI2) \ F(PCLMUL) \ F(AES) \ F(AVX) \ F(FMA) \ F(AVX2) \ F(AVX512F) \ F(AVX512DQ) \ F(AVX512IFMA) \ F(AVX512PF) \ F(AVX512ER) \ F(AVX512CD) \ F(AVX512BW) \ F(AVX512VL) \ F(AVX512VBMI) \ F(PREFETCHWT1) \ F(SHA) \ F(ADX) \ F(RDRAND) \ F(RDSEED) \ F(PCOMMIT) \ F(RDTSCP) \ F(CLFLUSHOPT) \ F(CLWB) \ F(XSAVE) \ F(OSXSAVE) #define Y_CPU_ID_ENUMERATE_OUTLINED_CACHED_DEFINE(F) \ F(F16C) \ F(BMI1) \ F(BMI2) \ F(PCLMUL) \ F(AES) \ F(AVX) \ F(FMA) \ F(AVX2) \ F(AVX512F) \ F(AVX512DQ) \ F(AVX512IFMA) \ F(AVX512PF) \ F(AVX512ER) \ F(AVX512CD) \ F(AVX512BW) \ F(AVX512VL) \ F(AVX512VBMI) \ F(PREFETCHWT1) \ F(SHA) \ F(ADX) \ F(RDRAND) \ F(RDSEED) \ F(PCOMMIT) \ F(RDTSCP) \ F(CLFLUSHOPT) \ F(CLWB) \ F(XSAVE) \ F(OSXSAVE) namespace NX86 { /** * returns false on non-x86 platforms */ bool CpuId(ui32 op, ui32 res[4]) noexcept; bool CpuId(ui32 op, ui32 subOp, ui32 res[4]) noexcept; #define Y_DEF_NAME(X) Y_CONST_FUNCTION bool Have##X() noexcept; Y_CPU_ID_ENUMERATE(Y_DEF_NAME) #undef Y_DEF_NAME #define Y_DEF_NAME(X) Y_CONST_FUNCTION bool CachedHave##X() noexcept; Y_CPU_ID_ENUMERATE_OUTLINED_CACHED_DEFINE(Y_DEF_NAME) #undef Y_DEF_NAME struct TFlagsCache { #define Y_DEF_NAME(X) const bool Have##X##_ = NX86::Have##X(); Y_CPU_ID_ENUMERATE(Y_DEF_NAME) #undef Y_DEF_NAME }; #define Y_LOOKUP_CPU_ID_IMPL(X) return SingletonWithPriority<TFlagsCache, 0>()->Have##X##_; inline bool CachedHaveSSE() noexcept { #ifdef _sse_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSE) #endif } inline bool CachedHaveSSE2() noexcept { #ifdef _sse2_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSE2) #endif } inline bool CachedHaveSSE3() noexcept { #ifdef _sse3_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSE3) #endif } inline bool CachedHaveSSSE3() noexcept { #ifdef _ssse3_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSSE3) #endif } inline bool CachedHaveSSE41() noexcept { #ifdef _sse4_1_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSE41) #endif } inline bool CachedHaveSSE42() noexcept { #ifdef _sse4_2_ return true; #else Y_LOOKUP_CPU_ID_IMPL(SSE42) #endif } inline bool CachedHavePOPCNT() noexcept { #ifdef _popcnt_ return true; #else Y_LOOKUP_CPU_ID_IMPL(POPCNT) #endif } #undef Y_LOOKUP_CPU_ID_IMPL } const char* CpuBrand(ui32 store[12]) noexcept;