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)
