mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
libgcc: Another __divmodbitint4 bug fix [PR114762]
The following testcase is miscompiled because the code to decrement vn on negative value with all ones in most significant limb (even partial) and 0 in most significant bit of the second most significant limb doesn't take into account the case where all bits below the most significant limb are zero. This has been a problem both in the version before yesterday's commit where it has been done only if un was one shorter than vn before this decrement, and is now problem even more often when it is done earlier. When we decrement vn in such case and negate it, we end up with all 0s in the v2 value, so have both the problems with UB on __builtin_clz* and the expectations of the algorithm that the divisor has most significant bit set after shifting, plus when the decremented vn is 1 it can SIGFPE on division by zero even when it is not division by zero etc. Other values shouldn't get 0 in the new most significant limb after negation, because the bitint_reduce_prec canonicalization should reduce prec if the second most significant limb is all ones and if that limb is all zeros, if at least one limb below it is non-zero, carry in will make it non-zero. The following patch fixes it by checking if at least one bit below the most significant limb is non-zero, in that case it decrements, otherwise it will do nothing (but e.g. for the un < vn case that also means the divisor is large enough that the result should be q 0 r u). 2024-04-18 Jakub Jelinek <jakub@redhat.com> PR libgcc/114762 * libgcc2.c (__divmodbitint4): Perform the decrement on negative v with most significant limb all ones and the second least significant limb with most significant bit clear always, regardless of un < vn. * gcc.dg/torture/bitint-70.c: New test.
This commit is contained in:
parent
694fa3717a
commit
36f4c8a9ac
22
gcc/testsuite/gcc.dg/torture/bitint-70.c
Normal file
22
gcc/testsuite/gcc.dg/torture/bitint-70.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* PR libgcc/114762 */
|
||||
/* { dg-do run { target bitint } } */
|
||||
/* { dg-options "-std=c23" } */
|
||||
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
|
||||
/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
|
||||
|
||||
#if __BITINT_MAXWIDTH__ >= 255
|
||||
__attribute__((__noipa__)) signed _BitInt(255)
|
||||
foo (signed _BitInt(255) a, signed _BitInt(65) b)
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
#if __BITINT_MAXWIDTH__ >= 255
|
||||
if (foo (1, -0xffffffffffffffffwb - 1wb))
|
||||
__builtin_abort ();
|
||||
#endif
|
||||
}
|
@ -1715,11 +1715,18 @@ __divmodbitint4 (UBILtype *q, SItype qprec,
|
||||
&& vn > 1
|
||||
&& (Wtype) v[BITINT_END (1, vn - 2)] >= 0)
|
||||
{
|
||||
vp = 0;
|
||||
--vn;
|
||||
/* Unless all bits below the most significant limb are zero. */
|
||||
SItype vn2;
|
||||
for (vn2 = vn - 2; vn2 >= 0; --vn2)
|
||||
if (v[BITINT_END (vn - 1 - vn2, vn2)])
|
||||
{
|
||||
vp = 0;
|
||||
--vn;
|
||||
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
++v;
|
||||
++v;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__builtin_expect (un < vn, 0))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user