https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120547
Bug ID: 120547
Summary: Wrong-code due to real_from_integer
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: jakub at gcc dot gnu.org
Target Milestone: ---
#define CHECK(x, y) \
if ((double) x != (double) y || (double) (x + 1) != (double) (y + 1))
\
__builtin_abort ()
int
main ()
{
unsigned long long a = 0x20000000000001ULL << 7;
volatile unsigned long long b = a;
CHECK (a, b);
unsigned _BitInt(4096) c = ((unsigned _BitInt(4096)) 0x20000000000001ULL) <<
253;
volatile unsigned _BitInt(4096) d = c;
CHECK (c, d);
unsigned _BitInt(4096) e = ((unsigned _BitInt(4096)) 0x20000000000001ULL) <<
931;
volatile unsigned _BitInt(4096) f = e;
CHECK (e, f);
}
is miscompiled in GCC 14+ (when _BitInt support has been added).
int maxbitlen = MAX_BITSIZE_MODE_ANY_INT + HOST_BITS_PER_WIDE_INT;
and
/* We have to ensure we can negate the largest negative number. */
wide_int val = wide_int::from (val_in, maxbitlen, sgn);
have not been adjusted for _BitInt.
And another bug is in
/* This value is too large, we must shift it right to
preserve all the bits we can, and then bump the
exponent up by that amount. */
val = wi::lrshift (val, e);
This throws away the low bits, while I think we should or in 1 if any of the
shifted away bits are non-zero (so the kind of sticky shift which e.g. soft-fp
is doing).