Message ID | 20191007164610.6881-25-ard.biesheuvel@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | crypto: crypto API library interfaces for WireGuard | expand |
Hi Ard, On Mon, Oct 7, 2019 at 6:46 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > Arnd reports that the 32-bit generic library code for Curve25119 ends > up using an excessive amount of stack space when built with Clang: > > lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size > of 1384 bytes in function 'curve25519_generic' > [-Werror,-Wframe-larger-than=] > > Let's give some hints to the compiler regarding which routines should > not be inlined, to prevent it from running out of registers and spilling > to the stack. The resulting code performs identically under both GCC > and Clang, and makes the warning go away. Are you *sure* about that? Couldn't we fix clang instead? I'd rather fixes go there instead of gimping this. The reason is that I noticed before that this code, performance-wise, was very inlining sensitive. Can you benchmark this on ARM32-noneon and on MIPS32? If there's a performance difference there, then maybe you can defer this part of the series until after the rest lands, and then we'll discuss at length various strategies? Alternatively, if you benchmark those and it also makes no difference, then it indeed makes no difference. Jason
On Mon, 14 Oct 2019 at 16:14, Jason A. Donenfeld <Jason@zx2c4.com> wrote: > > Hi Ard, > > On Mon, Oct 7, 2019 at 6:46 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > > Arnd reports that the 32-bit generic library code for Curve25119 ends > > up using an excessive amount of stack space when built with Clang: > > > > lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size > > of 1384 bytes in function 'curve25519_generic' > > [-Werror,-Wframe-larger-than=] > > > > Let's give some hints to the compiler regarding which routines should > > not be inlined, to prevent it from running out of registers and spilling > > to the stack. The resulting code performs identically under both GCC > > and Clang, and makes the warning go away. > > Are you *sure* about that? Couldn't we fix clang instead? I'd rather > fixes go there instead of gimping this. The reason is that I noticed > before that this code, performance-wise, was very inlining sensitive. > Can you benchmark this on ARM32-noneon and on MIPS32? If there's a > performance difference there, then maybe you can defer this part of > the series until after the rest lands, and then we'll discuss at > length various strategies? Alternatively, if you benchmark those and > it also makes no difference, then it indeed makes no difference. > I tested this using a 32-bit ARM VM running under an 64-bit KVM hypervisor, doing 100 iterations of the selftest.
diff --git a/lib/crypto/curve25519-fiat32.c b/lib/crypto/curve25519-fiat32.c index 1c455207341d..2fde0ec33dbd 100644 --- a/lib/crypto/curve25519-fiat32.c +++ b/lib/crypto/curve25519-fiat32.c @@ -223,7 +223,7 @@ static __always_inline void fe_1(fe *h) h->v[0] = 1; } -static void fe_add_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) +static noinline void fe_add_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) { { const u32 x20 = in1[9]; { const u32 x21 = in1[8]; @@ -266,7 +266,7 @@ static __always_inline void fe_add(fe_loose *h, const fe *f, const fe *g) fe_add_impl(h->v, f->v, g->v); } -static void fe_sub_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) +static noinline void fe_sub_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) { { const u32 x20 = in1[9]; { const u32 x21 = in1[8]; @@ -309,7 +309,7 @@ static __always_inline void fe_sub(fe_loose *h, const fe *f, const fe *g) fe_sub_impl(h->v, f->v, g->v); } -static void fe_mul_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) +static noinline void fe_mul_impl(u32 out[10], const u32 in1[10], const u32 in2[10]) { { const u32 x20 = in1[9]; { const u32 x21 = in1[8]; @@ -441,7 +441,7 @@ fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) fe_mul_impl(h->v, f->v, g->v); } -static void fe_sqr_impl(u32 out[10], const u32 in1[10]) +static noinline void fe_sqr_impl(u32 out[10], const u32 in1[10]) { { const u32 x17 = in1[9]; { const u32 x18 = in1[8]; @@ -619,7 +619,7 @@ static __always_inline void fe_invert(fe *out, const fe *z) * * Preconditions: b in {0,1} */ -static __always_inline void fe_cswap(fe *f, fe *g, unsigned int b) +static noinline void fe_cswap(fe *f, fe *g, unsigned int b) { unsigned i; b = 0 - b;
Arnd reports that the 32-bit generic library code for Curve25119 ends up using an excessive amount of stack space when built with Clang: lib/crypto/curve25519-fiat32.c:756:6: error: stack frame size of 1384 bytes in function 'curve25519_generic' [-Werror,-Wframe-larger-than=] Let's give some hints to the compiler regarding which routines should not be inlined, to prevent it from running out of registers and spilling to the stack. The resulting code performs identically under both GCC and Clang, and makes the warning go away. Suggested-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- lib/crypto/curve25519-fiat32.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) -- 2.20.1