Pip Cet wrote: > I'm already using a separate tag value for bignums, though it might > help to use tag value 0 instead of a nonzero one (but then Qnil > couldn't be all-zeroes in memory). We'd have to measure it, as there is also a benefit when NILP and initialization to Qnil are fast. > I've discovered that the sequence gcc (trunk) emits for a mask-and-compare is: > mov %rax, %rbx > and $7, %rbx > cmp $7, %rbx > where I would use > lea 1(%rax), %ebx > test $7, %bl > > I can force the latter by testing ((char)((int)(XLI (x) + 8 - > Lisp_String)) & 7) == 0 rather than the (equivalent, AFAICS) (XLI (x) > & 7) == Lisp_String (sometimes gcc uses a longer sequence, though). At > this point, I think gcc should be emitting the shorter two-insn > sequence for both C expressions. I agree, and filed a GCC bug report about it, here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87104 > With this "improvement", the code size difference is 13184 bytes. I'm > unable to measure a performance difference, since it is lost in the > noise. I tried a similar microoptimization on the Emacs trunk, and it made Emacs about 0.4% faster on my platform. This seems like a clear win pretty much everywhere, regardless of what we do about eq vs eql, so I installed the attached patch into master. > I've benchmarked the hash-cons approach, though the implementation I > used was rather trivial, and simple bignum calculations appear to be > about 20-50% slower. Again, I expect that number to increase once the > extra copy in make_number is removed. (For floats, the slowdown is > worse.) Ouch. These figures are making me more inclined to stick with what we have in master, namely the Common Lisp and Scheme tradition that eq is a finer comparison operation than eql is, when these comparisons are applied to bignums and/or to floats. Of course we can continue to guarantee the traditional eq semantics on fixnums.