arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
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}