On Fri, 30 Jan 2026, Jakub Jelinek wrote:

> Hi!
> 
> The integer_minus_onep case is really meant for multiplication by
> -1, not by (unsigned char)0xff or (unsigned short)0xffff or 0xffffffffU etc.
> We've already tested that the first operand is signed (otherwise the
> earlier case is used) and also that int_fits_type_p (@1, TREE_TYPE (@0)),
> but if @0 is signed and @1 is unsigned all ones with smaller precision
> than that, it fits into @0's type, integer_minus_onep will be true
> and it still should be handled through the ranges, not as @0 == min.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2026-01-30  Jakub Jelinek  <[email protected]>
> 
>       PR tree-optimization/123864
>       * match.pd (__builtin_mul_overflow_p (x, cst, (stype) 0) ->
>       x > stype_max / cst || x < stype_min / cst): Only check
>       integer_minus_onep for signed types.
> 
>       * gcc.c-torture/execute/pr123864.c: New test.
>       * gcc.dg/torture/pr123864.c: New test.
> 
> --- gcc/match.pd.jj   2026-01-28 19:08:29.826843328 +0100
> +++ gcc/match.pd      2026-01-29 14:10:58.905714057 +0100
> @@ -8798,7 +8798,7 @@ (define_operator_list SYNC_FETCH_AND_AND
>     (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
>      (convert (gt @0 (trunc_div! { TYPE_MAX_VALUE (TREE_TYPE (@0)); } @1)))
>      (if (TYPE_MIN_VALUE (TREE_TYPE (@0)))
> -     (if (integer_minus_onep (@1))
> +     (if (!TYPE_UNSIGNED (TREE_TYPE (@1)) && integer_minus_onep (@1))
>        (convert (eq @0 { TYPE_MIN_VALUE (TREE_TYPE (@0)); }))
>        (with
>         {
> --- gcc/testsuite/gcc.c-torture/execute/pr123864.c.jj 2026-01-29 
> 15:11:23.076781766 +0100
> +++ gcc/testsuite/gcc.c-torture/execute/pr123864.c    2026-01-29 
> 15:12:58.421227931 +0100
> @@ -0,0 +1,24 @@
> +/* PR tree-optimization/123864 */
> +
> +[[gnu::noipa]] static int
> +foo (long long x)
> +{
> +  return __builtin_mul_overflow_p (x, ~0U, x);
> +}
> +
> +int
> +main ()
> +{
> +  if (foo (0))
> +    __builtin_abort ();
> +#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 && __CHAR_BIT__ == 8
> +  if (foo (__INT_MAX__ + 1LL))
> +    __builtin_abort ();
> +  if (!foo (__INT_MAX__ + 2LL))
> +    __builtin_abort ();
> +  if (foo (-__INT_MAX__ - 1LL))
> +    __builtin_abort ();
> +  if (!foo (-__INT_MAX__ - 2LL))
> +    __builtin_abort ();
> +#endif
> +}
> --- gcc/testsuite/gcc.dg/torture/pr123864.c.jj        2026-01-29 
> 15:10:46.490378017 +0100
> +++ gcc/testsuite/gcc.dg/torture/pr123864.c   2026-01-29 15:10:23.016760566 
> +0100
> @@ -0,0 +1,28 @@
> +/* PR tree-optimization/123864 */
> +/* { dg-do run { target int128 } } */
> +
> +int u, v, x;
> +
> +[[gnu::noipa]] static void
> +foo ()
> +{
> +  __int128 c = (__int128) 0xa5ee4bc88ULL << 64;
> +  long long b = 0x207b8a7f7LL;
> +  int a = 4;
> +  long long y;
> +  __builtin_add_overflow (a, v, &y);
> +  c *= y;
> +  
> +  unsigned z;
> +  if (__builtin_add_overflow (b, u, &z))
> +    z = 0xffffffffU;
> +  x = __builtin_mul_overflow_p (z, c, c);
> +}
> +
> +int
> +main ()
> +{
> +  foo ();
> +  if (!x)
> +    __builtin_abort ();
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to