mpn/x86/aors_n.asm low-hanging fruit
David Sparks
sparks05 at proton.me
Tue Sep 29 06:49:16 CEST 2026
As the comment suggests, it is indeed possible to simplify.
The big win is avoiding a register spill.
The one thing I want to be certain of is that I am assuming the
carry parameter is a boolean and the change in the handling of
non-zero even values is not a problem.
I tried to audit the call sites, but there's a lot of subtle code
(toom*.c is twisty maze of little passages) and it's difficult to
be sure.
The other alternative is "shr $1,PARAM_CARRY", which would be
exactly compatible and even shorter, but would perform an
unnecessary stack write.
diff --git a/mpn/x86/aors_n.asm b/mpn/x86/aors_n.asm
index 5d359f59b..7af326ebd 100644
--- a/mpn/x86/aors_n.asm
+++ b/mpn/x86/aors_n.asm
@@ -105,12 +105,9 @@ L(0a): leal (%eax,%eax,8),%eax
leal L(oop)-3(%eax,%eax,8),%eax
')
- C These lines initialize carry from the 5th parameter. Should be
- C possible to simplify.
- pushl %ebp FRAME_pushl()
- movl PARAM_CARRY,%ebp
- shrl %ebp C shift bit 0 into carry
- popl %ebp FRAME_popl()
+ C Initialize the carry from the 5th parameter (without another spill)
+ cmpl $1,PARAM_CARRY C set borrow iff PARAM_CARRY < 1
+ cmc C complement carry, now set iff PARAM_CARRY > 0
jmp *%eax C jump into loop
I'd let the 32-bit x86 code quietly molder in obsolescence,
but the comment was a big flashing <blink>FIXME</blink>.
If I *were* going to tackle it, I'd have a look at mpn/x86/gcd_11.asm
(which assumes bsf is unusably slow for ctz) and see if it would
help to replace the current lookup table
while (unlikely((u & 0x3f) == 0))
u >>= 6;
u >>= ctz_table[u & 0x3f];
with an immediate constant like
// We know that u is even, as it's the difference of two odds
while (unlikely((u & 0x1e) == 0))
u >>= 4;
u >>= 0x12131210 >> (u & 0x1e) & 3;
u >>= 1;
This has a MAXSHIFT of 4, rather than 6, although it takes advantage
of the fact that u is initially even, so the chance of looping at least
once is 1/16, only twice as bad as the current code's 1/32.
... but I can't, because I have no idea where to find a suitable
benchmark target.
More information about the gmp-devel
mailing list