From 8466abb2804a0760cee01445c80b840091c5c2e6 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 21 May 2025 23:04:26 +0200 Subject: [PATCH] Reorder arguments to vaeseq_u8 to improve AArch64 performance The register arguments to the AESE instruction are commutative, however the first input register is constrained in that it also names the output register. The constraint on register allocation causes recent LLVM versions to emit a lot of MOV instructions, significantly impacting performance. Swapping the register operands allows the compiler to emit significantly fewer MOV instructions. This change improves performance on Arm infrastructure micro-architectures by 14-36% depending on the micro-architecture Found and reported by George Steed from ARM. Thanks! --- src/libsodium/crypto_aead/aegis128l/aegis128l_armcrypto.c | 2 +- src/libsodium/crypto_aead/aegis256/aegis256_armcrypto.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsodium/crypto_aead/aegis128l/aegis128l_armcrypto.c b/src/libsodium/crypto_aead/aegis128l/aegis128l_armcrypto.c index a01f60cb..1fceb26d 100644 --- a/src/libsodium/crypto_aead/aegis128l/aegis128l_armcrypto.c +++ b/src/libsodium/crypto_aead/aegis128l/aegis128l_armcrypto.c @@ -40,7 +40,7 @@ typedef uint8x16_t aes_block_t; #define AES_BLOCK_LOAD(A) vld1q_u8(A) #define AES_BLOCK_LOAD_64x2(A, B) vreinterpretq_u8_u64(vsetq_lane_u64((A), vmovq_n_u64(B), 1)) #define AES_BLOCK_STORE(A, B) vst1q_u8((A), (B)) -#define AES_ENC(A, B) veorq_u8(vaesmcq_u8(vaeseq_u8((A), vmovq_n_u8(0))), (B)) +#define AES_ENC(A, B) veorq_u8(vaesmcq_u8(vaeseq_u8(vmovq_n_u8(0), (A))), (B)) static inline void aegis128l_update(aes_block_t *const state, const aes_block_t d1, const aes_block_t d2) diff --git a/src/libsodium/crypto_aead/aegis256/aegis256_armcrypto.c b/src/libsodium/crypto_aead/aegis256/aegis256_armcrypto.c index 058e2072..ab365d46 100644 --- a/src/libsodium/crypto_aead/aegis256/aegis256_armcrypto.c +++ b/src/libsodium/crypto_aead/aegis256/aegis256_armcrypto.c @@ -40,7 +40,7 @@ typedef uint8x16_t aes_block_t; #define AES_BLOCK_LOAD(A) vld1q_u8(A) #define AES_BLOCK_LOAD_64x2(A, B) vreinterpretq_u8_u64(vsetq_lane_u64((A), vmovq_n_u64(B), 1)) #define AES_BLOCK_STORE(A, B) vst1q_u8((A), (B)) -#define AES_ENC(A, B) veorq_u8(vaesmcq_u8(vaeseq_u8((A), vmovq_n_u8(0))), (B)) +#define AES_ENC(A, B) veorq_u8(vaesmcq_u8(vaeseq_u8(vmovq_n_u8(0), (A))), (B)) static inline void aegis256_update(aes_block_t *const state, const aes_block_t d)