On Tue, Oct 6, 2026 at 11:27 PM Jakub Jelinek <[email protected]> wrote:
>
> Hi!
>
> r17-126 has changed the simplification in a way where it can now
> introduce signed integer overflow into a program which didn't have it before,
> e.g. x != (INT_MAX - 3) ? x + 5 : (INT_MIN + 1) when x is int
> doesn't invoke signed integer overflow for x equal to INT_MAX - 3 (it does
> for various other values and for many doesn't), while the simplified
> x + 5 invokes it even for that value.
>
> The following patch fixes it by checking for overflow on the CST1 + CST2
> addition, if TYPE_OVERFLOW_WRAPS or if CST1 + CST2 doesn't overflow,
> it does what it previously did, otherwise rewrites x + CST2 into
> unsigned.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2026-10-07 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/126459
> * match.pd (x != CST1 ? x + CST2 : CST3 -> x + CST2): If
> CST1 + CST2 overflows and type overflow doesn't wrap,
> simplify into corresponding unsigned addition.
Ok.
>
> * gcc.dg/torture/pr126459.c: New test.
>
> --- a/gcc/match.pd 2026-10-03 21:28:13.092320517 +0200
> +++ b/gcc/match.pd 2026-10-06 21:51:21.966900769 +0200
> @@ -5369,9 +5369,16 @@ (define_operator_list SYNC_FETCH_AND_AND
> tree cst1 = uniform_integer_cst_p (@1);
> tree cst2 = uniform_integer_cst_p (@3);
> tree cst3 = uniform_integer_cst_p (@4);
> - }
> - (if (wi::to_wide (cst1) + wi::to_wide (cst2) == wi::to_wide (cst3))
> - @2))))
> + wi::overflow_type ovf;
> + }
> + (if (wi::add (wi::to_wide (cst1), wi::to_wide (cst2),
> + TYPE_SIGN (TREE_TYPE (cst1)), &ovf) == wi::to_wide (cst3))
> + (if (!ovf || TYPE_OVERFLOW_WRAPS (TREE_TYPE (cst1)))
> + @2
> + (with {
> + tree utype = unsigned_type_for (type);
> + }
> + (convert (plus (convert:utype @0) (convert:utype @3)))))))))
>
> /* Simplifications of shift and rotates. */
>
> --- a/gcc/testsuite/gcc.dg/torture/pr126459.c 2026-10-06 22:05:01.595899608
> +0200
> +++ b/gcc/testsuite/gcc.dg/torture/pr126459.c 2026-10-06 22:04:43.130147484
> +0200
> @@ -0,0 +1,34 @@
> +/* PR tree-optimization/126459 */
> +/* { dg-do run } */
> +
> +#define INT_MAX __INT_MAX__
> +#define INT_MIN (-(INT_MAX) - 1)
> +
> +__attribute__((noipa)) int
> +foo (int x)
> +{
> + return (x != INT_MAX ? x + 1 : INT_MIN) > x;
> +}
> +
> +__attribute__((noipa)) int
> +bar (int x)
> +{
> + return (x != INT_MIN ? x - 1 : INT_MAX) < x;
> +}
> +
> +__attribute__((noipa)) int
> +baz (int x)
> +{
> + return (x != INT_MIN ? x + INT_MIN : 0) < 0;
> +}
> +
> +int
> +main ()
> +{
> + if (foo (INT_MAX) != 0 || foo (1) != 1)
> + __builtin_abort ();
> + if (bar (INT_MIN) != 0 || bar (2) != 1)
> + __builtin_abort ();
> + if (baz (INT_MIN) != 0 || baz (3) != 1)
> + __builtin_abort ();
> +}
>
> Jakub
>