Re: [PATCH 1/2] match.pd: recognise A > B ? A - B : B - A as abs (A - B) [PR50856]

Andrea Pinski <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CALvbMcDULCeuqMfzi9UrQPXmg-6bXeWtTA89Khb=VF2k27yhAg@mail.gmail.com>
On Wed, Aug 19, 2026 at 1:10 AM Richard Biener <[email protected]> wrote:
>
> On Tue, 18 Aug 2026, Andrea Pinski wrote:
>
> > On Tue, Aug 18, 2026 at 12:55 PM Dominic P <[email protected]> wrote:
> > >
> > > The absolute-difference idiom is already folded to abs (A - B) when the
> > > comparison is written against the subtraction itself, e.g.
> > > (A - B) > 0 ? (A - B) : (B - A).  The very common alternative spelling that
> > > compares the operands directly, A > B ? A - B : B - A, was not recognised, so
> > > phiopt kept two independent subtractions which the backend if-converted into a
> > > compare plus two predicated subtracts (three instructions on Arm) instead of
> > > the two-instruction "subs; rsb<cc>" abs sequence.
> > >
> > > For a signed, non-wrapping integer type A > B is equivalent to A - B > 0, so the
> > > idiom (and its >=, < and <= variants) folds to [-]abs (A - B).  Add the two
> > > simplifications next to the existing (A - B) cmp 0 family, guarded on
> > > !TYPE_OVERFLOW_WRAPS so that -fwrapv does not trigger the fold.
> > >
> > > As a two-patch series with the following widened-operand extension,
> > > bootstrapped on x86_64-pc-linux-gnu with the stage2/stage3 comparison
> > > successful, and regtested there with gcc.dg/dg.exp and
> > > gcc.dg/tree-ssa/tree-ssa.exp: no unexpected results.
> >
> > Couple of things. First Eikansh posted a patch less than a month ago
> > for this which was under review too:
> > https://inbox.sourceware.org/gcc-patches/[email protected]/T/#m31fbbf878192412099d1c0c9ae066bccc519fb44
> >
> > >
> > > Assisted-by: Claude Opus 5 (Anthropic)
> >
> > Second I think GCC really should have a policy of rejecting patches
> > using LLMs for easy issues. LLVM already has a similar policy. So this
> > should not be so controversial. The main reason is these easy issues
> > are here for learning GCC code base.
>
> True, though I somewhat lean towards progress is better than having
> (easy) bugs.
Progress is hard to measure though. Progress in learning how to
maintain and review and such is just as important as progress in code
generation improvements :).


 > Even with using LLMs this can be a learning process - it
