1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkCpu_DEFINED 9 #define SkCpu_DEFINED 10 11 #include "SkTypes.h" 12 13 struct SkCpu { 14 enum { 15 SSE1 = 1 << 0, 16 SSE2 = 1 << 1, 17 SSE3 = 1 << 2, 18 SSSE3 = 1 << 3, 19 SSE41 = 1 << 4, 20 SSE42 = 1 << 5, 21 AVX = 1 << 6, 22 F16C = 1 << 7, 23 FMA = 1 << 8, 24 AVX2 = 1 << 9, 25 BMI1 = 1 << 10, 26 BMI2 = 1 << 11, 27 // Handy alias for all the cool Haswell+ instructions. 28 HSW = AVX2 | BMI1 | BMI2 | F16C | FMA, 29 30 AVX512F = 1 << 12, 31 AVX512DQ = 1 << 13, 32 AVX512IFMA = 1 << 14, 33 AVX512PF = 1 << 15, 34 AVX512ER = 1 << 16, 35 AVX512CD = 1 << 17, 36 AVX512BW = 1 << 18, 37 AVX512VL = 1 << 19, 38 39 // Handy alias for all the cool Skylake Xeon+ instructions. 40 SKX = AVX512F | AVX512DQ | AVX512CD | AVX512BW | AVX512VL, 41 }; 42 enum { 43 NEON = 1 << 0, 44 NEON_FMA = 1 << 1, 45 VFP_FP16 = 1 << 2, 46 CRC32 = 1 << 3, 47 }; 48 49 static void CacheRuntimeFeatures(); 50 static bool Supports(uint32_t); 51 private: 52 static uint32_t gCachedFeatures; 53 }; 54 55 inline bool SkCpu::Supports(uint32_t mask) { 56 uint32_t features = gCachedFeatures; 57 58 // If we mask in compile-time known lower limits, the compiler can 59 // often compile away this entire function. 60 #if SK_CPU_X86 61 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1 62 features |= SSE1; 63 #endif 64 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 65 features |= SSE2; 66 #endif 67 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3 68 features |= SSE3; 69 #endif 70 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3 71 features |= SSSE3; 72 #endif 73 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41 74 features |= SSE41; 75 #endif 76 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42 77 features |= SSE42; 78 #endif 79 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX 80 features |= AVX; 81 #endif 82 // F16C goes here if we add SK_CPU_SSE_LEVEL_F16C 83 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 84 features |= AVX2; 85 #endif 86 // FMA doesn't fit neatly into this total ordering. 87 // It's available on Haswell+ just like AVX2, but it's technically a different bit. 88 // TODO: circle back on this if we find ourselves limited by lack of compile-time FMA 89 90 #if defined(SK_CPU_LIMIT_SSE41) 91 features &= (SkCpu::SSE1 | SkCpu::SSE2 | SkCpu::SSE3 | SkCpu::SSSE3 | SkCpu::SSE41); 92 #elif defined(SK_CPU_LIMIT_SSE2) 93 features &= (SkCpu::SSE1 | SkCpu::SSE2); 94 #endif 95 96 #else 97 #if defined(SK_ARM_HAS_NEON) 98 features |= NEON; 99 #endif 100 101 #if defined(SK_CPU_ARM64) 102 features |= NEON|NEON_FMA|VFP_FP16; 103 #endif 104 105 #if defined(SK_ARM_HAS_CRC32) 106 features |= CRC32; 107 #endif 108 109 #endif 110 return (features & mask) == mask; 111 } 112 113 #endif//SkCpu_DEFINED 114