Hi,

When I test MPFR with

./configure --with-mini-gmp=/home/vlefevre/software/gmp/mini-gmp CC=gcc-13 
CFLAGS="-O2 -fsanitize=undefined -fno-sanitize-recover 
-DMINI_GMP_LIMB_TYPE=short"

I get lots of failures in mini-gmp.c (I suspect that the errors were
hidden by some optimization in GCC 12 and before).

For instance:

cventin:...ftware/mpfr/tests> ./texceptions
mini-gmp.c:993:7: runtime error: signed integer overflow: 46604 * 61440 cannot 
be represented in type 'int'

This is a call to gmp_udiv_qrnnd_preinv, which has

#define gmp_udiv_qrnnd_preinv(q, r, nh, nl, d, di)                      \
  do {                                                                  \
    mp_limb_t _qh, _ql, _r, _mask;                                      \
    gmp_umul_ppmm (_qh, _ql, (nh), (di));                               \
    gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl));                \
    _r = (nl) - _qh * (d);                                              \
[...]

Here, both _qh and d have type mp_limb_t, which is an unsigned short.
Since this is a 16-bit type and int is on 32 bits, unsigned short is
promoted to int, which is now a signed integer type, hence the error.

Ditto in gmp_udiv_qr_3by2.

I suppose that the simplest solution would be to add a cast to
unsigned long, so that the multiplication is done in this type (and
the subtraction too as a consequence), as this should be the largest
MINI_GMP_LIMB_TYPE size... hoping that the compiler will optimize.

I've attached a patch.

On the following testcase, GCC generates the same code for i1 and i2
and for s1 and s2 (tested on 32-bit and 64-bit x86, on aarch64, and
on ppc64le):

unsigned int i1 (unsigned int a, unsigned int b, unsigned int c)
{
  return a - b * c;
}

unsigned int i2 (unsigned int a, unsigned int b, unsigned int c)
{
  return a - (unsigned long) b * c;
}

unsigned short s1 (unsigned short a, unsigned short b, unsigned short c)
{
  return a - b * c;
}

unsigned short s2 (unsigned short a, unsigned short b, unsigned short c)
{
  return a - (unsigned long) b * c;
}

Otherwise the sizes of the types could be checked like in
gmp_umul_ppmm.

-- 
Vincent Lefèvre <vinc...@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)
diff -r 73d9ef70d14f mini-gmp/mini-gmp.c
--- a/mini-gmp/mini-gmp.c	Wed Jul 19 11:44:37 2023 +0200
+++ b/mini-gmp/mini-gmp.c	Wed Jul 19 15:43:46 2023 +0200
@@ -177,7 +177,7 @@
     mp_limb_t _qh, _ql, _r, _mask;					\
     gmp_umul_ppmm (_qh, _ql, (nh), (di));				\
     gmp_add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl));		\
-    _r = (nl) - _qh * (d);						\
+    _r = (nl) - (unsigned long int) _qh * (d);				\
     _mask = -(mp_limb_t) (_r > _ql); /* both > and >= are OK */		\
     _qh += _mask;							\
     _r += _mask & (d);							\
@@ -198,7 +198,7 @@
     gmp_add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1));			\
 									\
     /* Compute the two most significant limbs of n - q'd */		\
-    (r1) = (n1) - (d1) * (q);						\
+    (r1) = (n1) - (unsigned long int) (d1) * (q);			\
     gmp_sub_ddmmss ((r1), (r0), (r1), (n0), (d1), (d0));		\
     gmp_umul_ppmm (_t1, _t0, (d0), (q));				\
     gmp_sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0);			\
_______________________________________________
gmp-bugs mailing list
gmp-bugs@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-bugs

Reply via email to