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 "include/core/SkTypes.h"
12
13struct 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 ASIMDHP = 1 << 4,
48 };
49
50 static void CacheRuntimeFeatures();
51 static bool Supports(uint32_t);
52private:
53 static uint32_t gCachedFeatures;
54};
55
56inline bool SkCpu::Supports(uint32_t mask) {
57 uint32_t features = gCachedFeatures;
58
59 // If we mask in compile-time known lower limits, the compiler can
60 // often compile away this entire function.
61#if SK_CPU_X86
62 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
63 features |= SSE1;
64 #endif
65 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
66 features |= SSE2;
67 #endif
68 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3
69 features |= SSE3;
70 #endif
71 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
72 features |= SSSE3;
73 #endif
74 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
75 features |= SSE41;
76 #endif
77 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42
78 features |= SSE42;
79 #endif
80 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX
81 features |= AVX;
82 #endif
83 // F16C goes here if we add SK_CPU_SSE_LEVEL_F16C
84 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
85 features |= AVX2;
86 #endif
87 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
88 features |= (AVX512F | AVX512DQ | AVX512CD | AVX512BW | AVX512VL);
89 #endif
90 // FMA doesn't fit neatly into this total ordering.
91 // It's available on Haswell+ just like AVX2, but it's technically a different bit.
92 // TODO: circle back on this if we find ourselves limited by lack of compile-time FMA
93
94 #if defined(SK_CPU_LIMIT_AVX)
95 features &= (SSE1 | SSE2 | SSE3 | SSSE3 | SSE41 | SSE42 | AVX);
96 #elif defined(SK_CPU_LIMIT_SSE41)
97 features &= (SSE1 | SSE2 | SSE3 | SSSE3 | SSE41);
98 #elif defined(SK_CPU_LIMIT_SSE2)
99 features &= (SSE1 | SSE2);
100 #endif
101
102#else
103 #if defined(SK_ARM_HAS_NEON)
104 features |= NEON;
105 #endif
106
107 #if defined(SK_CPU_ARM64)
108 features |= NEON|NEON_FMA|VFP_FP16;
109 #endif
110
111 #if defined(SK_ARM_HAS_CRC32)
112 features |= CRC32;
113 #endif
114
115#endif
116 return (features & mask) == mask;
117}
118
119#endif//SkCpu_DEFINED
120