> Am 31.07.2025 um 22:03 schrieb Jakub Jelinek <ja...@redhat.com>:
>
> Hi!
>
> The following testcase results in compiler UB as detected by ubsan.
> find_bswap_or_nop first checks is_bswap_or_nop_p and if that fails
> on the tmp_n value, tries some rotation of that if possible.
> The discovery what rotate count to use ignores zero bytes from
> the least significant end (those mean zero bytes and so can be masked
> away) and on the first non-zero non-0xff byte (0xff means don't know),
> 1-8 means some particular byte of the original computes count (the rotation
> count) from that byte + the byte index.
> Now, on the following testcase we have tmp_n 0x403020105060700, i.e.
> the least significant byte is zero, then the msb from the original value,
> byte below it, another one below it, then the low 32 bits of the original
> value. So, we stop at count 7 with i 1, it wraps around and we get count
> 0.
> Then we invoke UB on
> tmp_n = tmp_n >> count | tmp_n << (range - count);
> because count is 0 and range is 64.
> Now, of course I could fix it up by doing tmp_n << ((range - count) % range)
> or something similar, but that is just wasted compile time, if count is 0,
> we already know that is_bswap_or_nop_p failed on that tmp_n value and
> so it will fail again if the value is the same. So I think better
> just return NULL (i.e. punt).
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
> 15.2?
Ok
Richard
> 2025-07-31 Jakub Jelinek <ja...@redhat.com>
>
> PR middle-end/121322
> * gimple-ssa-store-merging.cc (find_bswap_or_nop): Return NULL if
> count is 0.
>
> * gcc.dg/pr121322.c: New test.
>
> --- gcc/gimple-ssa-store-merging.cc.jj 2025-07-31 10:53:47.607180140 +0200
> +++ gcc/gimple-ssa-store-merging.cc 2025-07-31 11:53:51.635997562 +0200
> @@ -1055,6 +1055,8 @@ find_bswap_or_nop (gimple *stmt, struct
> if (count <= range / BITS_PER_MARKER)
> {
> count = (count + i) * BITS_PER_MARKER % range;
> + if (!count)
> + return NULL;
> break;
> }
> else
> --- gcc/testsuite/gcc.dg/pr121322.c.jj 2025-07-31 11:58:02.103718378 +0200
> +++ gcc/testsuite/gcc.dg/pr121322.c 2025-07-31 11:57:44.136953600 +0200
> @@ -0,0 +1,14 @@
> +/* PR middle-end/121322 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +unsigned long long
> +foo (unsigned long long *p)
> +{
> + unsigned long long a = *p;
> + unsigned long long b = __builtin_bswap64 (a);
> + return ((b << 32)
> + | ((b >> 8) & 0xff000000ULL)
> + | ((b >> 24) & 0xff0000ULL)
> + | ((b >> 40) & 0xff00ULL));
> +}
>
> Jakub
>