emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 6eade1e: Improve --with-wide-int mpz_t→fixnum conv


From: Paul Eggert
Subject: [Emacs-diffs] master 6eade1e: Improve --with-wide-int mpz_t→fixnum conversion
Date: Sat, 18 Aug 2018 22:41:39 -0400 (EDT)

branch: master
commit 6eade1efde873d0b048d8f2841646924cb2ceb16
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Improve --with-wide-int mpz_t→fixnum conversion
    
    These tuneups and minor simplifications should affect only
    platforms with EMACS_INT wider than ‘long’.
    * src/alloc.c (make_number): If the number fits in long but
    not in fixnum, do not attempt to convert to fixnum again.
    Tighten the compile-time check for whether the second attempt
    is worth trying, from sizeof (long) < sizeof (EMACS_INT) to
    LONG_WIDTH < FIXNUM_BITS.  Do not bother computing the sign of
    the value to tighten the bounds for whether to try the second
    attempt, as it’s not worth the effort.  Do not call mpz_size,
    which is unnecessary since the number of bits is already known
    and the loop can iterate over a shift count instead.  Avoid
    unnecessary casts.  Use + instead of | where either will do,
    as + is typically better for optimization.
    
    Improve mpz_t to fixnum when --with-wide-int
    * src/alloc.c (make_number): Avoid undefined behavior
    when shifting an EMACS_UINT by more than EMACS_UINT_WIDTH bits.
    Check for integer overflow when shifting.
---
 src/alloc.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/alloc.c b/src/alloc.c
index 0cd3f0c..60850f7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3752,25 +3752,20 @@ make_number (mpz_t value)
       if (!FIXNUM_OVERFLOW_P (l))
        return make_fixnum (l);
     }
-
-  /* Check if fixnum can be larger than long.  */
-  if (sizeof (EMACS_INT) > sizeof (long))
+  else if (LONG_WIDTH < FIXNUM_BITS)
     {
       size_t bits = mpz_sizeinbase (value, 2);
-      int sign = mpz_sgn (value);
 
-      if (bits < FIXNUM_BITS + (sign < 0))
+      if (bits <= FIXNUM_BITS)
         {
           EMACS_INT v = 0;
-          size_t limbs = mpz_size (value);
-          mp_size_t i;
-
-          for (i = 0; i < limbs; i++)
+         int i = 0;
+         for (int shift = 0; shift < bits; shift += mp_bits_per_limb)
             {
-              mp_limb_t limb = mpz_getlimbn (value, i);
-              v |= (EMACS_INT) ((EMACS_UINT) limb << (i * mp_bits_per_limb));
+             EMACS_INT limb = mpz_getlimbn (value, i++);
+             v += limb << shift;
             }
-          if (sign < 0)
+         if (mpz_sgn (value) < 0)
             v = -v;
 
           if (!FIXNUM_OVERFLOW_P (v))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]