diff --git a/Source/astcenc_vecmathlib_avx2_8.h b/Source/astcenc_vecmathlib_avx2_8.h index 7cd34c31..17147a14 100644 --- a/Source/astcenc_vecmathlib_avx2_8.h +++ b/Source/astcenc_vecmathlib_avx2_8.h @@ -142,12 +142,13 @@ struct vint8 */ ASTCENC_SIMD_INLINE explicit vint8(const uint8_t *p) { - // _mm_loadu_si64 would be nicer syntax, but missing on older GCC and - // generates broken code on GCC 11.x before 11.3, so use this to - // generate alignment-safe and aliasing-safe alternative + // Copy through a uint32_t to avoid load through a reinterpreted + // pointer, which is both unaligned and an aliasing violation. uint64_t tmp; std::memcpy(&tmp, p, sizeof(tmp)); + // _mm_loadu_si64 would be nicer syntax, but missing on older GCC and + // generates broken code on GCC 11.x before 11.3. m = _mm256_cvtepu8_epi32(_mm_cvtsi64_si128(tmp)); } diff --git a/Source/astcenc_vecmathlib_neon_4.h b/Source/astcenc_vecmathlib_neon_4.h index 73d47dc9..9086b8b1 100644 --- a/Source/astcenc_vecmathlib_neon_4.h +++ b/Source/astcenc_vecmathlib_neon_4.h @@ -195,13 +195,17 @@ struct vint4 ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p) { #if ASTCENC_SVE == 0 - // Cast is safe - NEON loads are allowed to be unaligned - uint32x2_t t8 = vld1_dup_u32(reinterpret_cast(p)); - uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8))); - m = vreinterpretq_s32_u32(vmovl_u16(t16)); + // Copy through a uint32_t to avoid load through a reinterpreted + // pointer, which is both unaligned and an aliasing violation. + uint32_t tmp; + std::memcpy(&tmp, p, sizeof(tmp)); + + uint32x2_t t8 = vdup_n_u32(tmp); + uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8))); + m = vreinterpretq_s32_u32(vmovl_u16(t16)); #else - svint32_t data = svld1ub_s32(svptrue_pat_b32(SV_VL4), p); - m = svget_neonq(data); + svint32_t data = svld1ub_s32(svptrue_pat_b32(SV_VL4), p); + m = svget_neonq(data); #endif } diff --git a/Source/astcenc_vecmathlib_sse_4.h b/Source/astcenc_vecmathlib_sse_4.h index 823b41a9..c0eb6553 100644 --- a/Source/astcenc_vecmathlib_sse_4.h +++ b/Source/astcenc_vecmathlib_sse_4.h @@ -207,12 +207,13 @@ struct vint4 */ ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p) { - // _mm_loadu_si32 would be nicer syntax, but missing on older GCC and - // generates broken code on GCC 11.x before 11.3, so use this to - // generate alignment-safe and aliasing-safe alternative + // Copy through a uint32_t to avoid load through a reinterpreted + // pointer, which is both unaligned and an aliasing violation. int32_t tmp; std::memcpy(&tmp, p, sizeof(tmp)); + // _mm_loadu_si32 would be nicer syntax, but missing on older GCC and + // generates broken code on GCC 11.x before 11.3. __m128i t = _mm_cvtsi32_si128(tmp); #if ASTCENC_SSE >= 41