On Tue, May 19, 2026 at 2:20 PM Andrew Pinski
<[email protected]> wrote:
>
> On Tue, May 19, 2026 at 6:18 AM Avinal Kumar <[email protected]> wrote:
> >
> > The pattern X != C1 ? -X : C2 currently exits when C1 is
> > INT_MIN and the type doesn't wrap, because a signed negation
> > of INT_MIN is undefined behavior. But the whole expression is
> > well-defined, it is equivalent to (signed)(-(unsigned)X).
> >
> > Handle the wi::only_sign_bit_p case by emitting an unsigned
> > negate instead of giving up, copying what the abs pattern
> > already does for the same edge case.
> >
> > PR tree-optimization/125050
> >
> > gcc/ChangeLog:
> >
> > * match.pd: (X != C1 ? -X : C2): Handle C1 being INT_MIN
> > by emitting (signed)(-(unsigned)X) instead of bailing out.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.dg/pr125050.c: New test.
> > * gcc.dg/tree-ssa/phi-opt-50.c: New test.
> > * gcc.dg/tree-ssa/phi-opt-51.c: New test.
> >
> > Signed-off-by: Avinal Kumar <[email protected]>
> > ---
> > Build and ran full testsuite on AMD64 machine.
> >
> > Changes from v1:
> > Fixed the typo. Also found two whitespace issue, fixed them too.
> >
> > gcc/match.pd | 12 ++++++++----
> > gcc/testsuite/gcc.dg/pr125050.c | 13 +++++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/phi-opt-50.c | 21 +++++++++++++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/phi-opt-51.c | 21 +++++++++++++++++++++
> > 4 files changed, 63 insertions(+), 4 deletions(-)
> > create mode 100644 gcc/testsuite/gcc.dg/pr125050.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-50.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-51.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index ff13a07ea94..9fca662a2e4 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -6755,14 +6755,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > )
> > #endif
> >
> > -/* X != C1 ? -X : C2 simplifies to -X when -C1 == C2. */
> > +/* X != C1 ? -X : C2 simplifies to -X when -C1 == C2. Additionally,
> > + when C1 is the minimum signed value (e.g INT_MIN), -X would be
> > + undefined for signed types, so emit (signed)(-(unsigned)X) instead. */
> > (simplify
> > (cond (ne @0 INTEGER_CST@1) (negate@3 @0) INTEGER_CST@2)
> > (if (!TYPE_SATURATING (type)
> > - && (TYPE_OVERFLOW_WRAPS (type)
> > - || !wi::only_sign_bit_p (wi::to_wide (@1)))
> > && wi::eq_p (wi::neg (wi::to_wide (@1)), wi::to_wide (@2)))
> > - @3))
> > + (if (TYPE_OVERFLOW_WRAPS (type)
> > + || !wi::only_sign_bit_p (wi::to_wide (@1)))
> > + @3
> > + (with {tree utype = unsigned_type_for (TREE_TYPE (@0)); }
> > + (convert (negate (convert:utype @0)))))))
> >
> > /* X != C1 ? ~X : C2 simplifies to ~X when ~C1 == C2. */
> > (simplify
> > diff --git a/gcc/testsuite/gcc.dg/pr125050.c
> > b/gcc/testsuite/gcc.dg/pr125050.c
> > new file mode 100644
> > index 00000000000..cf73d200cd5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr125050.c
> > @@ -0,0 +1,13 @@
> > +/* PR tree-optimization/125050 */
> > +/* { dg-do compile } */
> > +/* { dg-options "O1 -fdump-tree-phiopt1" } */
I just noticed you missed the - in front of the O1 here too.
> > +
> > +int f(int a)
> > +{
> > + if (a == -__INT_MAX__ - 1)
> > + return -__INT_MAX__ - 1;
> > + return -a;
> > +}
> > +
> > +/* This should be converted to (int)(-(unsigned)a). */
> > +/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-50.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-50.c
> > new file mode 100644
> > index 00000000000..f386c25a61b
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-50.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O1 -fdump-tree-phiopt1" } */
> > +
> > +/* a == INT_MIN ? INT_MIN : -a simplifies to (int)(-(unsigned)a) */
> > +int f1(int a)
> > +{
> > + if (a == -__INT_MAX__ - 1)
> > + return -__INT_MAX__ - 1;
> > + return -a;
> > +}
> > +
> > +/* a != INT_MIN ? -a : INT_MIN simplifies to (int)(-(unsigned)a) */
> > +int f2(int a)
> > +{
> > + if (a != -__INT_MAX__ - 1)
> > + return -a;
> > + return -__INT_MAX__ - 1;
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "negate_expr" 2 "phiopt1" } } */
>
> This will fail since negate_expr won't match anywhere because you are
> not using the -raw option to the dump file.
>
> > +/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */
>
> But with -raw, then the above will work by accident. It should be
> matching "gimple_cond <".
>
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-51.c
> > b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-51.c
> > new file mode 100644
> > index 00000000000..952774e9840
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-51.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O1 -fdump-tree-phiopt1" } */
> > +
> > +/* Try the same pattern with different integer types. */
> > +
> > +short f_short(short a)
> > +{
> > + if (a == (short)(-__SHRT_MAX__ - 1))
> > + return -__SHRT_MAX__ - 1;
> > + return -a;
> > +}
> > +
> > +long long f_ll(long long a)
> > +{
> > + if (a == -__LONG_LONG_MAX__ - 1)
> > + return -__LONG_LONG_MAX__ - 1;
> > + return -a;
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "negate_expr" 2 "phiopt1" } } */
> > +/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */
>
> Likewise.
>
> With these 2 failures I am not very confident you tested the testcases
> and/or the patch.
>
> See
> http://54.172.246.49:9090/jobs/tcwg_gcc_check--master-arm-precommit/builds/10396/archive/artifacts/artifacts.precommit/notify/mail-body.txt
> also for other failures.
>
> Looks like gcc.dg/fold-condneg-2.c needs to be updated since we
> produce the correct result of casting to unsigned first.
>
> Thanks,
> Andrea
>
> > --
> > 2.54.0
> >