From: Paul Eggert Date: Sun, 19 Aug 2018 02:40:24 +0000 (-0700) Subject: Improve --with-wide-int mpz_t→fixnum conversion X-Git-Tag: emacs-27.0.90~4544 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=6eade1efde873d0b048d8f2841646924cb2ceb16;p=emacs.git 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. --- diff --git a/src/alloc.c b/src/alloc.c index 0cd3f0c0c3b..60850f73d51 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))