/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkCpu_DEFINED #define SkCpu_DEFINED #include "SkTypes.h" struct SkCpu { enum { SSE1 = 1 << 0, SSE2 = 1 << 1, SSE3 = 1 << 2, SSSE3 = 1 << 3, SSE41 = 1 << 4, SSE42 = 1 << 5, AVX = 1 << 6, F16C = 1 << 7, FMA = 1 << 8, AVX2 = 1 << 9, BMI1 = 1 << 10, BMI2 = 1 << 11, // Handy alias for all the cool Haswell+ instructions. HSW = AVX2 | BMI1 | BMI2 | F16C | FMA, AVX512F = 1 << 12, AVX512DQ = 1 << 13, AVX512IFMA = 1 << 14, AVX512PF = 1 << 15, AVX512ER = 1 << 16, AVX512CD = 1 << 17, AVX512BW = 1 << 18, AVX512VL = 1 << 19, // Handy alias for all the cool Skylake Xeon+ instructions. SKX = AVX512F | AVX512DQ | AVX512CD | AVX512BW | AVX512VL, }; enum { NEON = 1 << 0, NEON_FMA = 1 << 1, VFP_FP16 = 1 << 2, CRC32 = 1 << 3, ASIMDHP = 1 << 4, }; static void CacheRuntimeFeatures(); static bool Supports(uint32_t); private: static uint32_t gCachedFeatures; }; inline bool SkCpu::Supports(uint32_t mask) { uint32_t features = gCachedFeatures; // If we mask in compile-time known lower limits, the compiler can // often compile away this entire function. #if SK_CPU_X86 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1 features |= SSE1; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 features |= SSE2; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3 features |= SSE3; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 features |= SSSE3; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41 features |= SSE41; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42 features |= SSE42; #endif #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX features |= AVX; #endif // F16C goes here if we add SK_CPU_SSE_LEVEL_F16C #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 features |= AVX2; #endif // FMA doesn't fit neatly into this total ordering. // It's available on Haswell+ just like AVX2, but it's technically a different bit. // TODO: circle back on this if we find ourselves limited by lack of compile-time FMA #if defined(SK_CPU_LIMIT_SSE41) features &= (SkCpu::SSE1 | SkCpu::SSE2 | SkCpu::SSE3 | SkCpu::SSSE3 | SkCpu::SSE41); #elif defined(SK_CPU_LIMIT_SSE2) features &= (SkCpu::SSE1 | SkCpu::SSE2); #endif #else #if defined(SK_ARM_HAS_NEON) features |= NEON; #endif #if defined(SK_CPU_ARM64) features |= NEON|NEON_FMA|VFP_FP16; #endif #if defined(SK_ARM_HAS_CRC32) features |= CRC32; #endif #endif return (features & mask) == mask; } #endif//SkCpu_DEFINED