Help GCC compute modiff_incr
* src/floatfns.c: Don’t include count-leading-zeros.h, since we no longer use it directly. (ecount_leading_zeros): Remove. (Flogb): Use elogb instead of doing it by hand. * src/lisp.h: Include count-leading-zeros.h. (elogb): New macro. (modiff_incr): Use it so that on typical platforms we use a hardware instruction instead of a loop.
This commit is contained in:
parent
3cd8ce87d2
commit
0f5b1fcdf0
2 changed files with 19 additions and 13 deletions
|
@ -55,8 +55,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#include <count-leading-zeros.h>
|
||||
|
||||
/* Emacs needs proper handling of +/-inf; correct printing as well as
|
||||
important packages depend on it. Make sure the user didn't specify
|
||||
-ffinite-math-only, either directly or implicitly with -Ofast or
|
||||
|
@ -304,14 +302,6 @@ DEFUN ("float", Ffloat, Sfloat, 1, 1, 0,
|
|||
return FLOATP (arg) ? arg : make_float (XFLOATINT (arg));
|
||||
}
|
||||
|
||||
static int
|
||||
ecount_leading_zeros (EMACS_UINT x)
|
||||
{
|
||||
return (EMACS_UINT_WIDTH == UINT_WIDTH ? count_leading_zeros (x)
|
||||
: EMACS_UINT_WIDTH == ULONG_WIDTH ? count_leading_zeros_l (x)
|
||||
: count_leading_zeros_ll (x));
|
||||
}
|
||||
|
||||
DEFUN ("logb", Flogb, Slogb, 1, 1, 0,
|
||||
doc: /* Returns largest integer <= the base 2 log of the magnitude of ARG.
|
||||
This is the same as the exponent of a float. */)
|
||||
|
@ -338,7 +328,7 @@ This is the same as the exponent of a float. */)
|
|||
EMACS_INT i = XFIXNUM (arg);
|
||||
if (i == 0)
|
||||
return make_float (-HUGE_VAL);
|
||||
value = EMACS_UINT_WIDTH - 1 - ecount_leading_zeros (eabs (i));
|
||||
value = elogb (eabs (i));
|
||||
}
|
||||
|
||||
return make_fixnum (value);
|
||||
|
|
20
src/lisp.h
20
src/lisp.h
|
@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <limits.h>
|
||||
|
||||
#include <attribute.h>
|
||||
#include <count-leading-zeros.h>
|
||||
#include <intprops.h>
|
||||
#include <verify.h>
|
||||
|
||||
|
@ -3904,6 +3905,20 @@ integer_to_uintmax (Lisp_Object num, uintmax_t *n)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return floor (log2 (N)) as an int, where 0 < N <= ULLONG_MAX. */
|
||||
#if (201112 <= __STDC_VERSION__ && INT_MAX <= UINT_MAX \
|
||||
&& LONG_MAX <= ULONG_MAX && LLONG_MAX <= ULLONG_MAX)
|
||||
# define elogb(n) \
|
||||
_Generic (+(n), \
|
||||
int: UINT_WIDTH - 1 - count_leading_zeros (n), \
|
||||
unsigned int: UINT_WIDTH - 1 - count_leading_zeros (n), \
|
||||
long: ULONG_WIDTH - 1 - count_leading_zeros_l (n), \
|
||||
unsigned long: ULONG_WIDTH - 1 - count_leading_zeros_l (n), \
|
||||
default: ULLONG_WIDTH - 1 - count_leading_zeros_ll (n))
|
||||
#else
|
||||
# define elogb(n) (ULLONG_WIDTH - 1 - count_leading_zeros_ll (n))
|
||||
#endif
|
||||
|
||||
/* A modification count. These are wide enough, and incremented
|
||||
rarely enough, so that they should never overflow a 60-bit counter
|
||||
in practice, and the code below assumes this so a compiler can
|
||||
|
@ -3913,11 +3928,12 @@ typedef intmax_t modiff_count;
|
|||
INLINE modiff_count
|
||||
modiff_incr (modiff_count *a, ptrdiff_t len)
|
||||
{
|
||||
modiff_count a0 = *a; int incr = len ? 1 : 0;
|
||||
modiff_count a0 = *a;
|
||||
/* Increase the counter more for a large modification and less for a
|
||||
small modification. Increase it logarithmically to avoid
|
||||
increasing it too much. */
|
||||
while (len >>= 1) incr++;
|
||||
verify (PTRDIFF_MAX <= ULLONG_MAX);
|
||||
int incr = len == 0 ? 1 : elogb (len) + 1;
|
||||
bool modiff_overflow = INT_ADD_WRAPV (a0, incr, a);
|
||||
eassert (!modiff_overflow && *a >> 30 >> 30 == 0);
|
||||
return a0;
|
||||
|
|
Loading…
Add table
Reference in a new issue