aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-18 19:40:24 -0700
committerPaul Eggert2018-08-18 19:41:33 -0700
commit6eade1efde873d0b048d8f2841646924cb2ceb16 (patch)
tree6d4e3304cf8acedb9b3d841d6de35a3c868ec029 /src/alloc.c
parent1d2df2fd03f35ca8d8dfc8b999d8bba3c7c13157 (diff)
downloademacs-6eade1efde873d0b048d8f2841646924cb2ceb16.tar.gz
emacs-6eade1efde873d0b048d8f2841646924cb2ceb16.zip
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.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c19
1 files changed, 7 insertions, 12 deletions
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)
3752 if (!FIXNUM_OVERFLOW_P (l)) 3752 if (!FIXNUM_OVERFLOW_P (l))
3753 return make_fixnum (l); 3753 return make_fixnum (l);
3754 } 3754 }
3755 3755 else if (LONG_WIDTH < FIXNUM_BITS)
3756 /* Check if fixnum can be larger than long. */
3757 if (sizeof (EMACS_INT) > sizeof (long))
3758 { 3756 {
3759 size_t bits = mpz_sizeinbase (value, 2); 3757 size_t bits = mpz_sizeinbase (value, 2);
3760 int sign = mpz_sgn (value);
3761 3758
3762 if (bits < FIXNUM_BITS + (sign < 0)) 3759 if (bits <= FIXNUM_BITS)
3763 { 3760 {
3764 EMACS_INT v = 0; 3761 EMACS_INT v = 0;
3765 size_t limbs = mpz_size (value); 3762 int i = 0;
3766 mp_size_t i; 3763 for (int shift = 0; shift < bits; shift += mp_bits_per_limb)
3767
3768 for (i = 0; i < limbs; i++)
3769 { 3764 {
3770 mp_limb_t limb = mpz_getlimbn (value, i); 3765 EMACS_INT limb = mpz_getlimbn (value, i++);
3771 v |= (EMACS_INT) ((EMACS_UINT) limb << (i * mp_bits_per_limb)); 3766 v += limb << shift;
3772 } 3767 }
3773 if (sign < 0) 3768 if (mpz_sgn (value) < 0)
3774 v = -v; 3769 v = -v;
3775 3770
3776 if (!FIXNUM_OVERFLOW_P (v)) 3771 if (!FIXNUM_OVERFLOW_P (v))