https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126509
Bug ID: 126509
Summary: Wrong code with bitint bitfields
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: ktkachov at gcc dot gnu.org
CC: jakub at gcc dot gnu.org
Target Milestone: ---
#define NOIPA __attribute__((noipa))
#define TEST(P, L, K) \
typedef unsigned _BitInt(P) U##P##_##K; \
struct S##P##_##K { unsigned long long lead : L; \
unsigned _BitInt(P) f : K; }; \
NOIPA static void st##P##_##K (struct S##P##_##K *p, U##P##_##K v) \
{ p->f = v; } \
NOIPA static U##P##_##K ld##P##_##K (struct S##P##_##K *p) \
{ return p->f; } \
NOIPA static U##P##_##K add##P##_##K (struct S##P##_##K *p, U##P##_##K v) \
{ return (U##P##_##K) (p->f + v); } \
NOIPA static U##P##_##K xor##P##_##K (struct S##P##_##K *p, U##P##_##K v) \
{ return (U##P##_##K) (p->f ^ v); } \
NOIPA static U##P##_##K not##P##_##K (struct S##P##_##K *p) \
{ return (U##P##_##K) ~p->f; } \
NOIPA static U##P##_##K id##P##_##K (U##P##_##K v) \
{ volatile U##P##_##K t = v; return t; } \
NOIPA static U##P##_##K ref##P##_##K (U##P##_##K v) \
{ \
volatile U##P##_##K t = (U##P##_##K) (v << ((P) - (K))); \
volatile U##P##_##K u = (U##P##_##K) (t >> ((P) - (K))); \
return u; \
} \
static void chk##P##_##K (void) \
{ \
static struct S##P##_##K b; \
U##P##_##K v[4]; \
v[0] = (U##P##_##K) 1 << ((K) - 1); \
v[1] = (U##P##_##K) ~(U##P##_##K) 0; \
v[2] = (U##P##_##K) 1 << (((K) / 64) * 64); \
v[3] = (U##P##_##K) 0x0123456789abcdefULL; \
for (int i = 0; i < 4; i++) \
{ \
U##P##_##K w = v[i]; \
st##P##_##K (&b, w); \
U##P##_##K f = ld##P##_##K (&b); \
if (f != ref##P##_##K (w)) \
__builtin_abort (); \
if (add##P##_##K (&b, id##P##_##K (w)) \
!= (U##P##_##K) (ref##P##_##K (w) + id##P##_##K (w))) \
__builtin_abort (); \
if (xor##P##_##K (&b, id##P##_##K (w)) \
!= (U##P##_##K) (ref##P##_##K (w) ^ id##P##_##K (w))) \
__builtin_abort (); \
if (not##P##_##K (&b) != (U##P##_##K) ~ref##P##_##K (w)) \
__builtin_abort (); \
} \
}
TEST (256, 1, 193)
TEST (320, 1, 193)
TEST (385, 3, 321)
TEST (512, 1, 449)
TEST (575, 1, 511)
/* The same defect with a SIGNED bit-field. The arithmetic is still done in
the unsigned type so that no signed overflow can occur. */
typedef _BitInt(256) S256;
typedef unsigned _BitInt(256) U256;
struct SB { unsigned long long lead : 1; S256 f : 193; };
NOIPA static S256 mk (U256 v) { volatile S256 t = (S256) v; return t; }
NOIPA static void sst (struct SB *p, S256 v) { p->f = v; }
NOIPA static U256 sld (struct SB *p) { return (U256) p->f; }
NOIPA static U256 sadd (struct SB *p, U256 v) { return (U256) ((U256) p->f +
v); }
NOIPA static U256 sxor (struct SB *p, U256 v) { return (U256) ((U256) p->f ^
v); }
NOIPA static U256 sid (U256 v) { volatile U256 t = v; return t; }
static struct SB sb;
static void
chk_signed (void)
{
U256 v[3];
v[0] = (U256) 1 << 192;
v[1] = (U256) ~(U256) 0;
v[2] = (U256) 1 << 191;
for (int i = 0; i < 3; i++)
{
sst (&sb, mk (v[i]));
U256 f = sld (&sb);
if (sadd (&sb, sid (v[i])) != (U256) (f + sid (v[i])))
__builtin_abort ();
if (sxor (&sb, sid (v[i])) != (U256) (f ^ sid (v[i])))
__builtin_abort ();
}
}
int
main (void)
{
chk256_193 ();
chk320_193 ();
chk385_321 ();
chk512_449 ();
chk575_511 ();
chk_signed ();
return 0;
}
Aborts on aarch64 at -O2 and doesn't at -O0