From 1d7ef2b85bc4724dd6621b46036d419f13b032de Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 31 Jul 2025 09:50:53 +0900 Subject: [PATCH] mruby-bigint: Apply 4x loop unrolling to uadd for performance Improved the `uadd` function by applying 4x loop unrolling to its core addition loops. This optimization aims to reduce loop overhead and improve instruction-level parallelism, leading to better performance for multi-limb addition operations. Co-authored-by: Gemini --- mrbgems/mruby-bigint/core/bigint.c | 42 +++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index d39fa5823..05d9d326e 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -347,13 +347,53 @@ uadd(mpz_t *z, mpz_t *x, mpz_t *y) size_t i; /* Add overlapping limbs from both operands */ - for (i = 0; i < x->sz; i++) { + /* 4x unrolled loop for better performance */ + for (i = 0; i + 4 <= x->sz; i += 4) { + c += (mp_dbl_limb)y->p[i] + (mp_dbl_limb)x->p[i]; + z->p[i] = LOW(c); + c >>= DIG_SIZE; + + c += (mp_dbl_limb)y->p[i+1] + (mp_dbl_limb)x->p[i+1]; + z->p[i+1] = LOW(c); + c >>= DIG_SIZE; + + c += (mp_dbl_limb)y->p[i+2] + (mp_dbl_limb)x->p[i+2]; + z->p[i+2] = LOW(c); + c >>= DIG_SIZE; + + c += (mp_dbl_limb)y->p[i+3] + (mp_dbl_limb)x->p[i+3]; + z->p[i+3] = LOW(c); + c >>= DIG_SIZE; + } + + /* Handle remaining elements */ + for (; i < x->sz; i++) { c += (mp_dbl_limb)y->p[i] + (mp_dbl_limb)x->p[i]; z->p[i] = LOW(c); c >>= DIG_SIZE; } /* Add remaining limbs from larger operand */ + /* 4x unrolled loop for better performance */ + for (; i + 4 <= y->sz; i += 4) { + c += y->p[i]; + z->p[i] = LOW(c); + c >>= DIG_SIZE; + + c += y->p[i+1]; + z->p[i+1] = LOW(c); + c >>= DIG_SIZE; + + c += y->p[i+2]; + z->p[i+2] = LOW(c); + c >>= DIG_SIZE; + + c += y->p[i+3]; + z->p[i+3] = LOW(c); + c >>= DIG_SIZE; + } + + /* Handle remaining elements */ for (; i < y->sz; i++) { c += y->p[i]; z->p[i] = LOW(c);