From 6af2c2c67a54fa2afec5daefdcc07b599d96c62b Mon Sep 17 00:00:00 2001 From: Benoit Jacob Date: Mon, 21 Sep 2009 05:39:55 -0400 Subject: [PATCH] backported the following to 2.0: * EIGEN_ALIGN and EIGEN_DONT_ALIGN and the corresponding logic in Macros.h (instead of using EIGEN_ARCH_WANTS_ALIGNMENT) * The body of ei_aligned_malloc and ei_aligned_free The reason for this backporting is that a user complained that with eigen 2.0 he got a warning at Memory.h:81 that the return value of posix_memalign was not used, and that function was declared with an attribute warn_unused_result. Looking at this, it seemed that the body of this function was already overly complicated, and fixing this warning made it even worse, while the devel branch had a much simpler body and didn't suffer from that problem. Then it was necessary to update ei_aligned_free too, and to backport EIGEN_ALIGN. Inch' Allah.... --- Eigen/src/Core/util/Macros.h | 40 ++++++++++++++++++++++++++---------- Eigen/src/Core/util/Memory.h | 39 +++++++++++++++-------------------- doc/UnalignedArrayAssert.dox | 6 +++++- 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index cec0a8d8e..caf0d8de4 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -36,24 +36,42 @@ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ EIGEN_MINOR_VERSION>=z)))) -// if the compiler is GNUC, disable 16 byte alignment on exotic archs that probably don't need it, and on which -// it may be extra trouble to get aligned memory allocation to work (example: on ARM, overloading new[] is a PITA -// because extra memory must be allocated for bookkeeping). -// if the compiler is not GNUC, just cross fingers that the architecture isn't too exotic, because we don't want -// to keep track of all the different preprocessor symbols for all compilers. -#if !defined(__GNUC__) || defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ia64__) +// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all +// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems +// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems. +#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ia64__)) +#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1 +#else +#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0 +#endif + +#if defined(__GNUC__) && (__GNUC__ <= 3) +#define EIGEN_GCC3_OR_OLDER 1 +#else +#define EIGEN_GCC3_OR_OLDER 0 +#endif + +// FIXME vectorization + alignment is completely disabled with sun studio +#if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT && !EIGEN_GCC3_OR_OLDER && !defined(__SUNPRO_CC) #define EIGEN_ARCH_WANTS_ALIGNMENT 1 #else - #ifdef EIGEN_VECTORIZE - #error Vectorization enabled, but the architecture is not listed among those for which we require 16 byte alignment. If you added vectorization for another architecture, you also need to edit this list. - #endif #define EIGEN_ARCH_WANTS_ALIGNMENT 0 +#endif + +// EIGEN_ALIGN is the true test whether we want to align or not. It takes into account both the user choice to explicitly disable +// alignment (EIGEN_DONT_ALIGN) and the architecture config (EIGEN_ARCH_WANTS_ALIGNMENT). Henceforth, only EIGEN_ALIGN should be used. +#if EIGEN_ARCH_WANTS_ALIGNMENT && !defined(EIGEN_DONT_ALIGN) + #define EIGEN_ALIGN 1 +#else + #define EIGEN_ALIGN 0 + #ifdef EIGEN_VECTORIZE + #error "Vectorization enabled, but our platform checks say that we don't do 16 byte alignment on this platform. If you added vectorization for another architecture, you also need to edit this platform check." + #endif #ifndef EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT #endif #endif - #ifdef EIGEN_DEFAULT_TO_ROW_MAJOR #define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION RowMajor #else @@ -165,7 +183,7 @@ using Eigen::ei_cos; * If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link * vectorized and non-vectorized code. */ -#if !EIGEN_ARCH_WANTS_ALIGNMENT +#if !EIGEN_ALIGN #define EIGEN_ALIGN_128 #elif (defined __GNUC__) #define EIGEN_ALIGN_128 __attribute__((aligned(16))) diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index d301fb40c..09ad39d5b 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -73,30 +73,23 @@ inline void* ei_aligned_malloc(size_t size) ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)"); #endif - void *result; - #if EIGEN_HAS_POSIX_MEMALIGN && EIGEN_ARCH_WANTS_ALIGNMENT && !EIGEN_MALLOC_ALREADY_ALIGNED - #ifdef EIGEN_EXCEPTIONS - const int failed = - #endif - posix_memalign(&result, 16, size); + void *result; + #if !EIGEN_ALIGN + result = malloc(size); + #elif EIGEN_MALLOC_ALREADY_ALIGNED + result = malloc(size); + #elif EIGEN_HAS_POSIX_MEMALIGN + if(posix_memalign(&result, 16, size)) result = 0; + #elif EIGEN_HAS_MM_MALLOC + result = _mm_malloc(size, 16); + #elif (defined _MSC_VER) + result = _aligned_malloc(size, 16); #else - #if !EIGEN_ARCH_WANTS_ALIGNMENT - result = malloc(size); - #elif EIGEN_MALLOC_ALREADY_ALIGNED - result = malloc(size); - #elif EIGEN_HAS_MM_MALLOC - result = _mm_malloc(size, 16); - #elif (defined _MSC_VER) - result = _aligned_malloc(size, 16); - #else - result = ei_handmade_aligned_malloc(size); - #endif - #ifdef EIGEN_EXCEPTIONS - const int failed = (result == 0); - #endif + result = ei_handmade_aligned_malloc(size); #endif + #ifdef EIGEN_EXCEPTIONS - if(failed) + if(result == 0) throw std::bad_alloc(); #endif return result; @@ -143,7 +136,7 @@ template inline T* ei_conditional_aligned_new(size_t siz */ inline void ei_aligned_free(void *ptr) { - #if !EIGEN_ARCH_WANTS_ALIGNMENT + #if !EIGEN_ALIGN free(ptr); #elif EIGEN_MALLOC_ALREADY_ALIGNED free(ptr); @@ -237,7 +230,7 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset) ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0) -#if EIGEN_ARCH_WANTS_ALIGNMENT +#if EIGEN_ALIGN #ifdef EIGEN_EXCEPTIONS #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ void* operator new(size_t size, const std::nothrow_t&) throw() { \ diff --git a/doc/UnalignedArrayAssert.dox b/doc/UnalignedArrayAssert.dox index 1d207b712..19418f5d5 100644 --- a/doc/UnalignedArrayAssert.dox +++ b/doc/UnalignedArrayAssert.dox @@ -104,7 +104,11 @@ However there are a few corner cases where these alignment settings get overridd \section getrid I don't care about vectorization, how do I get rid of that stuff? -Define both preprocessor symbols EIGEN_DONT_VECTORIZE and EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT. +Two possibilities: + For more information, see this FAQ.