On Tue, Aug 11, 2026 at 10:13 AM Richard Biener
<[email protected]> wrote:
>
>
>
> > Am 11.08.2026 um 17:00 schrieb Andrea Pinski
> > <[email protected]>:
> >
> > 3 recent match patterns were added that introduce signed integer overflow
> > where
> > there was none before. These 3 were in the form of `cmp + (-cmp ^ x)` and
> > `((dec_exp + -cmp) ^ -cmp)` In the first 2, ABSU is needed to be used
> > and in the other one we need to cast first to the unsigned type before
> > taking the 2comps negative value and then cast back.
> >
> > Bootstrapped and tested on x86_64-linux-gnu.
> >
> > PR tree-optimization/126418
> >
> > gcc/ChangeLog:
> >
> > * match.pd (`((x - (x<0)) ^ -(x<0)`): Use ABSU.
> > (`(X ^ -(X < 0)) + (X < 0)`): Likewise.
> > (`(A ^ -cmp) + cmp`): Cast to unsigned type
> > before taking the negative.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.dg/tree-ssa/pr113894.c: Update testcase for ABSU.
> > * gcc.dg/tree-ssa/pr123514.c: Likewise.
> > * gcc.dg/tree-ssa/pr126418-1.c: New test.
> >
> > Signed-off-by: Andrea Pinski <[email protected]>
> > ---
> > gcc/match.pd | 18 +++++++++++++-----
> > gcc/testsuite/gcc.dg/tree-ssa/pr113894.c | 2 +-
> > gcc/testsuite/gcc.dg/tree-ssa/pr123514.c | 2 +-
> > gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c | 11 +++++++++++
> > 4 files changed, 26 insertions(+), 7 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 50e73177022..751f5571183 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -228,22 +228,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > (abs @0)))
> > #endif
> >
> > -/* (X - (X < 0)) ^ -(X < 0) -> abs (X) */
> > +/* (X - (X < 0)) ^ -(X < 0) -> absu (X) */
>
> But if X is INT_MIN then we subtract 1 already?
Yes for this one. I missed the connection between the cmp and INT_MIN
here; whoops.
>
> > (simplify
> > (bit_xor:c (minus @0 (convert@1 (lt @0 integer_zerop)))
> > (negate @1))
> > (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> > && !TYPE_UNSIGNED (TREE_TYPE (@0)))
> > - (abs @0)))
> > + (with { tree utype = unsigned_type_for (type); }
> > + (convert (absu:utype @0)))))
> >
> > -/* (X ^ -(X < 0)) + (X < 0) -> abs (X) */
> > +/* (X ^ -(X < 0)) + (X < 0) -> absu (X) */
>
> Likewise
Oh yes because we do (INT_MIN ^ -1) + 1 but wait that is INT_MAX + 1.
So yes that does not introduce a new overflow.
>
> > (simplify
> > (plus:c (bit_xor:c @0 (negate (convert@1 (lt @0 integer_zerop)))) @1)
> > (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> > && !TYPE_UNSIGNED (TREE_TYPE (@0))
> > && !TYPE_SATURATING (TREE_TYPE (@0))
> > && (GIMPLE || !TREE_SIDE_EFFECTS (@0)))
> > - (abs @0)))
> > + (with { tree utype = unsigned_type_for (type); }
> > + (convert (absu:utype @0)))))
> >
> > /* Following match patterns are used by the match_spaceship function to
> > detect
> > all possible spaceship combinations. */
> > @@ -4960,7 +4962,13 @@
>
> Not enough context here
What we have here is:
(cmp) + (-cmp ^ x)
Where there might be no connection between x and cmp.
So if x is say INT_MIN, then x^-cmp can just be INT_MIN without any
overflow when cmp is 0 and then adding 0 to INT_MIN has no overflow.
I will revert the other parts of the patch and resubmit after
bootstrap/test (this is what I had originally and then I went looked
at the other patterns that were added and missed there was already an
overflow in those cases).
>
> > DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > (if (INTEGRAL_TYPE_P (type)
> > && !TYPE_SATURATING (type)
> > && (GIMPLE || !TREE_SIDE_EFFECTS (@0)))
> > - (cond (convert:boolean_type_node @1) (negate @0) @0)))
> > + /* Do the negate in unsigned type always; otherwise
> > + we would be introducing an overflow. */
> > + (with { tree utype = unsigned_type_for (type); }
> > + (cond
> > + (convert:boolean_type_node @1)
> > + (convert:type (negate (convert:utype @0)))
> > + @0))))
> >
> > /* Transform A & (B*cmp) into (A&B)*cmp. */
> > (simplify
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c
> > index dc7a450d3e8..829a214632d 100644
> > --- a/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr113894.c
> > @@ -58,6 +58,6 @@ unsigned f_unsigned_not_zero_one(unsigned x, unsigned cmp)
> > not known to be 0 or 1. */
> > /* { dg-final { scan-tree-dump-times " \\^ " 2 "forwprop1" } } */
> > /* Sign tests should expose absolute value. */
> > -/* { dg-final { scan-tree-dump-times " = ABS_EXPR" 2 "forwprop1" } } */
> > +/* { dg-final { scan-tree-dump-times " = ABSU_EXPR" 2 "forwprop1" } } */
> > /* Other zero-one predicates should expose conditional negation. */
> > /* { dg-final { scan-tree-dump-times " \\? " 5 "forwprop1" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr123514.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr123514.c
> > index 4a09d859031..ef2dde1804b 100644
> > --- a/gcc/testsuite/gcc.dg/tree-ssa/pr123514.c
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr123514.c
> > @@ -8,4 +8,4 @@ bit_trick (int x)
> > return ((x + mask) ^ mask);
> > }
> >
> > -/* { dg-final { scan-tree-dump "ABS_EXPR" "optimized" } } */
> > +/* { dg-final { scan-tree-dump "ABSU_EXPR " "optimized" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
> > new file mode 100644
> > index 00000000000..3714069b43f
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fdump-tree-forwprop1" } */
> > +
> > +int f_cmp_gt_commuted(int x, int y)
> > +{
> > + int cmp = x > y;
> > + return cmp + (-cmp ^ x);
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "\\(unsigned int\\) " 1 "forwprop1" }
> > } */
> > +/* { dg-final { scan-tree-dump-times "\\(int\\) " 1 "forwprop1" } } */
> > --
> > 2.43.0
> >