Commit e4e2a2fa authored by Evan Nemerson's avatar Evan Nemerson

sse2, avx: use void* for destinations of loadu functions

The vector types have alignment requirements, but these functions are
specifically for storing *unaligned* data.  Some compilers (such as
clang 11) have started to generate bad code for the old versions, but
switching over to void* fixes that.

This also moves the _mm_loadu_epi{8,16,32,64} functions from AVX-512
over to SSE2 (for 128-bit) and AVX (for 256-bit), effectively replacing
the simde_x_mm*_loadu_* functions which are now simply aliases for the
AVX-512 functions.

The only real issue here is that our loadu_si* function take a void*
instead of a __m128i* or __m256i*, making them more permissive.  Code
written against SIMDe will allow you to pass, for example, int8_t* data
to these functions without warning, whereas the _loadu_si* functions
will likely trigger a diagnostic.

The solution for this is for code using SIMDe to call functions like
_mm_loadu_epi8 instead of _mm_loadu_si128, even if they don't want to
use AVX-512.  On SSE2, this will simply become a cast and call to
_mm_loadu_si128 and all is good.  On other architectures we avoid
undefined behavior becous void* has no alignment requirements.

That means the only *real* problem is code which ifdefs SIMDe usage.
In C I would suggest casting to void* instead of __m128i* or __m256i*
when calling _mm_loadu_si128 or _mm_loadu_si256; everything will work
as expected.  In C++, though, that will still generate a warning…
probably the best (well, least bad at least) solution there would be
to define a macro to use instead of _mm_loadu_si128/_mm256_loadu_si256
and use an ifdef to define it differently depending on whether you're
using SIMDe or not.
parent b0f16aa3
......@@ -803,6 +803,9 @@ HEDLEY_DIAGNOSTIC_POP
# if HEDLEY_GCC_VERSION_CHECK(4,3,0) /* -Wsign-conversion */
# define SIMDE_BUG_GCC_95144
# endif
# if !HEDLEY_GCC_VERSION_CHECK(11,0,0)
# define SIMDE_BUG_GCC_95483
# endif
# endif
# if !HEDLEY_GCC_VERSION_CHECK(9,4,0) && defined(SIMDE_ARCH_AARCH64)
# define SIMDE_BUG_GCC_94488
......
......@@ -3744,60 +3744,6 @@ simde_mm256_extract_epi64 (simde__m256i a, const int index)
#define _mm256_extract_epi64(a, index) simde_mm256_extract_epi64(a, index)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_x_mm256_loadu_epi8(void const* mem_addr) {
#if defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(simde__m256i const*, mem_addr));
#else
simde__m256i_private r_;
simde_memcpy(&r_, mem_addr, sizeof(r_));
return simde__m256i_from_private(r_);
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_x_mm256_loadu_epi16(void const* mem_addr) {
#if defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(simde__m256i const*, mem_addr));
#else
simde__m256i_private r_;
simde_memcpy(&r_, mem_addr, sizeof(r_));
return simde__m256i_from_private(r_);
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_x_mm256_loadu_epi32(void const* mem_addr) {
#if defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(simde__m256i const*, mem_addr));
#else
simde__m256i_private r_;
simde_memcpy(&r_, mem_addr, sizeof(r_));
return simde__m256i_from_private(r_);
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_x_mm256_loadu_epi64(void const* mem_addr) {
#if defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(simde__m256i const*, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_lddqu_si256 (simde__m256i const * mem_addr) {
......@@ -3894,6 +3840,82 @@ simde_mm256_loadu_ps (const float a[HEDLEY_ARRAY_PARAM(8)]) {
#define _mm256_loadu_ps(a) simde_mm256_loadu_ps(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi8(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm256_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
#define simde_x_mm256_loadu_epi8(mem_addr) simde_mm256_loadu_epi8(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm256_loadu_epi8
#define _mm256_loadu_epi8(a) simde_mm256_loadu_epi8(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi16(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm256_loadu_epi16(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
#define simde_x_mm256_loadu_epi16(mem_addr) simde_mm256_loadu_epi16(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm256_loadu_epi16
#define _mm256_loadu_epi16(a) simde_mm256_loadu_epi16(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi32(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm256_loadu_epi32(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
#define simde_x_mm256_loadu_epi32(mem_addr) simde_mm256_loadu_epi32(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm256_loadu_epi32
#define _mm256_loadu_epi32(a) simde_mm256_loadu_epi32(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi64(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm256_loadu_epi64(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
#define simde_x_mm256_loadu_epi64(mem_addr) simde_mm256_loadu_epi64(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm256_loadu_epi64
#define _mm256_loadu_epi64(a) simde_mm256_loadu_epi64(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_si256 (void const * mem_addr) {
......@@ -5193,9 +5215,9 @@ simde_mm256_storeu_pd (simde_float64 mem_addr[4], simde__m256d a) {
SIMDE_FUNCTION_ATTRIBUTES
void
simde_mm256_storeu_si256 (simde__m256i* mem_addr, simde__m256i a) {
simde_mm256_storeu_si256 (void* mem_addr, simde__m256i a) {
#if defined(SIMDE_X86_AVX_NATIVE)
_mm256_storeu_si256(mem_addr, a);
_mm256_storeu_si256(SIMDE_ALIGN_CAST(__m256i*, mem_addr), a);
#else
simde_memcpy(mem_addr, &a, sizeof(a));
#endif
......
......@@ -33,118 +33,6 @@ HEDLEY_DIAGNOSTIC_PUSH
SIMDE_DISABLE_UNWANTED_DIAGNOSTICS
SIMDE_BEGIN_DECLS_
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_mm_loadu_epi8(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_mm_loadu_epi16(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_mm_loadu_epi32(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_mm_loadu_epi64(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi8(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm256_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi16(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm256_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi32(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm256_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m256i
simde_mm256_loadu_epi64(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(HEDLEY_GCC_VERSION)
return _mm256_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_AVX_NATIVE)
return _mm256_loadu_si256(SIMDE_ALIGN_CAST(__m256i const *, mem_addr));
#else
simde__m256i r;
simde_memcpy(&r, mem_addr, sizeof(r));
return r;
#endif
}
SIMDE_FUNCTION_ATTRIBUTES
simde__m512
simde_mm512_loadu_ps (void const * mem_addr) {
......
......@@ -3416,75 +3416,103 @@ simde_mm_loadu_pd (simde_float64 const mem_addr[HEDLEY_ARRAY_PARAM(2)]) {
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_x_mm_loadu_epi8(int8_t const* mem_addr) {
#if defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(simde__m128i const*, mem_addr));
simde_mm_loadu_epi8(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm_loadu_epi8(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i_private r_;
simde__m128i r;
#if defined(SIMDE_ARM_NEON_A32V7_NATIVE)
r_.neon_i8 = vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr));
#else
simde_memcpy(&r_, mem_addr, sizeof(r_));
simde_memcpy(&r, mem_addr, sizeof(r));
#endif
return simde__m128i_from_private(r_);
return r;
#endif
}
#define simde_x_mm_loadu_epi8(mem_addr) simde_mm_loadu_epi8(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm_loadu_epi8
#define _mm_loadu_epi8(a) simde_mm_loadu_epi8(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_x_mm_loadu_epi16(int16_t const* mem_addr) {
#if defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(simde__m128i const*, mem_addr));
simde_mm_loadu_epi16(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && defined(SIMDE_X86_AVX512BW_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm_loadu_epi16(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i_private r_;
simde__m128i r;
#if defined(SIMDE_ARM_NEON_A32V7_NATIVE)
r_.neon_i16 = vld1q_s16(HEDLEY_REINTERPRET_CAST(int16_t const*, mem_addr));
r_.neon_i16 = vreinterpretq_s16_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr)));
#else
simde_memcpy(&r_, mem_addr, sizeof(r_));
simde_memcpy(&r, mem_addr, sizeof(r));
#endif
return simde__m128i_from_private(r_);
return r;
#endif
}
#define simde_x_mm_loadu_epi16(mem_addr) simde_mm_loadu_epi16(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || defined(SIMDE_X86_AVX512BW_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm_loadu_epi16
#define _mm_loadu_epi16(a) simde_mm_loadu_epi16(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_x_mm_loadu_epi32(int32_t const* mem_addr) {
#if defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(simde__m128i const*, mem_addr));
simde_mm_loadu_epi32(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm_loadu_epi32(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i_private r_;
simde__m128i r;
#if defined(SIMDE_ARM_NEON_A32V7_NATIVE)
r_.neon_i32 = vld1q_s32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr));
r_.neon_i32 = vreinterpretq_s32_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr)));
#else
simde_memcpy(&r_, mem_addr, sizeof(r_));
simde_memcpy(&r, mem_addr, sizeof(r));
#endif
return simde__m128i_from_private(r_);
return r;
#endif
}
#define simde_x_mm_loadu_epi32(mem_addr) simde_mm_loadu_epi32(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm_loadu_epi32
#define _mm_loadu_epi32(a) simde_mm_loadu_epi32(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
simde_x_mm_loadu_epi64(int64_t const* mem_addr) {
#if defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(simde__m128i const*, mem_addr));
simde_mm_loadu_epi64(void const * mem_addr) {
#if defined(SIMDE_X86_AVX512VL_NATIVE) && !defined(SIMDE_BUG_GCC_95483)
return _mm_loadu_epi64(mem_addr);
#elif defined(SIMDE_X86_SSE2_NATIVE)
return _mm_loadu_si128(SIMDE_ALIGN_CAST(__m128i const *, mem_addr));
#else
simde__m128i_private r_;
simde__m128i r;
#if defined(SIMDE_ARM_NEON_A32V7_NATIVE)
r_.neon_i64 = vld1q_s64(HEDLEY_REINTERPRET_CAST(int64_t const*, mem_addr));
r_.neon_i64 = vreinterpretq_s64_s8(vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr)));
#else
simde_memcpy(&r_, mem_addr, sizeof(r_));
simde_memcpy(&r, mem_addr, sizeof(r));
#endif
return simde__m128i_from_private(r_);
return r;
#endif
}
#define simde_x_mm_loadu_epi64(mem_addr) simde_mm_loadu_epi64(mem_addr)
#if defined(SIMDE_X86_AVX512VL_ENABLE_NATIVE_ALIASES) || (defined(SIMDE_ENABLE_NATIVE_ALIASES) && defined(SIMDE_BUG_GCC_95483))
#undef _mm_loadu_epi64
#define _mm_loadu_epi64(a) simde_mm_loadu_epi64(a)
#endif
SIMDE_FUNCTION_ATTRIBUTES
simde__m128i
......@@ -3503,9 +3531,7 @@ simde_mm_loadu_si128 (void const* mem_addr) {
r_ = HEDLEY_REINTERPRET_CAST(const struct simde_mm_loadu_si128_s *, mem_addr)->v;
HEDLEY_DIAGNOSTIC_POP
#elif defined(SIMDE_ARM_NEON_A32V7_NATIVE)
/* Note that this is a lower priority than the struct above since
* clang assumes mem_addr is aligned (since it is a __m128i*). */
r_.neon_i32 = vld1q_s32(HEDLEY_REINTERPRET_CAST(int32_t const*, mem_addr));
r_.neon_i8 = vld1q_s8(HEDLEY_REINTERPRET_CAST(int8_t const*, mem_addr));
#else
simde_memcpy(&r_, mem_addr, sizeof(r_));
#endif
......@@ -6190,7 +6216,7 @@ simde_mm_storeu_pd (simde_float64* mem_addr, simde__m128d a) {
SIMDE_FUNCTION_ATTRIBUTES
void
simde_mm_storeu_si128 (simde__m128i* mem_addr, simde__m128i a) {
simde_mm_storeu_si128 (void* mem_addr, simde__m128i a) {
#if defined(SIMDE_X86_SSE2_NATIVE)
_mm_storeu_si128(HEDLEY_STATIC_CAST(__m128i*, mem_addr), a);
#else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment