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

Reply via email to