Skip to content

Commit 6d99597

Browse files
Avoid unaligned aliasing load in NEON vint4 byte constructor (#652)
--------- Co-authored-by: Peter Harris <peter.harris@arm.com>
1 parent f863361 commit 6d99597

3 files changed

Lines changed: 18 additions & 12 deletions

File tree

Source/astcenc_vecmathlib_avx2_8.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ struct vint8
142142
*/
143143
ASTCENC_SIMD_INLINE explicit vint8(const uint8_t *p)
144144
{
145-
// _mm_loadu_si64 would be nicer syntax, but missing on older GCC and
146-
// generates broken code on GCC 11.x before 11.3, so use this to
147-
// generate alignment-safe and aliasing-safe alternative
145+
// Copy through a uint32_t to avoid load through a reinterpreted
146+
// pointer, which is both unaligned and an aliasing violation.
148147
uint64_t tmp;
149148
std::memcpy(&tmp, p, sizeof(tmp));
150149

150+
// _mm_loadu_si64 would be nicer syntax, but missing on older GCC and
151+
// generates broken code on GCC 11.x before 11.3.
151152
m = _mm256_cvtepu8_epi32(_mm_cvtsi64_si128(tmp));
152153
}
153154

Source/astcenc_vecmathlib_neon_4.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,17 @@ struct vint4
195195
ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p)
196196
{
197197
#if ASTCENC_SVE == 0
198-
// Cast is safe - NEON loads are allowed to be unaligned
199-
uint32x2_t t8 = vld1_dup_u32(reinterpret_cast<const uint32_t*>(p));
200-
uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8)));
201-
m = vreinterpretq_s32_u32(vmovl_u16(t16));
198+
// Copy through a uint32_t to avoid load through a reinterpreted
199+
// pointer, which is both unaligned and an aliasing violation.
200+
uint32_t tmp;
201+
std::memcpy(&tmp, p, sizeof(tmp));
202+
203+
uint32x2_t t8 = vdup_n_u32(tmp);
204+
uint16x4_t t16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(t8)));
205+
m = vreinterpretq_s32_u32(vmovl_u16(t16));
202206
#else
203-
svint32_t data = svld1ub_s32(svptrue_pat_b32(SV_VL4), p);
204-
m = svget_neonq(data);
207+
svint32_t data = svld1ub_s32(svptrue_pat_b32(SV_VL4), p);
208+
m = svget_neonq(data);
205209
#endif
206210
}
207211

Source/astcenc_vecmathlib_sse_4.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,13 @@ struct vint4
207207
*/
208208
ASTCENC_SIMD_INLINE explicit vint4(const uint8_t *p)
209209
{
210-
// _mm_loadu_si32 would be nicer syntax, but missing on older GCC and
211-
// generates broken code on GCC 11.x before 11.3, so use this to
212-
// generate alignment-safe and aliasing-safe alternative
210+
// Copy through a uint32_t to avoid load through a reinterpreted
211+
// pointer, which is both unaligned and an aliasing violation.
213212
int32_t tmp;
214213
std::memcpy(&tmp, p, sizeof(tmp));
215214

215+
// _mm_loadu_si32 would be nicer syntax, but missing on older GCC and
216+
// generates broken code on GCC 11.x before 11.3.
216217
__m128i t = _mm_cvtsi32_si128(tmp);
217218

218219
#if ASTCENC_SSE >= 41

0 commit comments

Comments
 (0)