https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108787
Bug ID: 108787 Summary: [13 Regression] libsodium miscompilation on power9 starting with r13-2107 Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- The following testcase is miscompiled with -mcpu=power9 -mtune=power9 starting with r13-2107-gdefa08a33672d200edbdd7f87ed7afa442249261 . Doesn't reproduce without -fPIC though. /* { dg-do run { target int128 } } */ /* { dg-options "-O2" } */ /* { dg-additional-options "-fPIC" { target fpic } } */ typedef unsigned __int128 uint128_t; static inline unsigned long long foo (const unsigned char src[8]) { unsigned long long w; __builtin_memcpy (&w, src, sizeof w); return w; } typedef struct S { unsigned long long r[3], h[3]; unsigned char final; } S; __attribute__((noipa)) static void poly1305_blocks (S *st, const unsigned char *m, unsigned long long bytes) { const unsigned long long hibit = st->final ? 0ULL : (1ULL << 40); unsigned long long r0, r1, r2; unsigned long long s1, s2; unsigned long long h0, h1, h2; unsigned long long c; uint128_t d0, d1, d2, d; r0 = st->r[0]; r1 = st->r[1]; r2 = st->r[2]; h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; s1 = r1 * (5 << 2); s2 = r2 * (5 << 2); while (bytes >= 16) { unsigned long long t0, t1; t0 = foo (&m[0]); t1 = foo (&m[8]); h0 += t0 & 0xfffffffffff; h1 += ((t0 >> 44) | (t1 << 20)) & 0xfffffffffff; h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit; d0 = ((uint128_t) h0 * r0); d = ((uint128_t) h1 * s2); d0 += d; d = ((uint128_t) h2 * s1); d0 += d; d1 = ((uint128_t) h0 * r1); d = ((uint128_t) h1 * r0); d1 += d; d = ((uint128_t) h2 * s2); d1 += d; d2 = ((uint128_t) h0 * r2); d = ((uint128_t) h1 * r1); d2 += d; d = ((uint128_t) h2 * r0); d2 += d; c = (unsigned long long) (d0 >> (44)); h0 = (unsigned long long) (d0) & 0xfffffffffff; d1 += c; c = (unsigned long long) (d1 >> (44)); h1 = (unsigned long long) (d1) & 0xfffffffffff; d2 += c; c = (unsigned long long) (d2 >> (42)); h2 = (unsigned long long) (d2) & 0x3ffffffffff; h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; h1 += c; m += 16; bytes -= 16; } st->h[0] = h0; st->h[1] = h1; st->h[2] = h2; } int main () { if (sizeof (unsigned long long) != 8 || sizeof (uint128_t) != 16) return 0; S st = { .r = { 0x42c052bac7bULL, 0x7ab6080f47bULL, 0x455e9a405ULL }, .h = { 0x3efe88da491ULL, 0xd10577b4a44ULL, 0x3efa677b3dbULL } }; unsigned long long l[2] = { 0, 0x72ULL }; poly1305_blocks (&st, (unsigned char *) &l[0], sizeof (l)); if (st.h[0] != 0xef4cd4260ULL || st.h[1] != 0x5d0e836abb6ULL || st.h[2] != 0x171e724427ULL) __builtin_abort (); return 0; }