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).

Reply via email to