https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127669

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2026-09-30

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Slightly reduced:
typedef unsigned _BitInt(129) T;

[[gnu::noipa]] static T
foo (T v)
{
  return v;
}

static T
bar ()
{
  return 1;
}

int
main ()
{
  T x = __builtin_bitreverseg ((T) 1);
  T y = __builtin_bitreverseg (bar ());
  T z = __builtin_bitreverseg (foo (1));
  if (x != y || x != z)
    __builtin_abort ();
}

x and z are correctly ((T) 1) << 128, and y should be too, but instead is x |
1.
Note, before bitint lowering x is folded to the right constant (already since
generic),
and the z computation is also correct.
The y case is about .BITREVERSE (1); appearing only later on and somehow
fold_stmt not folding that into constant.
So, one bug (missed optimization) is that fold_stmt_1 doesn't do
fold_const_call for internal fns with constant arguments.
And another bug is that when we actually lower large/huge .BITREVERSE (or
.BSWAP?) ifn call with INTEGER_CST argument, we choose wrong size of the
constant.
The lowering of 
  y_6 = .BITREVERSE (1);
is
  _32 = 1 & 1;
  MEM[(unsigned long *)&bitint.13 + 16B] = _32;

  <bb 3> [local count: 1073741824]:
  # _33 = PHI <1(2), _34(3)>
  _35 = 2 - _33;
  _36 = VIEW_CONVERT_EXPR<unsigned long[2]>(*.LC0)[_35];
  _37 = _36 << 63;
  _38 = _35 + 18446744073709551615;
  _39 = VIEW_CONVERT_EXPR<unsigned long[2]>(*.LC0)[_38];
  _40 = _39 >> 1;
  _41 = _37 | _40;
  _42 = __builtin_bitreverse64 (_41);
  bitint.13[_33] = _42;
  _34 = _33 + 18446744073709551615;
  if (_33 != 0)
    goto <bb 3>; [0.05%]
  else
    goto <bb 4>; [99.95%]
which would be correct if .LC0 was an unsigned _BitInt(129) constant.
But the assembly shows
.LC0:
        .quad   1
        .quad   0
i.e. only 128-bit one.  The loop first accesses limbs 2-1 and 2-1-1 and in the
second iteration 2-0 and 2-0-1.  So, it reads one bit out of bounds...

Reply via email to