miden-crypto/arch/arm64-sve/rpo/library.c
arch/arm64-sve/rpo/library.cRaw
1#include <stddef.h>
2#include <arm_sve.h>
3#include "library.h"
4#include "rpo_hash_128bit.h"
5#include "rpo_hash_256bit.h"
6
7// The STATE_WIDTH of RPO hash is 12x u64 elements.
8// The current generation of SVE-enabled processors - Neoverse V1
9// (e.g. AWS Graviton3) have 256-bit vector registers (4x u64)
10// This allows us to split the state into 3 vectors of 4 elements
11// and process all 3 independent of each other.
12
13// We see the biggest performance gains by leveraging both
14// vector and scalar operations on parts of the state array.
15// Due to high latency of vector operations, the processor is able
16// to reorder and pipeline scalar instructions while we wait for
17// vector results. This effectively gives us some 'free' scalar
18// operations and masks vector latency.
19//
20// This also means that we can fully saturate all four arithmetic
21// units of the processor (2x scalar, 2x SIMD)
22//
23// THIS ANALYSIS NEEDS TO BE PERFORMED AGAIN ONCE PROCESSORS
24// GAIN WIDER REGISTERS. It's quite possible that with 8x u64
25// vectors processing 2 partially filled vectors might
26// be easier and faster than dealing with scalar operations
27// on the remainder of the array.
28//
29// FOR NOW THIS IS ONLY ENABLED ON 4x u64 VECTORS! It falls back
30// to the regular, already highly-optimized scalar version
31// if the conditions are not met.
32
33bool add_constants_and_apply_sbox(uint64_t state[STATE_WIDTH], uint64_t constants[STATE_WIDTH]) {
34 const uint64_t vl = svcntd(); // number of u64 numbers in one SVE vector
35
36 if (vl == 2) {
37 return add_constants_and_apply_sbox_128(state, constants);
38 } else if (vl == 4) {
39 return add_constants_and_apply_sbox_256(state, constants);
40 } else {
41 return false;
42 }
43}
44
45bool add_constants_and_apply_inv_sbox(uint64_t state[STATE_WIDTH], uint64_t constants[STATE_WIDTH]) {
46 const uint64_t vl = svcntd(); // number of u64 numbers in one SVE vector
47
48 if (vl == 2) {
49 return add_constants_and_apply_inv_sbox_128(state, constants);
50 } else if (vl == 4) {
51 return add_constants_and_apply_inv_sbox_256(state, constants);
52 } else {
53 return false;
54 }
55}