xref: /aosp_15_r20/external/skia/src/opts/SkOpts_SetTarget.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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 // Include guards are intentionally omitted
9 
10 #include "include/private/base/SkFeatures.h"
11 
12 #if !defined(SK_OPTS_TARGET)
13     #error Define SK_OPTS_TARGET before including SkOpts_SetTarget
14 #endif
15 
16 #if defined(SK_OPTS_NS)
17     // For testing define SK_OPTS_NS before including.
18 #elif SK_OPTS_TARGET == SK_OPTS_TARGET_DEFAULT
19 
20     #if defined(SK_ARM_HAS_NEON)
21         #define SK_OPTS_NS neon
22     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
23         #define SK_OPTS_NS skx
24     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
25         #define SK_OPTS_NS avx2
26     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX
27         #define SK_OPTS_NS avx
28     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42
29         #define SK_OPTS_NS sse42
30     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
31         #define SK_OPTS_NS sse41
32     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
33         #define SK_OPTS_NS ssse3
34     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3
35         #define SK_OPTS_NS sse3
36     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
37         #define SK_OPTS_NS sse2
38     #elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
39         #define SK_OPTS_NS sse
40     #elif SK_CPU_LSX_LEVEL >= SK_CPU_LSX_LEVEL_LASX
41         #define SK_OPTS_NS lasx
42     #elif SK_CPU_LSX_LEVEL >= SK_CPU_LSX_LEVEL_LSX
43         #define SK_OPTS_NS lsx
44     #else
45         #define SK_OPTS_NS portable
46     #endif
47 
48     #define DEFINE_DEFAULT(name) decltype(name) name = SK_OPTS_NS::name
49 
50 #else  // SK_OPTS_TARGET != SK_OPTS_TARGET_DEFAULT
51 
52     #if defined(SK_OLD_CPU_SSE_LEVEL)
53         #error Include SkOpts_RestoreTarget before re-including SkOpts_SetTarget
54     #endif
55 
56     #define SK_OLD_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL
57     #undef SK_CPU_SSE_LEVEL
58     #undef SK_CPU_LSX_LEVEL
59 
60     // NOTE: Below, we automatically include arch-specific intrinsic headers when we've detected
61     // that the compiler is clang-cl. Clang's headers skip including "unsupported" intrinsics (via
62     // defines like __AVX__ etc.), but only when _MSC_VER is also defined. To get around that, we
63     // directly include the headers for any intrinsics that ought to be present in each opts target.
64     //
65     // Each of the specific intrinsic headers also checks to ensure that immintrin.h has been
66     // included, so do that here, first.
67     #if defined(__clang__) && defined(_MSC_VER)
68         #include <immintrin.h>
69     #endif
70 
71     // Why not put the target string in a #define, and remove the boilerplate? Because GCC doesn't
72     // allow the target() option to be expanded by the preprocessor - it must be a literal string.
73     #if SK_OPTS_TARGET == SK_OPTS_TARGET_SSSE3
74 
75         #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSSE3
76         #define SK_OPTS_NS ssse3
77 
78         #if defined(__clang__)
79             #pragma clang attribute push(__attribute__((target("sse2,ssse3"))), apply_to=function)
80         #elif defined(__GNUC__)
81             #pragma GCC push_options
82             #pragma GCC target("sse2,ssse3")
83         #endif
84 
85         #if defined(__clang__) && defined(_MSC_VER)
86             #include <pmmintrin.h>
87             #include <tmmintrin.h>
88         #endif
89 
90     #elif SK_OPTS_TARGET == SK_OPTS_TARGET_AVX
91 
92         #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
93         #define SK_OPTS_NS avx
94 
95         #if defined(__clang__)
96             #pragma clang attribute push(__attribute__((target("sse2,ssse3,sse4.1,sse4.2,avx"))), apply_to=function)
97         #elif defined(__GNUC__)
98             #pragma GCC push_options
99             #pragma GCC target("sse2,ssse3,sse4.1,sse4.2,avx")
100         #endif
101 
102         #if defined(__clang__) && defined(_MSC_VER)
103             #include <pmmintrin.h>
104             #include <tmmintrin.h>
105             #include <smmintrin.h>
106             #include <avxintrin.h>
107         #endif
108 
109     #elif SK_OPTS_TARGET == SK_OPTS_TARGET_HSW
110 
111         #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
112         #define SK_OPTS_NS hsw
113 
114         #if defined(__clang__)
115             #pragma clang attribute push(__attribute__((target("sse2,ssse3,sse4.1,sse4.2,avx,avx2,bmi,bmi2,f16c,fma"))), apply_to=function)
116         #elif defined(__GNUC__)
117             #pragma GCC push_options
118             #pragma GCC target("sse2,ssse3,sse4.1,sse4.2,avx,avx2,bmi,bmi2,f16c,fma")
119         #endif
120 
121         #if defined(__clang__) && defined(_MSC_VER)
122             #include <pmmintrin.h>
123             #include <tmmintrin.h>
124             #include <smmintrin.h>
125             #include <avxintrin.h>
126             #include <avx2intrin.h>
127             #include <f16cintrin.h>
128             #include <bmi2intrin.h>
129             #include <fmaintrin.h>
130         #endif
131 
132     #elif SK_OPTS_TARGET == SK_OPTS_TARGET_LASX
133 
134         #define SK_CPU_LSX_LEVEL SK_CPU_LSX_LEVEL_LASX
135         #define SK_OPTS_NS lasx
136         // The intrinsic from lasxintrin.h is wrapped by the __loongarch_asx macro, so we need to define it.
137         #define __loongarch_asx
138 
139         #if defined(__clang__)
140           #pragma clang attribute push(__attribute__((target("lasx"))), apply_to=function)
141         #endif
142 
143     #else
144         #error Unexpected value of SK_OPTS_TARGET
145 
146     #endif
147 
148 #endif  // !SK_OPTS_TARGET_DEFAULT
149