/////////////////////////////////////////////////////////////////////// // File: simddetect.cpp // Description: Architecture detector. // Author: Stefan Weil (based on code from Ray Smith) // // (C) Copyright 2014, Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /////////////////////////////////////////////////////////////////////// #include "simddetect.h" #include "tprintf.h" #undef X86_BUILD #if defined(__x86_64__) || defined(__i386__) || defined(_WIN32) #if !defined(ANDROID_BUILD) #define X86_BUILD 1 #endif // !ANDROID_BUILD #endif // x86 target #if defined(X86_BUILD) #if defined(__GNUC__) #include #elif defined(_WIN32) #include #endif #endif SIMDDetect SIMDDetect::detector; // If true, then AVX has been detected. bool SIMDDetect::avx_available_; bool SIMDDetect::avx2_available_; bool SIMDDetect::avx512F_available_; bool SIMDDetect::avx512BW_available_; // If true, then SSe4.1 has been detected. bool SIMDDetect::sse_available_; // Constructor. // Tests the architecture in a system-dependent way to detect AVX, SSE and // any other available SIMD equipment. // __GNUC__ is also defined by compilers that include GNU extensions such as // clang. SIMDDetect::SIMDDetect() { #if defined(X86_BUILD) #if defined(__GNUC__) unsigned int eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) != 0) { // Note that these tests all use hex because the older compilers don't have // the newer flags. sse_available_ = (ecx & 0x00080000) != 0; avx_available_ = (ecx & 0x10000000) != 0; if (avx_available_) { // There is supposed to be a __get_cpuid_count function, but this is all // there is in my cpuid.h. It is a macro for an asm statement and cannot // be used inside an if. __cpuid_count(7, 0, eax, ebx, ecx, edx); avx2_available_ = (ebx & 0x00000020) != 0; avx512F_available_ = (ebx & 0x00010000) != 0; avx512BW_available_ = (ebx & 0x40000000) != 0; } } #elif defined(_WIN32) int cpuInfo[4]; __cpuid(cpuInfo, 0); if (cpuInfo[0] >= 1) { __cpuid(cpuInfo, 1); sse_available_ = (cpuInfo[2] & 0x00080000) != 0; avx_available_ = (cpuInfo[2] & 0x10000000) != 0; } #else #error "I don't know how to test for SIMD with this compiler" #endif #endif // X86_BUILD }