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 <[email protected]> - 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
[email protected]
https://gmplib.org/mailman/listinfo/gmp-bugs