|
1 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* compile-time and runtime tests for whether to use SSE instructions */ |
|
7 |
|
8 #ifndef mozilla_SSE_h_ |
|
9 #define mozilla_SSE_h_ |
|
10 |
|
11 // for definition of MFBT_DATA |
|
12 #include "mozilla/Types.h" |
|
13 |
|
14 /** |
|
15 * The public interface of this header consists of a set of macros and |
|
16 * functions for Intel CPU features. |
|
17 * |
|
18 * DETECTING ISA EXTENSIONS |
|
19 * ======================== |
|
20 * |
|
21 * This header provides the following functions for determining whether the |
|
22 * current CPU supports a particular instruction set extension: |
|
23 * |
|
24 * mozilla::supports_mmx |
|
25 * mozilla::supports_sse |
|
26 * mozilla::supports_sse2 |
|
27 * mozilla::supports_sse3 |
|
28 * mozilla::supports_ssse3 |
|
29 * mozilla::supports_sse4a |
|
30 * mozilla::supports_sse4_1 |
|
31 * mozilla::supports_sse4_2 |
|
32 * |
|
33 * If you're writing code using inline assembly, you should guard it with a |
|
34 * call to one of these functions. For instance: |
|
35 * |
|
36 * if (mozilla::supports_sse2()) { |
|
37 * asm(" ... "); |
|
38 * } |
|
39 * else { |
|
40 * ... |
|
41 * } |
|
42 * |
|
43 * Note that these functions depend on cpuid intrinsics only available in gcc |
|
44 * 4.3 or later and MSVC 8.0 (Visual C++ 2005) or later, so they return false |
|
45 * in older compilers. (This could be fixed by replacing the code with inline |
|
46 * assembly.) |
|
47 * |
|
48 * |
|
49 * USING INTRINSICS |
|
50 * ================ |
|
51 * |
|
52 * This header also provides support for coding using CPU intrinsics. |
|
53 * |
|
54 * For each mozilla::supports_abc function, we define a MOZILLA_MAY_SUPPORT_ABC |
|
55 * macro which indicates that the target/compiler combination we're using is |
|
56 * compatible with the ABC extension. For instance, x86_64 with MSVC 2003 is |
|
57 * compatible with SSE2 but not SSE3, since although there exist x86_64 CPUs |
|
58 * with SSE3 support, MSVC 2003 only supports through SSE2. |
|
59 * |
|
60 * Until gcc fixes #pragma target [1] [2] or our x86 builds require SSE2, |
|
61 * you'll need to separate code using intrinsics into a file separate from your |
|
62 * regular code. Here's the recommended pattern: |
|
63 * |
|
64 * #ifdef MOZILLA_MAY_SUPPORT_ABC |
|
65 * namespace mozilla { |
|
66 * namespace ABC { |
|
67 * void foo(); |
|
68 * } |
|
69 * } |
|
70 * #endif |
|
71 * |
|
72 * void foo() { |
|
73 * #ifdef MOZILLA_MAY_SUPPORT_ABC |
|
74 * if (mozilla::supports_abc()) { |
|
75 * mozilla::ABC::foo(); // in a separate file |
|
76 * return; |
|
77 * } |
|
78 * #endif |
|
79 * |
|
80 * foo_unvectorized(); |
|
81 * } |
|
82 * |
|
83 * You'll need to define mozilla::ABC::foo() in a separate file and add the |
|
84 * -mabc flag when using gcc. |
|
85 * |
|
86 * [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39787 and |
|
87 * [2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41201 being fixed. |
|
88 * |
|
89 */ |
|
90 |
|
91 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) |
|
92 |
|
93 #ifdef __MMX__ |
|
94 // It's ok to use MMX instructions based on the -march option (or |
|
95 // the default for x86_64 or for Intel Mac). |
|
96 #define MOZILLA_PRESUME_MMX 1 |
|
97 #endif |
|
98 #ifdef __SSE__ |
|
99 // It's ok to use SSE instructions based on the -march option (or |
|
100 // the default for x86_64 or for Intel Mac). |
|
101 #define MOZILLA_PRESUME_SSE 1 |
|
102 #endif |
|
103 #ifdef __SSE2__ |
|
104 // It's ok to use SSE2 instructions based on the -march option (or |
|
105 // the default for x86_64 or for Intel Mac). |
|
106 #define MOZILLA_PRESUME_SSE2 1 |
|
107 #endif |
|
108 #ifdef __SSE3__ |
|
109 // It's ok to use SSE3 instructions based on the -march option (or the |
|
110 // default for Intel Mac). |
|
111 #define MOZILLA_PRESUME_SSE3 1 |
|
112 #endif |
|
113 #ifdef __SSSE3__ |
|
114 // It's ok to use SSSE3 instructions based on the -march option. |
|
115 #define MOZILLA_PRESUME_SSSE3 1 |
|
116 #endif |
|
117 #ifdef __SSE4A__ |
|
118 // It's ok to use SSE4A instructions based on the -march option. |
|
119 #define MOZILLA_PRESUME_SSE4A 1 |
|
120 #endif |
|
121 #ifdef __SSE4_1__ |
|
122 // It's ok to use SSE4.1 instructions based on the -march option. |
|
123 #define MOZILLA_PRESUME_SSE4_1 1 |
|
124 #endif |
|
125 #ifdef __SSE4_2__ |
|
126 // It's ok to use SSE4.2 instructions based on the -march option. |
|
127 #define MOZILLA_PRESUME_SSE4_2 1 |
|
128 #endif |
|
129 |
|
130 #ifdef HAVE_CPUID_H |
|
131 #define MOZILLA_SSE_HAVE_CPUID_DETECTION |
|
132 #endif |
|
133 |
|
134 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) |
|
135 |
|
136 #define MOZILLA_SSE_HAVE_CPUID_DETECTION |
|
137 |
|
138 #if defined(_M_IX86_FP) |
|
139 |
|
140 #if _M_IX86_FP >= 1 |
|
141 // It's ok to use SSE instructions based on the /arch option |
|
142 #define MOZILLA_PRESUME_SSE |
|
143 #endif |
|
144 #if _M_IX86_FP >= 2 |
|
145 // It's ok to use SSE2 instructions based on the /arch option |
|
146 #define MOZILLA_PRESUME_SSE2 |
|
147 #endif |
|
148 |
|
149 #elif defined(_M_AMD64) |
|
150 // MSVC for AMD64 doesn't support MMX, so don't presume it here. |
|
151 |
|
152 // SSE is always available on AMD64. |
|
153 #define MOZILLA_PRESUME_SSE |
|
154 // SSE2 is always available on AMD64. |
|
155 #define MOZILLA_PRESUME_SSE2 |
|
156 #endif |
|
157 |
|
158 #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) |
|
159 // Sun Studio on x86 or amd64 |
|
160 |
|
161 #define MOZILLA_SSE_HAVE_CPUID_DETECTION |
|
162 |
|
163 #if defined(__x86_64__) |
|
164 // MMX is always available on AMD64. |
|
165 #define MOZILLA_PRESUME_MMX |
|
166 // SSE is always available on AMD64. |
|
167 #define MOZILLA_PRESUME_SSE |
|
168 // SSE2 is always available on AMD64. |
|
169 #define MOZILLA_PRESUME_SSE2 |
|
170 #endif |
|
171 |
|
172 #endif |
|
173 |
|
174 namespace mozilla { |
|
175 |
|
176 namespace sse_private { |
|
177 #if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
178 #if !defined(MOZILLA_PRESUME_MMX) |
|
179 extern bool MFBT_DATA mmx_enabled; |
|
180 #endif |
|
181 #if !defined(MOZILLA_PRESUME_SSE) |
|
182 extern bool MFBT_DATA sse_enabled; |
|
183 #endif |
|
184 #if !defined(MOZILLA_PRESUME_SSE2) |
|
185 extern bool MFBT_DATA sse2_enabled; |
|
186 #endif |
|
187 #if !defined(MOZILLA_PRESUME_SSE3) |
|
188 extern bool MFBT_DATA sse3_enabled; |
|
189 #endif |
|
190 #if !defined(MOZILLA_PRESUME_SSSE3) |
|
191 extern bool MFBT_DATA ssse3_enabled; |
|
192 #endif |
|
193 #if !defined(MOZILLA_PRESUME_SSE4A) |
|
194 extern bool MFBT_DATA sse4a_enabled; |
|
195 #endif |
|
196 #if !defined(MOZILLA_PRESUME_SSE4_1) |
|
197 extern bool MFBT_DATA sse4_1_enabled; |
|
198 #endif |
|
199 #if !defined(MOZILLA_PRESUME_SSE4_2) |
|
200 extern bool MFBT_DATA sse4_2_enabled; |
|
201 #endif |
|
202 #endif |
|
203 } |
|
204 |
|
205 #if defined(MOZILLA_PRESUME_MMX) |
|
206 #define MOZILLA_MAY_SUPPORT_MMX 1 |
|
207 inline bool supports_mmx() { return true; } |
|
208 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
209 #if !(defined(_MSC_VER) && defined(_M_AMD64)) |
|
210 // Define MOZILLA_MAY_SUPPORT_MMX only if we're not on MSVC for |
|
211 // AMD64, since that compiler doesn't support MMX. |
|
212 #define MOZILLA_MAY_SUPPORT_MMX 1 |
|
213 #endif |
|
214 inline bool supports_mmx() { return sse_private::mmx_enabled; } |
|
215 #else |
|
216 inline bool supports_mmx() { return false; } |
|
217 #endif |
|
218 |
|
219 #if defined(MOZILLA_PRESUME_SSE) |
|
220 #define MOZILLA_MAY_SUPPORT_SSE 1 |
|
221 inline bool supports_sse() { return true; } |
|
222 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
223 #define MOZILLA_MAY_SUPPORT_SSE 1 |
|
224 inline bool supports_sse() { return sse_private::sse_enabled; } |
|
225 #else |
|
226 inline bool supports_sse() { return false; } |
|
227 #endif |
|
228 |
|
229 #if defined(MOZILLA_PRESUME_SSE2) |
|
230 #define MOZILLA_MAY_SUPPORT_SSE2 1 |
|
231 inline bool supports_sse2() { return true; } |
|
232 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
233 #define MOZILLA_MAY_SUPPORT_SSE2 1 |
|
234 inline bool supports_sse2() { return sse_private::sse2_enabled; } |
|
235 #else |
|
236 inline bool supports_sse2() { return false; } |
|
237 #endif |
|
238 |
|
239 #if defined(MOZILLA_PRESUME_SSE3) |
|
240 #define MOZILLA_MAY_SUPPORT_SSE3 1 |
|
241 inline bool supports_sse3() { return true; } |
|
242 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
243 #define MOZILLA_MAY_SUPPORT_SSE3 1 |
|
244 inline bool supports_sse3() { return sse_private::sse3_enabled; } |
|
245 #else |
|
246 inline bool supports_sse3() { return false; } |
|
247 #endif |
|
248 |
|
249 #if defined(MOZILLA_PRESUME_SSSE3) |
|
250 #define MOZILLA_MAY_SUPPORT_SSSE3 1 |
|
251 inline bool supports_ssse3() { return true; } |
|
252 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
253 #define MOZILLA_MAY_SUPPORT_SSSE3 1 |
|
254 inline bool supports_ssse3() { return sse_private::ssse3_enabled; } |
|
255 #else |
|
256 inline bool supports_ssse3() { return false; } |
|
257 #endif |
|
258 |
|
259 #if defined(MOZILLA_PRESUME_SSE4A) |
|
260 #define MOZILLA_MAY_SUPPORT_SSE4A 1 |
|
261 inline bool supports_sse4a() { return true; } |
|
262 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
263 #define MOZILLA_MAY_SUPPORT_SSE4A 1 |
|
264 inline bool supports_sse4a() { return sse_private::sse4a_enabled; } |
|
265 #else |
|
266 inline bool supports_sse4a() { return false; } |
|
267 #endif |
|
268 |
|
269 #if defined(MOZILLA_PRESUME_SSE4_1) |
|
270 #define MOZILLA_MAY_SUPPORT_SSE4_1 1 |
|
271 inline bool supports_sse4_1() { return true; } |
|
272 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
273 #define MOZILLA_MAY_SUPPORT_SSE4_1 1 |
|
274 inline bool supports_sse4_1() { return sse_private::sse4_1_enabled; } |
|
275 #else |
|
276 inline bool supports_sse4_1() { return false; } |
|
277 #endif |
|
278 |
|
279 #if defined(MOZILLA_PRESUME_SSE4_2) |
|
280 #define MOZILLA_MAY_SUPPORT_SSE4_2 1 |
|
281 inline bool supports_sse4_2() { return true; } |
|
282 #elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION) |
|
283 #define MOZILLA_MAY_SUPPORT_SSE4_2 1 |
|
284 inline bool supports_sse4_2() { return sse_private::sse4_2_enabled; } |
|
285 #else |
|
286 inline bool supports_sse4_2() { return false; } |
|
287 #endif |
|
288 |
|
289 } |
|
290 |
|
291 #endif /* !defined(mozilla_SSE_h_) */ |