GS: AArch64 has no slow unaligned load to compile around

FAST_UNALIGNED was defined only inside the ARCH_X86 arm, where it records
that AVX-and-later cores stopped punishing unaligned vector loads. On ARM64
the macro was therefore undefined, which the preprocessor reads as zero, so
every arm64 build compiled the texture-upload path as though the punishment
existed.

It never did. LDR Q and LD1 take any address, and GSVector4i's load template
ignores its own `aligned` parameter and emits the same instruction either
way. So the callers were paying for a distinction with no machine behind it:
WriteImage tests the source address and the pitch on every call to choose
between three template instantiations of WriteImageBlock and
WriteImageColumn that, for 8- and 4-bit columns, compile to identical code.
For 32- and 16-bit columns the unaligned arm is not identical, but it is the
worse one — eight combining 64-bit loads instead of four 128-bit loads and a
swizzle.

Defining it collapses all of that. GSLocalMemoryMultiISA.cpp.o goes from
80,368 to 62,184 bytes of .text and from 58 emitted functions to 32, which
is what an I-cache on a handheld cares about. Only GSBlock.h and
GSLocalMemoryMultiISA.cpp read the macro, so nothing else moves.

The retained load strategy is not new code: whenever an upload happened to
land 32-byte aligned, arm64 already ran exactly this sequence. What goes
away is the arm that only ever ran when it did not.
This commit is contained in:
Brian Degenhardt
2026-08-14 21:25:14 -07:00
parent 6aa2fd79d9
commit a3bf73bf7a
+10
View File
@@ -38,6 +38,16 @@
#include <immintrin.h>
#elif defined(ARCH_ARM64)
// AArch64 has no aligned/unaligned load distinction to begin with: LDR Q and LD1
// take any address, and GSVector4i::load<aligned> ignores its own parameter and
// emits the same instruction either way. Leaving this undefined made the callers
// pay for a distinction that does not exist — a runtime address-and-pitch test
// per texture upload, dispatching into three template instantiations that
// compile to identical code, and for 32/16-bit columns a worse load strategy
// (eight combining 64-bit loads instead of four 128-bit loads and a swizzle).
#define FAST_UNALIGNED 1
#include <arm_neon.h>
#endif