std.crypto.25519.field: avoid excessive inlining

This valid zig code produces reasonable LLVM IR, however, on the
wasm32-wasi target, when using the wasmtime runtime, the number of
locals of the `isSquare` function exceeds 50000, causing wasmtime
to refuse to execute the binary.

The `inline` keyword in Zig is intended to be used only where it is
semantically necessary; not as an optimization hint. Otherwise, this may
produce unwanted binary bloat for the -OReleaseSmall use case.

In the future, it is possible that we may end up with both `inline`
keyword, which operates as it does in status quo, and additionally
`callconv(.inline_hint)` which has no semantic impact, but may be
observed by optimization passes.

In this commit, I also cleaned up `isSquare` by eliminating an
unnecessary mutable variable, replacing it with several local constants.

Closes #11947.
This commit is contained in:
Andrew Kelley 2022-06-27 19:05:51 -07:00
parent 0b8bd9b2b4
commit a71d00a4d5

View File

@ -341,7 +341,7 @@ pub const Fe = struct {
}
/// Square a field element `n` times
inline fn sqn(a: Fe, comptime n: comptime_int) Fe {
fn sqn(a: Fe, n: usize) Fe {
var i: usize = 0;
var fe = a;
while (i < n) : (i += 1) {
@ -390,13 +390,12 @@ pub const Fe = struct {
const _11 = a.mul(a.sq());
const _1111 = _11.mul(_11.sq().sq());
const _11111111 = _1111.mul(_1111.sq().sq().sq().sq());
var t = _11111111.sqn(2).mul(_11);
const u = t;
t = t.sqn(10).mul(u).sqn(10).mul(u);
t = t.sqn(30).mul(t);
t = t.sqn(60).mul(t);
t = t.sqn(120).mul(t).sqn(10).mul(u).sqn(3).mul(_11).sq();
return @bitCast(bool, @truncate(u1, ~(t.toBytes()[1] & 1)));
const u = _11111111.sqn(2).mul(_11);
const t = u.sqn(10).mul(u).sqn(10).mul(u);
const t2 = t.sqn(30).mul(t);
const t3 = t2.sqn(60).mul(t2);
const t4 = t3.sqn(120).mul(t3).sqn(10).mul(u).sqn(3).mul(_11).sq();
return @bitCast(bool, @truncate(u1, ~(t4.toBytes()[1] & 1)));
}
fn uncheckedSqrt(x2: Fe) Fe {