From 0ed00f7825baca2b63c44ab598049c66e49fa98e Mon Sep 17 00:00:00 2001
From: Oleksandr Tkachenko <108659113+altkdf@users.noreply.github.com>
Date: Thu, 14 Dec 2023 17:00:36 +0100
Subject: [PATCH] k256: add more inlines for better efficiency (#999)

---
 k256/benches/ecdsa.rs                   | 14 +++++++++---
 k256/benches/field.rs                   | 16 +++++++------
 k256/benches/scalar.rs                  | 30 ++++++++++++++++---------
 k256/src/arithmetic/field.rs            |  2 ++
 k256/src/arithmetic/field/field_5x52.rs |  2 ++
 k256/src/arithmetic/scalar.rs           |  1 +
 6 files changed, 44 insertions(+), 21 deletions(-)

diff --git a/k256/benches/ecdsa.rs b/k256/benches/ecdsa.rs
index 425ab15b0..548b16b92 100644
--- a/k256/benches/ecdsa.rs
+++ b/k256/benches/ecdsa.rs
@@ -1,6 +1,6 @@
 //! secp256k1 scalar arithmetic benchmarks
 
-use criterion::{criterion_group, criterion_main, Criterion};
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
 use ecdsa_core::{
     elliptic_curve::group::prime::PrimeCurveAffine,
     hazmat::{SignPrimitive, VerifyPrimitive},
@@ -44,14 +44,22 @@ fn bench_ecdsa(c: &mut Criterion) {
     let z = test_scalar_z();
 
     group.bench_function("try_sign_prehashed", |b| {
-        b.iter(|| d.try_sign_prehashed(k, &z).unwrap())
+        b.iter(|| {
+            black_box(d)
+                .try_sign_prehashed(black_box(k), &black_box(z))
+                .unwrap()
+        })
     });
 
     let q = (AffinePoint::generator() * d).to_affine();
     let s = d.try_sign_prehashed(k, &z).unwrap().0;
 
     group.bench_function("verify_prehashed", |b| {
-        b.iter(|| q.verify_prehashed(&z, &s).unwrap())
+        b.iter(|| {
+            black_box(q)
+                .verify_prehashed(&black_box(z), &black_box(s))
+                .unwrap()
+        })
     });
 
     group.finish();
diff --git a/k256/benches/field.rs b/k256/benches/field.rs
index 1ccac28b0..2c0bdd02a 100644
--- a/k256/benches/field.rs
+++ b/k256/benches/field.rs
@@ -1,7 +1,7 @@
 //! secp256k1 field element benchmarks
 
 use criterion::{
-    criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion,
+    black_box, criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion,
 };
 use k256::FieldElement;
 
@@ -31,33 +31,35 @@ fn test_field_element_y() -> FieldElement {
 
 fn bench_field_element_normalize_weak<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
-    group.bench_function("normalize_weak", |b| b.iter(|| x.normalize_weak()));
+    group.bench_function("normalize_weak", |b| {
+        b.iter(|| black_box(x).normalize_weak())
+    });
 }
 
 fn bench_field_element_normalize<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
-    group.bench_function("normalize", |b| b.iter(|| x.normalize()));
+    group.bench_function("normalize", |b| b.iter(|| black_box(x).normalize()));
 }
 
 fn bench_field_element_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
     let y = test_field_element_y();
-    group.bench_function("mul", |b| b.iter(|| &x * &y));
+    group.bench_function("mul", |b| b.iter(|| &black_box(x) * &black_box(y)));
 }
 
 fn bench_field_element_square<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
-    group.bench_function("square", |b| b.iter(|| x.square()));
+    group.bench_function("square", |b| b.iter(|| black_box(x).square()));
 }
 
 fn bench_field_element_sqrt<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
-    group.bench_function("sqrt", |b| b.iter(|| x.sqrt()));
+    group.bench_function("sqrt", |b| b.iter(|| black_box(x).sqrt()));
 }
 
 fn bench_field_element_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_field_element_x();
-    group.bench_function("invert", |b| b.iter(|| x.invert()));
+    group.bench_function("invert", |b| b.iter(|| black_box(x).invert()));
 }
 
 fn bench_field_element(c: &mut Criterion) {
diff --git a/k256/benches/scalar.rs b/k256/benches/scalar.rs
index 2199eb6e2..c6f73d2b2 100644
--- a/k256/benches/scalar.rs
+++ b/k256/benches/scalar.rs
@@ -1,7 +1,7 @@
 //! secp256k1 scalar arithmetic benchmarks
 
 use criterion::{
-    criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion,
+    black_box, criterion_group, criterion_main, measurement::Measurement, BenchmarkGroup, Criterion,
 };
 use hex_literal::hex;
 use k256::{
@@ -33,16 +33,22 @@ fn bench_point_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let p = ProjectivePoint::GENERATOR;
     let m = hex!("AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522");
     let s = Scalar::from_repr(m.into()).unwrap();
-    group.bench_function("point-scalar mul", |b| b.iter(|| &p * &s));
+    group.bench_function("point-scalar mul", |b| {
+        b.iter(|| &black_box(p) * &black_box(s))
+    });
 }
 
 fn bench_point_lincomb<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let p = ProjectivePoint::GENERATOR;
     let m = hex!("AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522");
     let s = Scalar::from_repr(m.into()).unwrap();
-    group.bench_function("lincomb via mul+add", |b| b.iter(|| &p * &s + &p * &s));
+    group.bench_function("lincomb via mul+add", |b| {
+        b.iter(|| &black_box(p) * &black_box(s) + &black_box(p) * &black_box(s))
+    });
     group.bench_function("lincomb()", |b| {
-        b.iter(|| ProjectivePoint::lincomb(&p, &s, &p, &s))
+        b.iter(|| {
+            ProjectivePoint::lincomb(&black_box(p), &black_box(s), &black_box(p), &black_box(s))
+        })
     });
 }
 
