Eigen  5.0.1
 
Loading...
Searching...
No Matches
ConfigureVectorization.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2018 Gael Guennebaud <gael.guennebaud@inria.fr>
5// Copyright (C) 2020, Arm Limited and Contributors
6//
7// This Source Code Form is subject to the terms of the Mozilla
8// Public License v. 2.0. If a copy of the MPL was not distributed
9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10// SPDX-License-Identifier: MPL-2.0
11
12#ifndef EIGEN_CONFIGURE_VECTORIZATION_H
13#define EIGEN_CONFIGURE_VECTORIZATION_H
14
15// Prepare for using the generic clang backend if requested.
16#if defined(EIGEN_VECTORIZE_GENERIC) && !defined(EIGEN_GENERIC_VECTOR_SIZE_BYTES)
17#define EIGEN_GENERIC_VECTOR_SIZE_BYTES 64
18#endif
19#if defined(EIGEN_VECTORIZE_GENERIC) && !defined(EIGEN_DONT_VECTORIZE) && !defined(EIGEN_DONT_ALIGN)
20#if !EIGEN_ARCH_VECTOR_EXTENSIONS
21#error "The compiler does not support clang vector extensions."
22#endif
23#define EIGEN_VECTORIZE
24#define EIGEN_MAX_ALIGN_BYTES EIGEN_GENERIC_VECTOR_SIZE_BYTES
25#endif
26
27//------------------------------------------------------------------------------------------
28// Static and dynamic alignment control
29//
30// The main purpose of this section is to define EIGEN_MAX_ALIGN_BYTES and EIGEN_MAX_STATIC_ALIGN_BYTES
31// as the maximal boundary in bytes on which dynamically and statically allocated data may be alignment respectively.
32// The values of EIGEN_MAX_ALIGN_BYTES and EIGEN_MAX_STATIC_ALIGN_BYTES can be specified by the user. If not,
33// a default value is automatically computed based on architecture, compiler, and OS.
34//
35// This section also defines macros EIGEN_ALIGN_TO_BOUNDARY(N) and the shortcuts EIGEN_ALIGN{8,16,32,_MAX}
36// to be used to declare statically aligned buffers.
37//------------------------------------------------------------------------------------------
38
39/* EIGEN_ALIGN_TO_BOUNDARY(n) forces data to be n-byte aligned. This is used to satisfy SIMD requirements.
40 * However, we do that EVEN if vectorization (EIGEN_VECTORIZE) is disabled,
41 * so that vectorization doesn't affect binary compatibility.
42 *
43 * If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link
44 * vectorized and non-vectorized code.
45 */
46#if (defined EIGEN_CUDACC)
47#define EIGEN_ALIGN_TO_BOUNDARY(n) __align__(n)
48#define EIGEN_ALIGNOF(x) __alignof(x)
49#else
50#define EIGEN_ALIGN_TO_BOUNDARY(n) alignas(n)
51#define EIGEN_ALIGNOF(x) alignof(x)
52#endif
53
54// Align to the boundary that avoids false sharing.
55// Pinned to 128 bytes to preserve a stable ABI across architectures and standard libraries
56// and avoid GCC -Winterference-size warnings.
57#ifndef EIGEN_ALIGN_TO_AVOID_FALSE_SHARING
58#define EIGEN_ALIGN_TO_AVOID_FALSE_SHARING EIGEN_ALIGN_TO_BOUNDARY(128)
59#endif
60
61// If the user explicitly disable vectorization, then we also disable alignment
62#if defined(EIGEN_DONT_VECTORIZE)
63#if defined(EIGEN_GPUCC)
64// GPU code is always vectorized and requires memory alignment for
65// statically allocated buffers.
66#define EIGEN_IDEAL_MAX_ALIGN_BYTES 16
67#else
68#define EIGEN_IDEAL_MAX_ALIGN_BYTES 0
69#endif
70#elif defined(EIGEN_VECTORIZE_GENERIC)
71// Generic clang backend overrides native SIMD; align to the generic vector size.
72#define EIGEN_IDEAL_MAX_ALIGN_BYTES EIGEN_GENERIC_VECTOR_SIZE_BYTES
73#elif defined(__AVX512F__)
74// 64 bytes static alignment is preferred only if really required
75#define EIGEN_IDEAL_MAX_ALIGN_BYTES 64
76// Deliberately no SME case: this block runs long before EIGEN_VECTORIZE_SME is
77// defined, so a test for it here is unreachable -- and moving it would be wrong
78// rather than merely late. Raising the value changes the alignment, and so the
79// ABI, of every fixed-size object relative to a NEON build of the same headers;
80// past 16 bytes aligned_malloc also switches to the prefixed
81// handmade_aligned_malloc, so a matrix allocated in an SME translation unit and
82// freed in a non-SME one corrupts the heap. Keeping 16 is not free: the SME GEMM
83// kernel is up to 3.4x faster at small sizes when the result matrix starts on a
84// 64-byte boundary, which is what 64 here would give every Eigen-owned matrix.
85#elif defined(EIGEN_ARM64_USE_SVE) && defined(__ARM_FEATURE_SVE_BITS) && (__ARM_FEATURE_SVE_BITS != 0)
86// A fixed-length SVE packet is __ARM_FEATURE_SVE_BITS/8 bytes wide and asks for
87// exactly that much alignment; a fixed-size object has to be able to offer it or
88// it never reaches the vectorized path. The Alignment enum stops at 128.
89#if __ARM_FEATURE_SVE_BITS <= 1024
90#define EIGEN_IDEAL_MAX_ALIGN_BYTES (__ARM_FEATURE_SVE_BITS / 8)
91#else
92#define EIGEN_IDEAL_MAX_ALIGN_BYTES 128
93#endif
94#elif defined(__AVX__)
95// 32 bytes static alignment is preferred only if really required
96#define EIGEN_IDEAL_MAX_ALIGN_BYTES 32
97#elif defined __HVX__ && (__HVX_LENGTH__ == 128)
98#define EIGEN_IDEAL_MAX_ALIGN_BYTES 128
99#elif defined(EIGEN_RISCV64_USE_RVV10)
100#if __riscv_v_fixed_vlen <= 512
101#define EIGEN_IDEAL_MAX_ALIGN_BYTES 64
102#else
103#define EIGEN_IDEAL_MAX_ALIGN_BYTES 128
104#endif
105#else
106#define EIGEN_IDEAL_MAX_ALIGN_BYTES 16
107#endif
108
109// EIGEN_MIN_ALIGN_BYTES defines the minimal value for which the notion of explicit alignment makes sense
110#define EIGEN_MIN_ALIGN_BYTES 16
111
112// Defined the boundary (in bytes) on which the data needs to be aligned. Note
113// that unless EIGEN_ALIGN is defined and not equal to 0, the data may not be
114// aligned at all regardless of the value of this #define.
115
116#if (defined(EIGEN_DONT_ALIGN_STATICALLY) || defined(EIGEN_DONT_ALIGN)) && defined(EIGEN_MAX_STATIC_ALIGN_BYTES) && \
117 EIGEN_MAX_STATIC_ALIGN_BYTES > 0
118#error EIGEN_MAX_STATIC_ALIGN_BYTES and EIGEN_DONT_ALIGN[_STATICALLY] are both defined with EIGEN_MAX_STATIC_ALIGN_BYTES!=0. Use EIGEN_MAX_STATIC_ALIGN_BYTES=0 as a synonym of EIGEN_DONT_ALIGN_STATICALLY.
119#endif
120
121// EIGEN_DONT_ALIGN_STATICALLY and EIGEN_DONT_ALIGN are deprecated
122// They imply EIGEN_MAX_STATIC_ALIGN_BYTES=0
123#if defined(EIGEN_DONT_ALIGN_STATICALLY) || defined(EIGEN_DONT_ALIGN)
124#ifdef EIGEN_MAX_STATIC_ALIGN_BYTES
125#undef EIGEN_MAX_STATIC_ALIGN_BYTES
126#endif
127#define EIGEN_MAX_STATIC_ALIGN_BYTES 0
128#endif
129
130#ifndef EIGEN_MAX_STATIC_ALIGN_BYTES
131
132// Try to automatically guess what is the best default value for EIGEN_MAX_STATIC_ALIGN_BYTES
133
134// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable
135// 16 byte alignment on all platforms where vectorization might be enabled. In theory we could always
136// enable alignment, but it can be a cause of problems on some platforms, so we just disable it in
137// certain common platform (compiler+architecture combinations) to avoid these problems.
138// Only static alignment is really problematic (relies on nonstandard compiler extensions),
139// try to keep heap alignment even when we have to disable static alignment.
140#if EIGEN_COMP_GNUC && !(EIGEN_ARCH_i386_OR_x86_64 || EIGEN_ARCH_ARM_OR_ARM64 || EIGEN_ARCH_PPC || EIGEN_ARCH_IA64 || \
141 EIGEN_ARCH_MIPS || EIGEN_ARCH_LOONGARCH64 || EIGEN_ARCH_RISCV)
142#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT 1
143#else
144#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT 0
145#endif
146
147// static alignment is completely disabled with GCC 3, Sun Studio, and QCC/QNX
148#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT && !EIGEN_COMP_SUNCC && !EIGEN_OS_QNX
149#define EIGEN_ARCH_WANTS_STACK_ALIGNMENT 1
150#else
151#define EIGEN_ARCH_WANTS_STACK_ALIGNMENT 0
152#endif
153
154#if EIGEN_ARCH_WANTS_STACK_ALIGNMENT
155#define EIGEN_MAX_STATIC_ALIGN_BYTES EIGEN_IDEAL_MAX_ALIGN_BYTES
156#else
157#define EIGEN_MAX_STATIC_ALIGN_BYTES 0
158#endif
159
160#endif
161
162// If EIGEN_MAX_ALIGN_BYTES is defined, then it is considered as an upper bound for EIGEN_MAX_STATIC_ALIGN_BYTES
163#if defined(EIGEN_MAX_ALIGN_BYTES) && EIGEN_MAX_ALIGN_BYTES < EIGEN_MAX_STATIC_ALIGN_BYTES
164#undef EIGEN_MAX_STATIC_ALIGN_BYTES
165#define EIGEN_MAX_STATIC_ALIGN_BYTES EIGEN_MAX_ALIGN_BYTES
166#endif
167
168#if EIGEN_MAX_STATIC_ALIGN_BYTES == 0 && !defined(EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT)
169#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
170#endif
171
172// At this stage, EIGEN_MAX_STATIC_ALIGN_BYTES>0 is the true test whether we want to align arrays on the stack or not.
173// It takes into account both the user choice to explicitly enable/disable alignment (by setting
174// EIGEN_MAX_STATIC_ALIGN_BYTES) and the architecture config (EIGEN_ARCH_WANTS_STACK_ALIGNMENT). Henceforth, only
175// EIGEN_MAX_STATIC_ALIGN_BYTES should be used.
176
177// Shortcuts to EIGEN_ALIGN_TO_BOUNDARY
178#define EIGEN_ALIGN8 EIGEN_ALIGN_TO_BOUNDARY(8)
179#define EIGEN_ALIGN16 EIGEN_ALIGN_TO_BOUNDARY(16)
180#define EIGEN_ALIGN32 EIGEN_ALIGN_TO_BOUNDARY(32)
181#define EIGEN_ALIGN64 EIGEN_ALIGN_TO_BOUNDARY(64)
182#if EIGEN_MAX_STATIC_ALIGN_BYTES > 0
183#define EIGEN_ALIGN_MAX EIGEN_ALIGN_TO_BOUNDARY(EIGEN_MAX_STATIC_ALIGN_BYTES)
184#else
185#define EIGEN_ALIGN_MAX
186#endif
187
188// Dynamic alignment control
189
190#if defined(EIGEN_DONT_ALIGN) && defined(EIGEN_MAX_ALIGN_BYTES) && EIGEN_MAX_ALIGN_BYTES > 0
191#error EIGEN_MAX_ALIGN_BYTES and EIGEN_DONT_ALIGN are both defined with EIGEN_MAX_ALIGN_BYTES!=0. Use EIGEN_MAX_ALIGN_BYTES=0 as a synonym of EIGEN_DONT_ALIGN.
192#endif
193
194#ifdef EIGEN_DONT_ALIGN
195#ifdef EIGEN_MAX_ALIGN_BYTES
196#undef EIGEN_MAX_ALIGN_BYTES
197#endif
198#define EIGEN_MAX_ALIGN_BYTES 0
199#elif !defined(EIGEN_MAX_ALIGN_BYTES)
200#define EIGEN_MAX_ALIGN_BYTES EIGEN_IDEAL_MAX_ALIGN_BYTES
201#endif
202
203#if EIGEN_IDEAL_MAX_ALIGN_BYTES > EIGEN_MAX_ALIGN_BYTES
204#define EIGEN_DEFAULT_ALIGN_BYTES EIGEN_IDEAL_MAX_ALIGN_BYTES
205#else
206#define EIGEN_DEFAULT_ALIGN_BYTES EIGEN_MAX_ALIGN_BYTES
207#endif
208
209#ifndef EIGEN_UNALIGNED_VECTORIZE
210#define EIGEN_UNALIGNED_VECTORIZE 1
211#endif
212
213//----------------------------------------------------------------------
214
215// if alignment is disabled, then disable vectorization. Note: EIGEN_MAX_ALIGN_BYTES is the proper check, it takes into
216// account both the user's will (EIGEN_MAX_ALIGN_BYTES,EIGEN_DONT_ALIGN) and our own platform checks
217#if EIGEN_MAX_ALIGN_BYTES == 0
218#ifndef EIGEN_DONT_VECTORIZE
219#define EIGEN_DONT_VECTORIZE
220#endif
221#endif
222
223// MSVC needs <malloc.h> for aligned allocation helpers, and 32-bit x86 uses
224// _M_IX86_FP to decide whether SSE2 is enabled.
225#if EIGEN_COMP_MSVC
226#include <malloc.h> // for _aligned_malloc -- need it regardless of whether vectorization is enabled
227// a user reported that in 64-bit mode, MSVC doesn't care to define _M_IX86_FP.
228#if (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) || EIGEN_ARCH_x86_64
229#define EIGEN_SSE2_ON_MSVC_2008_OR_LATER
230#endif
231#else
232#if defined(__SSE2__)
233#define EIGEN_SSE2_ON_NON_MSVC
234#endif
235#endif
236
237#if !(defined(EIGEN_DONT_VECTORIZE) || defined(EIGEN_GPUCC) || defined(EIGEN_VECTORIZE_GENERIC))
238
239// Whether the ARM SME backend can be built at all. Two hard requirements, both
240// properties of the translation unit rather than of the CPU:
241// - SME2, not just SME: the micro-kernel's multi-vector loads (svld1_*_x2/x4)
242// and svcount_t predicates are SME2 instructions.
243// - scalable (VLA) SVE mode: the kernel derives its ZA-tile geometry from the
244// runtime streaming vector length, so -msve-vector-bits=N would pin it to
245// one SVL and silently miscompute at any other.
246#if defined(__ARM_FEATURE_SME2) && !(defined(__ARM_FEATURE_SVE_BITS) && (__ARM_FEATURE_SVE_BITS != 0))
247#define EIGEN_ARM64_SME_USABLE
248#endif
249
250// ... and whether it is the backend to use. SME is selected automatically when
251// it is usable: unlike SVE it needs no fixed vector length, and it only
252// replaces the GEMM kernels -- everything else keeps the NEON packet path. Two
253// escapes: EIGEN_ARM64_NO_SME turns it off, and EIGEN_ARM64_USE_SVE takes
254// precedence for callers who asked for SVE specifically.
255#if defined(EIGEN_ARM64_SME_USABLE) && !defined(EIGEN_ARM64_NO_SME) && !defined(EIGEN_ARM64_USE_SVE)
256#define EIGEN_ARM64_SME_SELECTED
257#endif
258
259#if defined(EIGEN_ARM64_USE_SME) && defined(EIGEN_ARM64_NO_SME)
260#error "EIGEN_ARM64_USE_SME and EIGEN_ARM64_NO_SME are mutually exclusive."
261#endif
262
263#if defined(EIGEN_SSE2_ON_NON_MSVC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER)
264
265// Defines symbols for compile-time detection of which instructions are
266// used.
267// EIGEN_VECTORIZE_YY is defined if and only if the instruction set YY is used
268#define EIGEN_VECTORIZE
269#define EIGEN_VECTORIZE_SSE
270#define EIGEN_VECTORIZE_SSE2
271
272// Detect sse3/ssse3/sse4:
273// gcc and icc defines __SSE3__, ...
274// there is no way to know about this on msvc. You can define EIGEN_VECTORIZE_SSE* if you
275// want to force the use of those instructions with msvc.
276#ifdef __SSE3__
277#define EIGEN_VECTORIZE_SSE3
278#endif
279#ifdef __SSSE3__
280#define EIGEN_VECTORIZE_SSSE3
281#endif
282#ifdef __SSE4_1__
283#define EIGEN_VECTORIZE_SSE4_1
284#endif
285#ifdef __SSE4_2__
286#define EIGEN_VECTORIZE_SSE4_2
287#endif
288#ifdef __AVX__
289#if !defined(EIGEN_USE_SYCL) && !EIGEN_COMP_EMSCRIPTEN
290#define EIGEN_VECTORIZE_AVX
291#endif
292#define EIGEN_VECTORIZE_SSE3
293#define EIGEN_VECTORIZE_SSSE3
294#define EIGEN_VECTORIZE_SSE4_1
295#define EIGEN_VECTORIZE_SSE4_2
296#endif
297#ifdef __AVX2__
298#ifndef EIGEN_USE_SYCL
299#define EIGEN_VECTORIZE_AVX2
300#define EIGEN_VECTORIZE_AVX
301#endif
302#define EIGEN_VECTORIZE_SSE3
303#define EIGEN_VECTORIZE_SSSE3
304#define EIGEN_VECTORIZE_SSE4_1
305#define EIGEN_VECTORIZE_SSE4_2
306#endif
307#if defined(__FMA__) || (EIGEN_COMP_MSVC && defined(__AVX2__))
308// MSVC does not expose a switch dedicated for FMA
309// For MSVC, AVX2 => FMA
310#define EIGEN_VECTORIZE_FMA
311#endif
312#if defined(__AVX512F__)
313#ifndef EIGEN_VECTORIZE_FMA
314#if EIGEN_COMP_GNUC
315#error Please add -mfma to your compiler flags: compiling with -mavx512f alone without SSE/AVX FMA is not supported (bug 1638).
316#else
317#error Please enable FMA in your compiler flags (e.g. -mfma): compiling with AVX512 alone without SSE/AVX FMA is not supported (bug 1638).
318#endif
319#endif
320#ifndef EIGEN_USE_SYCL
321#define EIGEN_VECTORIZE_AVX512
322#define EIGEN_VECTORIZE_AVX2
323#define EIGEN_VECTORIZE_AVX
324#endif
325#define EIGEN_VECTORIZE_FMA
326#define EIGEN_VECTORIZE_SSE3
327#define EIGEN_VECTORIZE_SSSE3
328#define EIGEN_VECTORIZE_SSE4_1
329#define EIGEN_VECTORIZE_SSE4_2
330#ifndef EIGEN_USE_SYCL
331#ifdef __AVX512DQ__
332#define EIGEN_VECTORIZE_AVX512DQ
333#endif
334#ifdef __AVX512ER__
335#define EIGEN_VECTORIZE_AVX512ER
336#endif
337#ifdef __AVX512BF16__
338#define EIGEN_VECTORIZE_AVX512BF16
339#endif
340#ifdef __AVX512VL__
341#define EIGEN_VECTORIZE_AVX512VL
342#endif
343#ifdef __AVX512FP16__
344#if EIGEN_COMP_NVHPC
345// NVC++ exposes AVX512-FP16 inconsistently: older releases define the feature without _Float16/__m512h,
346// and 24.11-26.3 lower compare/blend intrinsics to unresolved __builtin_ia32_*ph* references.
347#elif defined(__AVX512VL__)
348#define EIGEN_VECTORIZE_AVX512FP16
349// Built-in _Float16.
350#define EIGEN_HAS_BUILTIN_FLOAT16 1
351#else
352#if EIGEN_COMP_GNUC
353#error Please add -mavx512vl to your compiler flags: compiling with -mavx512fp16 alone without AVX512-VL is not supported.
354#else
355#error Please enable AVX512-VL in your compiler flags (e.g. -mavx512vl): compiling with AVX512-FP16 alone without AVX512-VL is not supported.
356#endif
357#endif
358#endif
359#endif
360#endif
361
362// Disable AVX support on broken xcode versions
363#if (EIGEN_COMP_CLANGAPPLE == 11000033) && (__MAC_OS_X_VERSION_MIN_REQUIRED == 101500)
364// A nasty bug in the clang compiler shipped with xcode in a common compilation situation
365// when XCode 11.0 and Mac deployment target macOS 10.15 is https://trac.macports.org/ticket/58776#no1
366#ifdef EIGEN_VECTORIZE_AVX
367#undef EIGEN_VECTORIZE_AVX
368#warning \
369 "Disabling AVX support: clang compiler shipped with XCode 11.[012] generates broken assembly with -macosx-version-min=10.15 and AVX enabled. "
370#ifdef EIGEN_VECTORIZE_AVX2
371#undef EIGEN_VECTORIZE_AVX2
372#endif
373#ifdef EIGEN_VECTORIZE_FMA
374#undef EIGEN_VECTORIZE_FMA
375#endif
376#ifdef EIGEN_VECTORIZE_AVX512
377#undef EIGEN_VECTORIZE_AVX512
378#endif
379#ifdef EIGEN_VECTORIZE_AVX512DQ
380#undef EIGEN_VECTORIZE_AVX512DQ
381#endif
382#ifdef EIGEN_VECTORIZE_AVX512ER
383#undef EIGEN_VECTORIZE_AVX512ER
384#endif
385#endif
386// NOTE: Confirmed test failures in XCode 11.0, and XCode 11.2 with -macosx-version-min=10.15 and AVX
387// NOTE using -macosx-version-min=10.15 with Xcode 11.0 results in runtime segmentation faults in many tests, 11.2
388// produce core dumps in 3 tests NOTE using -macosx-version-min=10.14 produces functioning and passing tests in all
389// cases NOTE __clang_version__ "11.0.0 (clang-1100.0.33.8)" XCode 11.0 <- Produces many segfault and core dumping
390// tests
391// with -macosx-version-min=10.15 and AVX
392// NOTE __clang_version__ "11.0.0 (clang-1100.0.33.12)" XCode 11.2 <- Produces 3 core dumping tests with
393// -macosx-version-min=10.15 and AVX
394#endif
395
396// include files
397
398// This extern "C" works around a MINGW-w64 compilation issue
399// https://sourceforge.net/tracker/index.php?func=detail&aid=3018394&group_id=202880&atid=983354
400// In essence, intrin.h is included by windows.h and also declares intrinsics (just as emmintrin.h etc. below do).
401// However, intrin.h uses an extern "C" declaration, and g++ thus complains of duplicate declarations
402// with conflicting linkage. The linkage for intrinsics doesn't matter, but at that stage the compiler doesn't know;
403// so, to avoid compile errors when windows.h is included after Eigen/Core, ensure intrinsics are extern "C" here too.
404// notice that since these are C headers, the extern "C" is theoretically needed anyways.
405extern "C" {
406// ICC and Emscripten need the umbrella header instead of direct *mmintrin.h includes.
407#if EIGEN_COMP_ICC || EIGEN_COMP_EMSCRIPTEN
408#include <immintrin.h>
409#else
410#include <mmintrin.h>
411#include <emmintrin.h>
412#include <xmmintrin.h>
413#ifdef EIGEN_VECTORIZE_SSE3
414#include <pmmintrin.h>
415#endif
416#ifdef EIGEN_VECTORIZE_SSSE3
417#include <tmmintrin.h>
418#endif
419#ifdef EIGEN_VECTORIZE_SSE4_1
420#include <smmintrin.h>
421#endif
422#ifdef EIGEN_VECTORIZE_SSE4_2
423#include <nmmintrin.h>
424#endif
425#if defined(EIGEN_VECTORIZE_AVX) || defined(EIGEN_VECTORIZE_AVX512)
426#include <immintrin.h>
427#endif
428#endif
429} // end extern "C"
430
431#elif defined(__VSX__) && !defined(__APPLE__)
432
433#define EIGEN_VECTORIZE
434#define EIGEN_VECTORIZE_VSX 1
435// The POWER8 (ISA 2.07) vector instructions, such as 64-bit integer lane arithmetic and compares and vec_neg; a
436// POWER7 target has VSX without them.
437#if defined(__POWER8_VECTOR__)
438#define EIGEN_VECTORIZE_POWER8_VECTOR
439#endif
440#define EIGEN_VECTORIZE_FMA
441#include <altivec.h>
442// We need to #undef macros defined by <altivec.h> that conflict with standard C++ names.
443// => use __vector instead of vector
444#undef bool
445#undef vector
446#undef pixel
447
448#elif defined __ALTIVEC__
449
450#define EIGEN_VECTORIZE
451#define EIGEN_VECTORIZE_ALTIVEC
452#define EIGEN_VECTORIZE_FMA
453#include <altivec.h>
454// We need to #undef macros defined by <altivec.h> that conflict with standard C++ names.
455// => use __vector instead of vector
456#undef bool
457#undef vector
458#undef pixel
459
460#elif defined(EIGEN_ARM64_USE_SME) && !defined(EIGEN_ARM64_SME_USABLE)
461
462#error \
463 "EIGEN_ARM64_USE_SME requires a compiler targeting SME2 in scalable (SVE VLA) mode: build with e.g. -march=armv9.2-a+sme2 and without -msve-vector-bits."
464
465#elif ((defined __ARM_NEON) || (defined __ARM_NEON__)) && !(defined EIGEN_ARM64_USE_SVE) && \
466 !(defined EIGEN_ARM64_SME_SELECTED)
467
468#define EIGEN_VECTORIZE
469#define EIGEN_VECTORIZE_NEON
470#include <arm_neon.h>
471
472// We currently require SVE to be enabled explicitly via EIGEN_ARM64_USE_SVE and
473// will not select the backend automatically
474#elif (defined __ARM_FEATURE_SVE) && (defined EIGEN_ARM64_USE_SVE)
475
476#define EIGEN_VECTORIZE
477#define EIGEN_VECTORIZE_SVE
478#include <arm_sve.h>
479
480// Since we depend on knowing SVE vector length at compile-time, we need
481// to ensure a fixed length is set
482#if defined __ARM_FEATURE_SVE_BITS
483#define EIGEN_ARM64_SVE_VL __ARM_FEATURE_SVE_BITS
484
485// Architecture-mandated length constraints.
486static_assert((EIGEN_ARM64_SVE_VL >= 128) && (EIGEN_ARM64_SVE_VL <= 2048) &&
487 ((EIGEN_ARM64_SVE_VL & (EIGEN_ARM64_SVE_VL - 1)) == 0),
488 "SVE vector length must be 2^n for some n in [7, 11]");
489#else
490#error "Eigen requires a fixed SVE vector length but EIGEN_ARM64_SVE_VL is not set."
491#endif
492
493// TriangularMatrixMatrix.h puts a (2 * max(mr, nr))^2 panel of Scalar on the
494// stack, and mr is 3 * PacketSize, so for float -- the widest scalar this backend
495// vectorizes -- the panel is 9 * VL^2 / 64 bytes
496// -- 144 kB at VL=1024 and 576 kB at VL=2048, past the 128 kB default, and the
497// backend does not compile at those lengths without more room. Only raise Eigen's
498// default; an explicit user limit remains authoritative, including 0.
499#if defined(EIGEN_STACK_ALLOCATION_LIMIT_WAS_DEFAULTED) && \
500 EIGEN_STACK_ALLOCATION_LIMIT < (9 * EIGEN_ARM64_SVE_VL * EIGEN_ARM64_SVE_VL / 64)
501#undef EIGEN_STACK_ALLOCATION_LIMIT
502#define EIGEN_STACK_ALLOCATION_LIMIT (9 * EIGEN_ARM64_SVE_VL * EIGEN_ARM64_SVE_VL / 64)
503#endif
504
505// Selected automatically whenever the toolchain can provide it; see
506// EIGEN_ARM64_SME_SELECTED above for the conditions and the opt-out.
507#elif defined(EIGEN_ARM64_SME_SELECTED)
508
509#define EIGEN_VECTORIZE
510#define EIGEN_VECTORIZE_SME
511#include <arm_neon.h>
512#include <arm_sme.h>
513
514// Double-precision outer products (FMOPA into a ZA.D tile) need the optional
515// FEAT_SME_F64F64, which each compiler reports differently: GCC defines the ACLE
516// macro, clang defines no macro but gates the builtin on the target feature.
517// Both halves are needed -- clang otherwise accepts svmopa_za64_f64_m without the
518// feature, so a missed gate faults at run time rather than at build time.
519#if !defined(EIGEN_ARM64_NO_SME_F64F64) && \
520 (defined(__ARM_FEATURE_SME_F64F64) || EIGEN_HAS_BUILTIN(__builtin_sme_svmopa_za64_f64_m))
521#define EIGEN_VECTORIZE_SME_F64F64
522#endif
523
524#elif EIGEN_ARCH_RISCV
525
526#if defined(__riscv_zfh)
527#define EIGEN_HAS_BUILTIN_FLOAT16
528#endif
529
530// We currently require RVV to be enabled explicitly via EIGEN_RISCV64_USE_RVV and
531// will not select the backend automatically
532#if (defined EIGEN_RISCV64_USE_RVV10)
533
534#define EIGEN_VECTORIZE
535#define EIGEN_VECTORIZE_RVV10
536#include <riscv_vector.h>
537
538// Since we depend on knowing RVV vector length at compile-time, we need
539// to ensure a fixed length is set
540#if defined(__riscv_v_fixed_vlen)
541#define EIGEN_RISCV64_RVV_VL __riscv_v_fixed_vlen
542#if __riscv_v_fixed_vlen >= 256
543#undef EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT
544#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT 1
545#endif
546#else
547#error "Eigen requires a fixed RVV vector length but -mrvv-vector-bits=zvl is not set."
548#endif
549
550// Raise Eigen's own default only, as the SVE block above does: an explicit limit is a caller
551// policy on stack safety, and rewriting it defeats the policy. nomalloc, bdcsvd, jacobisvd,
552// diagonalview and diagonalmatrices set 0 to switch the check off, and clobbering that re-enables
553// alloca underneath the very tests written to catch it.
554#ifdef EIGEN_STACK_ALLOCATION_LIMIT_WAS_DEFAULTED
555#undef EIGEN_STACK_ALLOCATION_LIMIT
556#if __riscv_v_fixed_vlen <= 512
557#define EIGEN_STACK_ALLOCATION_LIMIT 196608
558#else
559#define EIGEN_STACK_ALLOCATION_LIMIT 393216
560#endif
561#endif
562
563#if defined(__riscv_zvfh) && defined(__riscv_zfh)
564#define EIGEN_VECTORIZE_RVV10FP16
565#elif defined(__riscv_zvfh)
566#if defined(__GNUC__) || defined(__clang__)
567#warning "The Eigen::Half vectorization requires Zfh and Zvfh extensions."
568#elif defined(_MSC_VER)
569#pragma message("The Eigen::Half vectorization requires Zfh and Zvfh extensions.")
570#endif
571#endif
572
573#if defined(__riscv_zvfbfwma)
574#define EIGEN_VECTORIZE_RVV10BF16
575#endif
576
577#endif // defined(EIGEN_ARCH_RISCV)
578
579// ZVector needs the vector float instructions of z14 (__ARCH__ 12); below that, s390x stays scalar.
580#elif (defined __s390x__ && defined __VEC__ && (!defined(__ARCH__) || __ARCH__ >= 12))
581
582#define EIGEN_VECTORIZE
583#define EIGEN_VECTORIZE_ZVECTOR
584#include <vecintrin.h>
585
586#elif defined __mips_msa
587
588// Limit MSA optimizations to little-endian CPUs for now.
589// TODO: Perhaps, eventually support MSA optimizations on big-endian CPUs?
590#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
591#if defined(__LP64__)
592#define EIGEN_MIPS_64
593#else
594#define EIGEN_MIPS_32
595#endif
596#define EIGEN_VECTORIZE
597#define EIGEN_VECTORIZE_MSA
598#include <msa.h>
599#endif
600
601#elif (defined __loongarch64 && defined __loongarch_sx)
602
603#define EIGEN_VECTORIZE
604#define EIGEN_VECTORIZE_LSX
605#include <lsxintrin.h>
606
607#elif defined __HVX__ && (__HVX_LENGTH__ == 128)
608
609#define EIGEN_VECTORIZE
610#define EIGEN_VECTORIZE_HVX
611#include <hexagon_types.h>
612
613#endif
614#endif
615
616// The backend blocks above are the only consumers; do not leak it into user code.
617#undef EIGEN_STACK_ALLOCATION_LIMIT_WAS_DEFAULTED
618
619// Following the Arm ACLE arm_neon.h should also include arm_fp16.h but not all
620// compilers seem to follow this. We therefore include it explicitly.
621// See also: https://bugs.llvm.org/show_bug.cgi?id=47955
622#if defined(EIGEN_HAS_ARM64_FP16_SCALAR_ARITHMETIC)
623#include <arm_fp16.h>
624#endif
625
626// Enable FMA for ARM.
627#if defined(__ARM_FEATURE_FMA)
628#define EIGEN_VECTORIZE_FMA
629#endif
630
631#if defined(__F16C__) && !defined(EIGEN_GPUCC)
632// We can use the optimized fp16 to float and float to fp16 conversion routines
633#define EIGEN_HAS_FP16_C
634
635#if EIGEN_COMP_GNUC
636// Make sure immintrin.h is included, even if e.g. vectorization is
637// explicitly disabled (see also issue #2395).
638// Note that FP16C intrinsics for gcc and clang are included by immintrin.h,
639// as opposed to emmintrin.h as suggested by Intel:
640// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#othertechs=FP16C&expand=1711
641#include <immintrin.h>
642#endif
643#endif
644
645#if defined EIGEN_CUDACC
646#define EIGEN_VECTORIZE_GPU
647#include <vector_types.h>
648#include <cuda_runtime_api.h>
649#if defined(EIGEN_HAS_CUDA_FP16)
650#include <cuda_fp16.h>
651#endif
652#endif
653
654#if defined(EIGEN_HIPCC)
655#define EIGEN_VECTORIZE_GPU
656#include <hip/hip_vector_types.h>
657#include <hip/hip_fp16.h>
658#define EIGEN_HAS_HIP_BF16
659#include <hip/hip_bfloat16.h>
660#endif
661
662#if defined(__riscv)
663// Defines the default LMUL for RISC-V
664#ifndef EIGEN_RISCV64_DEFAULT_LMUL
665#define EIGEN_RISCV64_DEFAULT_LMUL 1
666#endif
667#endif
668
670// IWYU pragma: private
671#include "../InternalHeaderCheck.h"
672
681#ifndef EIGEN_SCALAR_MADD_USE_FMA
682#ifdef EIGEN_VECTORIZE_FMA
683#define EIGEN_SCALAR_MADD_USE_FMA 1
684#else
685#define EIGEN_SCALAR_MADD_USE_FMA 0
686#endif
687#endif
688
689namespace Eigen {
690
691inline static const char* SimdInstructionSetsInUse(void) {
692#if defined(EIGEN_VECTORIZE_AVX512)
693 return "AVX512, FMA, AVX2, AVX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
694#elif defined(EIGEN_VECTORIZE_AVX)
695 return "AVX SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
696#elif defined(EIGEN_VECTORIZE_SSE4_2)
697 return "SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2";
698#elif defined(EIGEN_VECTORIZE_SSE4_1)
699 return "SSE, SSE2, SSE3, SSSE3, SSE4.1";
700#elif defined(EIGEN_VECTORIZE_SSSE3)
701 return "SSE, SSE2, SSE3, SSSE3";
702#elif defined(EIGEN_VECTORIZE_SSE3)
703 return "SSE, SSE2, SSE3";
704#elif defined(EIGEN_VECTORIZE_SSE2)
705 return "SSE, SSE2";
706#elif defined(EIGEN_VECTORIZE_ALTIVEC)
707 return "AltiVec";
708#elif defined(EIGEN_VECTORIZE_POWER8_VECTOR)
709 return "VSX, POWER8 vector";
710#elif defined(EIGEN_VECTORIZE_VSX)
711 return "VSX";
712#elif defined(EIGEN_VECTORIZE_NEON)
713 return "ARM NEON";
714#elif defined(EIGEN_VECTORIZE_SME)
715 return "ARM SME";
716#elif defined(EIGEN_VECTORIZE_SVE)
717 return "ARM SVE";
718#elif defined(EIGEN_VECTORIZE_ZVECTOR)
719 return "S390X ZVECTOR";
720#elif defined(EIGEN_VECTORIZE_MSA)
721 return "MIPS MSA";
722#elif defined(EIGEN_VECTORIZE_LSX)
723 return "LOONGARCH64 LSX";
724#elif defined(EIGEN_VECTORIZE_RVV10)
725 return "RVV";
726#else
727 return "None";
728#endif
729}
730
731} // end namespace Eigen
732
733#endif // EIGEN_CONFIGURE_VECTORIZATION_H