Avoid unaligned reads, even on x86_64 where they are safe

This commit is contained in:
Frank Denis
2026-04-08 12:03:28 +02:00
parent 4a6a7a010d
commit 11cd77c5cd
2 changed files with 72 additions and 72 deletions
@@ -172,14 +172,14 @@ while (bytes >= 64) {
diag1 = _mm_shuffle_epi32(diag1, 0x39); \
diag2 = _mm_shuffle_epi32(diag2, 0x39); \
diag3 = _mm_shuffle_epi32(diag3, 0x39); \
in##A ^= *(const uint32_t *) (m + (A * 4)); \
in##B ^= *(const uint32_t *) (m + (B * 4)); \
in##C ^= *(const uint32_t *) (m + (C * 4)); \
in##D ^= *(const uint32_t *) (m + (D * 4)); \
*(uint32_t *) (c + (A * 4)) = in##A; \
*(uint32_t *) (c + (B * 4)) = in##B; \
*(uint32_t *) (c + (C * 4)) = in##C; \
*(uint32_t *) (c + (D * 4)) = in##D; \
in##A ^= LOAD32_LE(m + (A * 4)); \
in##B ^= LOAD32_LE(m + (B * 4)); \
in##C ^= LOAD32_LE(m + (C * 4)); \
in##D ^= LOAD32_LE(m + (D * 4)); \
STORE32_LE(c + (A * 4), in##A); \
STORE32_LE(c + (B * 4), in##B); \
STORE32_LE(c + (C * 4), in##C); \
STORE32_LE(c + (D * 4), in##D); \
} while (0)
#define ONEQUAD(A, B, C, D) ONEQUAD_SHUFFLE(A, B, C, D)
@@ -374,15 +374,15 @@ if (bytes >= 256) {
z##C = _mm_shuffle_epi32(z##C, 0x39); \
z##D = _mm_shuffle_epi32(z##D, 0x39); \
\
in##A ^= *(uint32_t *) (m + 0); \
in##B ^= *(uint32_t *) (m + 4); \
in##C ^= *(uint32_t *) (m + 8); \
in##D ^= *(uint32_t *) (m + 12); \
in##A ^= LOAD32_LE(m + 0); \
in##B ^= LOAD32_LE(m + 4); \
in##C ^= LOAD32_LE(m + 8); \
in##D ^= LOAD32_LE(m + 12); \
\
*(uint32_t *) (c + 0) = in##A; \
*(uint32_t *) (c + 4) = in##B; \
*(uint32_t *) (c + 8) = in##C; \
*(uint32_t *) (c + 12) = in##D; \
STORE32_LE(c + 0, in##A); \
STORE32_LE(c + 4, in##B); \
STORE32_LE(c + 8, in##C); \
STORE32_LE(c + 12, in##D); \
\
in##A = _mm_cvtsi128_si32(z##A); \
in##B = _mm_cvtsi128_si32(z##B); \
@@ -393,14 +393,14 @@ if (bytes >= 256) {
z##C = _mm_shuffle_epi32(z##C, 0x39); \
z##D = _mm_shuffle_epi32(z##D, 0x39); \
\
in##A ^= *(uint32_t *) (m + 64); \
in##B ^= *(uint32_t *) (m + 68); \
in##C ^= *(uint32_t *) (m + 72); \
in##D ^= *(uint32_t *) (m + 76); \
*(uint32_t *) (c + 64) = in##A; \
*(uint32_t *) (c + 68) = in##B; \
*(uint32_t *) (c + 72) = in##C; \
*(uint32_t *) (c + 76) = in##D; \
in##A ^= LOAD32_LE(m + 64); \
in##B ^= LOAD32_LE(m + 68); \
in##C ^= LOAD32_LE(m + 72); \
in##D ^= LOAD32_LE(m + 76); \
STORE32_LE(c + 64, in##A); \
STORE32_LE(c + 68, in##B); \
STORE32_LE(c + 72, in##C); \
STORE32_LE(c + 76, in##D); \
\
in##A = _mm_cvtsi128_si32(z##A); \
in##B = _mm_cvtsi128_si32(z##B); \
@@ -411,28 +411,28 @@ if (bytes >= 256) {
z##C = _mm_shuffle_epi32(z##C, 0x39); \
z##D = _mm_shuffle_epi32(z##D, 0x39); \
\
in##A ^= *(uint32_t *) (m + 128); \
in##B ^= *(uint32_t *) (m + 132); \
in##C ^= *(uint32_t *) (m + 136); \
in##D ^= *(uint32_t *) (m + 140); \
*(uint32_t *) (c + 128) = in##A; \
*(uint32_t *) (c + 132) = in##B; \
*(uint32_t *) (c + 136) = in##C; \
*(uint32_t *) (c + 140) = in##D; \
in##A ^= LOAD32_LE(m + 128); \
in##B ^= LOAD32_LE(m + 132); \
in##C ^= LOAD32_LE(m + 136); \
in##D ^= LOAD32_LE(m + 140); \
STORE32_LE(c + 128, in##A); \
STORE32_LE(c + 132, in##B); \
STORE32_LE(c + 136, in##C); \
STORE32_LE(c + 140, in##D); \
\
in##A = _mm_cvtsi128_si32(z##A); \
in##B = _mm_cvtsi128_si32(z##B); \
in##C = _mm_cvtsi128_si32(z##C); \
in##D = _mm_cvtsi128_si32(z##D); \
\
in##A ^= *(uint32_t *) (m + 192); \
in##B ^= *(uint32_t *) (m + 196); \
in##C ^= *(uint32_t *) (m + 200); \
in##D ^= *(uint32_t *) (m + 204); \
*(uint32_t *) (c + 192) = in##A; \
*(uint32_t *) (c + 196) = in##B; \
*(uint32_t *) (c + 200) = in##C; \
*(uint32_t *) (c + 204) = in##D
in##A ^= LOAD32_LE(m + 192); \
in##B ^= LOAD32_LE(m + 196); \
in##C ^= LOAD32_LE(m + 200); \
in##D ^= LOAD32_LE(m + 204); \
STORE32_LE(c + 192, in##A); \
STORE32_LE(c + 196, in##B); \
STORE32_LE(c + 200, in##C); \
STORE32_LE(c + 204, in##D)
/* store data ; this macro replaces shuffle+mov by a direct extract; not much
* difference */
@@ -445,56 +445,56 @@ if (bytes >= 256) {
in##B = _mm_cvtsi128_si32(z##B); \
in##C = _mm_cvtsi128_si32(z##C); \
in##D = _mm_cvtsi128_si32(z##D); \
in##A ^= *(uint32_t *) (m + 0); \
in##B ^= *(uint32_t *) (m + 4); \
in##C ^= *(uint32_t *) (m + 8); \
in##D ^= *(uint32_t *) (m + 12); \
*(uint32_t *) (c + 0) = in##A; \
*(uint32_t *) (c + 4) = in##B; \
*(uint32_t *) (c + 8) = in##C; \
*(uint32_t *) (c + 12) = in##D; \
in##A ^= LOAD32_LE(m + 0); \
in##B ^= LOAD32_LE(m + 4); \
in##C ^= LOAD32_LE(m + 8); \
in##D ^= LOAD32_LE(m + 12); \
STORE32_LE(c + 0, in##A); \
STORE32_LE(c + 4, in##B); \
STORE32_LE(c + 8, in##C); \
STORE32_LE(c + 12, in##D); \
\
in##A = _mm_extract_epi32(z##A, 1); \
in##B = _mm_extract_epi32(z##B, 1); \
in##C = _mm_extract_epi32(z##C, 1); \
in##D = _mm_extract_epi32(z##D, 1); \
\
in##A ^= *(uint32_t *) (m + 64); \
in##B ^= *(uint32_t *) (m + 68); \
in##C ^= *(uint32_t *) (m + 72); \
in##D ^= *(uint32_t *) (m + 76); \
*(uint32_t *) (c + 64) = in##A; \
*(uint32_t *) (c + 68) = in##B; \
*(uint32_t *) (c + 72) = in##C; \
*(uint32_t *) (c + 76) = in##D; \
in##A ^= LOAD32_LE(m + 64); \
in##B ^= LOAD32_LE(m + 68); \
in##C ^= LOAD32_LE(m + 72); \
in##D ^= LOAD32_LE(m + 76); \
STORE32_LE(c + 64, in##A); \
STORE32_LE(c + 68, in##B); \
STORE32_LE(c + 72, in##C); \
STORE32_LE(c + 76, in##D); \
\
in##A = _mm_extract_epi32(z##A, 2); \
in##B = _mm_extract_epi32(z##B, 2); \
in##C = _mm_extract_epi32(z##C, 2); \
in##D = _mm_extract_epi32(z##D, 2); \
\
in##A ^= *(uint32_t *) (m + 128); \
in##B ^= *(uint32_t *) (m + 132); \
in##C ^= *(uint32_t *) (m + 136); \
in##D ^= *(uint32_t *) (m + 140); \
*(uint32_t *) (c + 128) = in##A; \
*(uint32_t *) (c + 132) = in##B; \
*(uint32_t *) (c + 136) = in##C; \
*(uint32_t *) (c + 140) = in##D; \
in##A ^= LOAD32_LE(m + 128); \
in##B ^= LOAD32_LE(m + 132); \
in##C ^= LOAD32_LE(m + 136); \
in##D ^= LOAD32_LE(m + 140); \
STORE32_LE(c + 128, in##A); \
STORE32_LE(c + 132, in##B); \
STORE32_LE(c + 136, in##C); \
STORE32_LE(c + 140, in##D); \
\
in##A = _mm_extract_epi32(z##A, 3); \
in##B = _mm_extract_epi32(z##B, 3); \
in##C = _mm_extract_epi32(z##C, 3); \
in##D = _mm_extract_epi32(z##D, 3); \
\
in##A ^= *(uint32_t *) (m + 192); \
in##B ^= *(uint32_t *) (m + 196); \
in##C ^= *(uint32_t *) (m + 200); \
in##D ^= *(uint32_t *) (m + 204); \
*(uint32_t *) (c + 192) = in##A; \
*(uint32_t *) (c + 196) = in##B; \
*(uint32_t *) (c + 200) = in##C; \
*(uint32_t *) (c + 204) = in##D
in##A ^= LOAD32_LE(m + 192); \
in##B ^= LOAD32_LE(m + 196); \
in##C ^= LOAD32_LE(m + 200); \
in##D ^= LOAD32_LE(m + 204); \
STORE32_LE(c + 192, in##A); \
STORE32_LE(c + 196, in##B); \
STORE32_LE(c + 200, in##C); \
STORE32_LE(c + 204, in##D)
/* store data ; this macro first transpose data in-registers, and then store
* them in memory. much faster with icc. */