@@ -50,10 +56,12 @@ fn bench_point_mul_by_generator<'a, M: Measurement>(group: &mut BenchmarkGroup<'
     let p = ProjectivePoint::GENERATOR;
     let x = test_scalar_x();
 
-    group.bench_function("mul_by_generator naive", |b| b.iter(|| &p * &x));
+    group.bench_function("mul_by_generator naive", |b| {
+        b.iter(|| &black_box(p) * &black_box(x))
+    });
 
     group.bench_function("mul_by_generator precomputed", |b| {
-        b.iter(|| ProjectivePoint::mul_by_generator(&x))
+        b.iter(|| ProjectivePoint::mul_by_generator(&black_box(x)))
     });
 }
 
@@ -68,29 +76,29 @@ fn bench_high_level(c: &mut Criterion) {
 fn bench_scalar_sub<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_scalar_x();
     let y = test_scalar_y();
-    group.bench_function("sub", |b| b.iter(|| &x - &y));
+    group.bench_function("sub", |b| b.iter(|| &black_box(x) - &black_box(y)));
 }
 
 fn bench_scalar_add<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_scalar_x();
     let y = test_scalar_y();
-    group.bench_function("add", |b| b.iter(|| &x + &y));
+    group.bench_function("add", |b| b.iter(|| &black_box(x) + &black_box(y)));
 }
 
 fn bench_scalar_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_scalar_x();
     let y = test_scalar_y();
-    group.bench_function("mul", |b| b.iter(|| &x * &y));
+    group.bench_function("mul", |b| b.iter(|| &black_box(x) * &black_box(y)));
 }
 
 fn bench_scalar_negate<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_scalar_x();
-    group.bench_function("negate", |b| b.iter(|| -x));
+    group.bench_function("negate", |b| b.iter(|| -black_box(x)));
 }
 
 fn bench_scalar_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) {
     let x = test_scalar_x();
-    group.bench_function("invert", |b| b.iter(|| x.invert()));
+    group.bench_function("invert", |b| b.iter(|| black_box(x).invert()));
 }
 
 fn bench_scalar(c: &mut Criterion) {
diff --git a/k256/src/arithmetic/field.rs b/k256/src/arithmetic/field.rs
index 6956169ed..db2f556c2 100644
--- a/k256/src/arithmetic/field.rs
+++ b/k256/src/arithmetic/field.rs
@@ -441,6 +441,7 @@ impl Mul<FieldElement> for FieldElement {
 impl Mul<&FieldElement> for FieldElement {
     type Output = FieldElement;
 
+    #[inline(always)]
     fn mul(self, other: &FieldElement) -> FieldElement {
         FieldElement(self.0.mul(&(other.0)))
     }
@@ -489,6 +490,7 @@ impl Sum for FieldElement {
 }
 
 impl<'a> Sum<&'a FieldElement> for FieldElement {
+    #[inline]
     fn sum<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
         iter.copied().sum()
     }
diff --git a/k256/src/arithmetic/field/field_5x52.rs b/k256/src/arithmetic/field/field_5x52.rs
index fbb973308..c14de07ae 100644
--- a/k256/src/arithmetic/field/field_5x52.rs
+++ b/k256/src/arithmetic/field/field_5x52.rs
@@ -71,6 +71,7 @@ impl FieldElement5x52 {
     ///
     /// Returns None if the byte array does not contain a big-endian integer in the range
     /// [0, p).
+    #[inline]
     pub fn from_bytes(bytes: &FieldBytes) -> CtOption<Self> {
         let res = Self::from_bytes_unchecked(bytes.as_ref());
         let overflow = res.get_overflow();
@@ -442,6 +443,7 @@ impl FieldElement5x52 {
     /// Returns self * rhs mod p
     /// Brings the magnitude to 1 (but doesn't normalize the result).
     /// The magnitudes of arguments should be <= 8.
+    #[inline(always)]
     pub fn mul(&self, rhs: &Self) -> Self {
         self.mul_inner(rhs)
     }
diff --git a/k256/src/arithmetic/scalar.rs b/k256/src/arithmetic/scalar.rs
index cd63eec01..e0f98595c 100644
--- a/k256/src/arithmetic/scalar.rs
+++ b/k256/src/arithmetic/scalar.rs
@@ -575,6 +575,7 @@ impl Add<&Scalar> for Scalar {
 }
 
 impl AddAssign<Scalar> for Scalar {
+    #[inline]
     fn add_assign(&mut self, rhs: Scalar) {
         *self = Scalar::add(self, &rhs);
     }