> really depends what "Assisted-by: Claude Opus 5" actually means
> and I'd welcome some more elaboration on such annotations from
> contributors.
>
> > Also our current policy about LLMs can be found at
> > https://gcc.gnu.org/ai-policy.html ; it does not cover easy issues
> > currently. But it seems like we are in a need of one here considering
> > most of the easy issues are going to be small enough.
> >
> > The other thing is I think you should mention which parts were
> > assisted by the LLM; was only the testcases or the whole thing?
> > Our current policy suggest we can only legally insignificant
> > contributions but the GNU policy on legally significant says:
> > "Keep in mind, however, that a series of minor changes by the same
> > person can add up to a significant contribution."
> > So I am not sure if after say one or 2 patches using LLMs for the
> > match patterns can be accepted any more from the same person. This is
> > the vague part of the policy which does need clarifications.
>
> Why should it only become legally significant if it's from the same
> person (or same LLM?) or to the same file?  In the extreme it should
> be multiple LLM contributions to GCC as-whole add up, and I guess
> we're way past a "legally insignificant" threshold there, if you
> think -- narrowed to copyright -- that patches like this would ever
> be able to infringe on somebody elses copyright (not being
> copyrightable should not be a problem).
>
> Richard.
>
> >
> > Thanks,
> > Andrea
> >
> >
> > >
> > >         PR tree-optimization/50856
> > >
> > > gcc/ChangeLog:
> > >
> > >         * match.pd: Fold A > B ? A - B : B - A (and the >=, < and <=
> > >         spellings) into [-]abs (A - B) for signed non-wrapping integer
> > >         types.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >         * gcc.target/arm/pr50856.c: New test.
> > >         * gcc.dg/tree-ssa/absdiff-1.c: New test.
> > >
> > > Signed-off-by: Dominic P <[email protected]>
> > > ---
> > >  gcc/match.pd                              | 26 +++++++++++++++++
> > >  gcc/testsuite/gcc.dg/tree-ssa/absdiff-1.c | 12 ++++++++
> > >  gcc/testsuite/gcc.target/arm/pr50856.c    | 35 +++++++++++++++++++++++
> > >  3 files changed, 73 insertions(+)
> > >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/absdiff-1.c
> > >  create mode 100644 gcc/testsuite/gcc.target/arm/pr50856.c
> > >
> > > diff --git a/gcc/match.pd b/gcc/match.pd
> > > index 18d295ad4cb..04ddb82c76e 100644
> > > --- a/gcc/match.pd
> > > +++ b/gcc/match.pd
> > > @@ -7601,6 +7601,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > >        (convert (negate (absu:utype @0))))
> > >        (negate (abs @0)))))
> > >   )
> > > + /* A > B ? A - B : B - A   and   A >= B ? A - B : B - A
> > > +    same as abs (A - B) for signed non-wrapping types, where the
> > > +    no-overflow assumption gives A > B <=> A - B > 0.  (PR50856)  */
> > > + (for cmp (gt ge)
> > > +  (simplify
> > > +   (cnd (cmp @1 @2) (minus@0 @1 @2) (minus @2 @1))
> > > +   (if (!HONOR_SIGNED_ZEROS (type)
> > > +       && !TYPE_UNSIGNED (type)
> > > +       && ANY_INTEGRAL_TYPE_P (type)
> > > +       && !TYPE_OVERFLOW_WRAPS (type)
> > > +       && (!VECTOR_TYPE_P (type)
> > > +           || target_supports_op_p (type, ABS_EXPR, optab_vector)))
> > > +    (abs @0))))
> > > + /* A < B ? A - B : B - A   and   A <= B ? A - B : B - A
> > > +    same as -abs (A - B) for signed non-wrapping types.  (PR50856)  */
> > > + (for cmp (lt le)
> > > +  (simplify
> > > +   (cnd (cmp @1 @2) (minus@0 @1 @2) (minus @2 @1))
> > > +   (if (!HONOR_SIGNED_ZEROS (type)
> > > +       && !TYPE_UNSIGNED (type)
> > > +       && ANY_INTEGRAL_TYPE_P (type)
> > > +       && !TYPE_OVERFLOW_WRAPS (type)
> > > +       && (!VECTOR_TYPE_P (type)
> > > +           || (target_supports_op_p (type, ABS_EXPR, optab_vector)
> > > +               && target_supports_op_p (type, NEGATE_EXPR, optab_vector))))
> > > +    (negate (abs @0)))))
> > >  )
> > >
> > >  /* X >=/> 0 ? Y + X : Y - X
> > > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/absdiff-1.c b/gcc/testsuite/gcc.dg/tree-ssa/absdiff-1.c
> > > new file mode 100644
> > > index 00000000000..4d59b93429b
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.dg/tree-ssa/absdiff-1.c
> > > @@ -0,0 +1,12 @@
> > > +/* A > B ? A - B : B - A folds to abs (A - B) for signed non-wrapping
> > > +   operands, in all four comparison directions.  PR50856.  */
> > > +/* { dg-do compile } */
> > > +/* { dg-options "-O2 -fdump-tree-optimized" } */
> > > +
> > > +int ad_gt (int a, int b) { return a > b ? a - b : b - a; }
> > > +int ad_ge (int a, int b) { return a >= b ? a - b : b - a; }
> > > +long ad_lt (long a, long b) { return a < b ? a - b : b - a; }
> > > +int ad_le (int a, int b) { return a <= b ? a - b : b - a; }
> > > +
> > > +/* { dg-final { scan-tree-dump-times "ABS_EXPR" 4 "optimized" } } */
> > > +/* { dg-final { scan-tree-dump-times "= -" 2 "optimized" } } */
> > > diff --git a/gcc/testsuite/gcc.target/arm/pr50856.c b/gcc/testsuite/gcc.target/arm/pr50856.c
> > > new file mode 100644
> > > index 00000000000..adae32b09ea
> > > --- /dev/null
> > > +++ b/gcc/testsuite/gcc.target/arm/pr50856.c
> > > @@ -0,0 +1,35 @@
> > > +/* PR tree-optimization/50856: the signed absolute-difference idiom
> > > +   a > b ? a - b : b - a  (and the >=, and the mirror < / <= giving
> > > +   -abs) should be recognised as ABS_EXPR (a - b) so the ARM backend
> > > +   emits the 2-instruction "subs; rsb<cc>" sequence instead of a
> > > +   compare followed by two predicated subtracts.  */
> > > +
> > > +/* { dg-do compile } */
> > > +/* { dg-options "-O2 -marm" } */
> > > +/* { dg-require-effective-target arm32 } */
> > > +/* { dg-final { scan-tree-dump-times "ABS_EXPR" 3 "optimized" } } */
> > > +/* { dg-additional-options "-fdump-tree-optimized" } */
> > > +
> > > +int
> > > +absdiff_gt (int a, int b)
> > > +{
> > > +  return a > b ? a - b : b - a;
> > > +}
> > > +
> > > +int
> > > +absdiff_ge (int a, int b)
> > > +{
> > > +  return a >= b ? a - b : b - a;
> > > +}
> > > +
> > > +long
> > > +labsdiff_gt (long a, long b)
> > > +{
> > > +  return a > b ? a - b : b - a;
> > > +}
> > > +
> > > +/* The abs sequence is "subs rN, ..; rsb<cc> rN, rN, #0"; make sure we
> > > +   no longer emit the compare + two predicated subtracts form.  */
> > > +/* { dg-final { scan-assembler-not "subgt" } } */
> > > +/* { dg-final { scan-assembler-not "suble" } } */
> > > +/* { dg-final { scan-assembler "rsb" } } */
> > > --
> > > 2.55.0
> > >
> >
>
> --
> Richard Biener <[email protected]>
> SUSE Software Solutions Germany GmbH,
> Frankenstrasse 146, 90461 Nuernberg, Germany;
> GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.