zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 1d96a17af473d5ca79ecc7b64bbf2e899b5de3b4 (tree)
parent 10c74631b381b6b7d84def90a3a747192f2793a0
Author: Frank Denis <124872+jedisct1@users.noreply.github.com>
Date:   Mon, 13 Mar 2023 08:06:27 +0100

crypto.aescrypto.encrypt: do not add the round key in an asm block (#14899)

Apple M1/M2 have an EOR3 instruction that can XOR 2 operands with
another one, and LLVM knows how to take advantage of it.

However, two EOR can't be automatically combined into an EOR3 if
one of them is in an assembly block.

That simple change speeds up ciphers doing an AES round immediately
followed by a XOR operation on Apple Silicon.

Before:

   aegis-128l mac:      12534 MiB/s
    aegis-256 mac:       6722 MiB/s
       aegis-128l:      10634 MiB/s
        aegis-256:       6133 MiB/s
       aes128-gcm:       3890 MiB/s
       aes256-gcm:       3122 MiB/s
       aes128-ocb:       2832 MiB/s
       aes256-ocb:       2057 MiB/s

After:

   aegis-128l mac:      15667 MiB/s
    aegis-256 mac:       8240 MiB/s
       aegis-128l:      12656 MiB/s
        aegis-256:       7214 MiB/s
       aes128-gcm:       3976 MiB/s
       aes256-gcm:       3202 MiB/s
       aes128-ocb:       2835 MiB/s
       aes256-ocb:       2118 MiB/s
Diffstat:
Mlib/std/crypto/aes/armcrypto.zig | 24++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/lib/std/crypto/aes/armcrypto.zig b/lib/std/crypto/aes/armcrypto.zig @@ -32,62 +32,54 @@ pub const Block = struct { /// Encrypt a block with a round key. pub inline fn encrypt(block: Block, round_key: Block) Block { return Block{ - .repr = asm ( + .repr = (asm ( \\ mov %[out].16b, %[in].16b \\ aese %[out].16b, %[zero].16b \\ aesmc %[out].16b, %[out].16b - \\ eor %[out].16b, %[out].16b, %[rk].16b : [out] "=&x" (-> BlockVec), : [in] "x" (block.repr), - [rk] "x" (round_key.repr), [zero] "x" (zero), - ), + )) ^ round_key.repr, }; } /// Encrypt a block with the last round key. pub inline fn encryptLast(block: Block, round_key: Block) Block { return Block{ - .repr = asm ( + .repr = (asm ( \\ mov %[out].16b, %[in].16b \\ aese %[out].16b, %[zero].16b - \\ eor %[out].16b, %[out].16b, %[rk].16b : [out] "=&x" (-> BlockVec), : [in] "x" (block.repr), - [rk] "x" (round_key.repr), [zero] "x" (zero), - ), + )) ^ round_key.repr, }; } /// Decrypt a block with a round key. pub inline fn decrypt(block: Block, inv_round_key: Block) Block { return Block{ - .repr = asm ( + .repr = (asm ( \\ mov %[out].16b, %[in].16b \\ aesd %[out].16b, %[zero].16b \\ aesimc %[out].16b, %[out].16b - \\ eor %[out].16b, %[out].16b, %[rk].16b : [out] "=&x" (-> BlockVec), : [in] "x" (block.repr), - [rk] "x" (inv_round_key.repr), [zero] "x" (zero), - ), + )) ^ inv_round_key.repr, }; } /// Decrypt a block with the last round key. pub inline fn decryptLast(block: Block, inv_round_key: Block) Block { return Block{ - .repr = asm ( + .repr = (asm ( \\ mov %[out].16b, %[in].16b \\ aesd %[out].16b, %[zero].16b - \\ eor %[out].16b, %[out].16b, %[rk].16b : [out] "=&x" (-> BlockVec), : [in] "x" (block.repr), - [rk] "x" (inv_round_key.repr), [zero] "x" (zero), - ), + )) ^ inv_round_key.repr, }; }