authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-03-13 08:06:27+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-13 07:06:27+00:00
log1d96a17af473d5ca79ecc7b64bbf2e899b5de3b4
treead2e8a32bebcd5a27eca3262028f2c4e62a8b339
parent10c74631b381b6b7d84def90a3a747192f2793a0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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

1 files changed, 8 insertions(+), 16 deletions(-)

lib/std/crypto/aes/armcrypto.zig+8-16
...@@ -32,62 +32,54 @@ pub const Block = struct {...@@ -32,62 +32,54 @@ pub const Block = struct {
32 /// Encrypt a block with a round key.32 /// Encrypt a block with a round key.
33 pub inline fn encrypt(block: Block, round_key: Block) Block {33 pub inline fn encrypt(block: Block, round_key: Block) Block {
34 return Block{34 return Block{
35 .repr = asm (35 .repr = (asm (
36 \\ mov %[out].16b, %[in].16b36 \\ mov %[out].16b, %[in].16b
37 \\ aese %[out].16b, %[zero].16b37 \\ aese %[out].16b, %[zero].16b
38 \\ aesmc %[out].16b, %[out].16b38 \\ aesmc %[out].16b, %[out].16b
39 \\ eor %[out].16b, %[out].16b, %[rk].16b
40 : [out] "=&x" (-> BlockVec),39 : [out] "=&x" (-> BlockVec),
41 : [in] "x" (block.repr),40 : [in] "x" (block.repr),
42 [rk] "x" (round_key.repr),
43 [zero] "x" (zero),41 [zero] "x" (zero),
44 ),42 )) ^ round_key.repr,
45 };43 };
46 }44 }
4745
48 /// Encrypt a block with the last round key.46 /// Encrypt a block with the last round key.
49 pub inline fn encryptLast(block: Block, round_key: Block) Block {47 pub inline fn encryptLast(block: Block, round_key: Block) Block {
50 return Block{48 return Block{
51 .repr = asm (49 .repr = (asm (
52 \\ mov %[out].16b, %[in].16b50 \\ mov %[out].16b, %[in].16b
53 \\ aese %[out].16b, %[zero].16b51 \\ aese %[out].16b, %[zero].16b
54 \\ eor %[out].16b, %[out].16b, %[rk].16b
55 : [out] "=&x" (-> BlockVec),52 : [out] "=&x" (-> BlockVec),
56 : [in] "x" (block.repr),53 : [in] "x" (block.repr),
57 [rk] "x" (round_key.repr),
58 [zero] "x" (zero),54 [zero] "x" (zero),
59 ),55 )) ^ round_key.repr,
60 };56 };
61 }57 }
6258
63 /// Decrypt a block with a round key.59 /// Decrypt a block with a round key.
64 pub inline fn decrypt(block: Block, inv_round_key: Block) Block {60 pub inline fn decrypt(block: Block, inv_round_key: Block) Block {
65 return Block{61 return Block{
66 .repr = asm (62 .repr = (asm (
67 \\ mov %[out].16b, %[in].16b63 \\ mov %[out].16b, %[in].16b
68 \\ aesd %[out].16b, %[zero].16b64 \\ aesd %[out].16b, %[zero].16b
69 \\ aesimc %[out].16b, %[out].16b65 \\ aesimc %[out].16b, %[out].16b
70 \\ eor %[out].16b, %[out].16b, %[rk].16b
71 : [out] "=&x" (-> BlockVec),66 : [out] "=&x" (-> BlockVec),
72 : [in] "x" (block.repr),67 : [in] "x" (block.repr),
73 [rk] "x" (inv_round_key.repr),
74 [zero] "x" (zero),68 [zero] "x" (zero),
75 ),69 )) ^ inv_round_key.repr,
76 };70 };
77 }71 }
7872
79 /// Decrypt a block with the last round key.73 /// Decrypt a block with the last round key.
80 pub inline fn decryptLast(block: Block, inv_round_key: Block) Block {74 pub inline fn decryptLast(block: Block, inv_round_key: Block) Block {
81 return Block{75 return Block{
82 .repr = asm (76 .repr = (asm (
83 \\ mov %[out].16b, %[in].16b77 \\ mov %[out].16b, %[in].16b
84 \\ aesd %[out].16b, %[zero].16b78 \\ aesd %[out].16b, %[zero].16b
85 \\ eor %[out].16b, %[out].16b, %[rk].16b
86 : [out] "=&x" (-> BlockVec),79 : [out] "=&x" (-> BlockVec),
87 : [in] "x" (block.repr),80 : [in] "x" (block.repr),
88 [rk] "x" (inv_round_key.repr),
89 [zero] "x" (zero),81 [zero] "x" (zero),
90 ),82 )) ^ inv_round_key.repr,
91 };83 };
92 }84 }
9385