On 23/10/2025 14:55, Dhruv Chawla wrote:
> On 13/10/25 11:43, Dhruv Chawla wrote:
> > External email: Use caution opening links or attachments
> > 
> > 
> > On 06/10/25 15:14, Dhruv Chawla wrote:
> > > External email: Use caution opening links or attachments
> > > 
> > > 
> > > On 23/09/25 11:15, Dhruv Chawla wrote:
> > > > External email: Use caution opening links or attachments
> > > > 
> > > > 
> > > > On 18/08/25 21:31, [email protected] wrote:
> > > > > External email: Use caution opening links or attachments
> > > > > 
> > > > > 
> > > > > From: Dhruv Chawla <[email protected]>
> > > > > 
> > > > > This patch folds the following patterns:
> > > > > - umax (a, add (a, b)) -> [sum,  ovf] = adds (a, b); !ovf ? sum : a
> > > > > - umin (a, add (a, b)) -> [sum,  ovf] = adds (a, b); !ovf ? a : sum
> > > > > - umax (a, sub (a, b)) -> [diff, ovf] = subs (a, b); ovf ? diff : a
> > > > > - umin (a, sub (a, b)) -> [diff, ovf] = subs (a, b); ovf ? a : diff
> > > > > 
> > > > > Where ovf is the overflow flag. adds and subs are generated by
> > > > > generating a parallel compare+plus/minus which maps to the pattern
> > > > > add<mode>3_compareC. sub<mode>3_compareC is also created to have an
> > > > > equivalent pattern for the subs instruction. In the case of subs, the
> > > > > overflow flag represents underflow.
> > > > > 
> > > > > This patch is a respin of the patch posted at
> > > > > https://gcc.gnu.org/pipermail/gcc-patches/2025-May/685021.html as per
> > > > > the suggestion to turn it into a target-specific transform by Richard
> > > > > Biener.
> > > > > 
> > > > > Bootstrapped and regtested on aarch64-unknown-linux-gnu.
> > > > > 
> > > > > Signed-off-by: Dhruv Chawla <[email protected]>
> > > > > 
> > > > >          PR middle-end/116815
> > > > > 
> > > > > gcc/ChangeLog:
> > > > > 
> > > > >          * config/aarch64/aarch64.md (sub<mode>3_compareC): New 
> > > > > pattern.
> > > > >          (*aarch64_plus_within_<optab><mode>3_<ovf_commutate>): 
> > > > > Likewise.
> > > > >          (*aarch64_minus_within_<optab><mode>3): Likewise.
> > > > >          * config/aarch64/iterators.md (ovf_add_cmp): New code 
> > > > > attribute.
> > > > >          (ovf_sub_cmp): Likewise.
> > > > >          (ovf_commutate): New iterator.
> > > > >          (ovf_comm_opp): New int attribute.
> > > > > 
> > > > > gcc/testsuite/ChangeLog:
> > > > > 
> > > > >          * gcc.target/aarch64/pr116815-1.c: New test.
> > > > >          * gcc.target/aarch64/pr116815-2.c: Likewise.
> > > > >          * gcc.target/aarch64/pr116815-3.c: Likewise.
> > > > >          * gcc.target/aarch64/pr116815-4.c: Likewise.
> > > > >          * gcc.target/aarch64/pr116815-5.c: Likewise.
> > > > >          * gcc.target/aarch64/pr116815-6.c: Likewise.
> > > > > ---
> > > > >   gcc/config/aarch64/aarch64.md                 |  76 +++++++++++
> > > > >   gcc/config/aarch64/iterators.md               |   9 ++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-1.c | 120 
> > > > > ++++++++++++++++++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-2.c |  93 ++++++++++++++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-3.c |  62 +++++++++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-4.c |  48 +++++++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-5.c |  44 +++++++
> > > > >   gcc/testsuite/gcc.target/aarch64/pr116815-6.c |  60 +++++++++
> > > > >   8 files changed, 512 insertions(+)
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-1.c
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-2.c
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-3.c
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-4.c
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-5.c
> > > > >   create mode 100644 gcc/testsuite/gcc.target/aarch64/pr116815-6.c
> > > > > 
> > > > > diff --git a/gcc/config/aarch64/aarch64.md 
> > > > > b/gcc/config/aarch64/aarch64.md
> > > > > index 8e431a10cb1..a55fe5c85d8 100644
> > > > > --- a/gcc/config/aarch64/aarch64.md
> > > > > +++ b/gcc/config/aarch64/aarch64.md
> > > > > @@ -3715,6 +3715,20 @@
> > > > >     [(set_attr "type" "alus_sreg")]
> > > > >   )
> > > > > 
> > > > > +;; An equivalent to add<mode>3_compareC
> > > > > +(define_insn "sub<mode>3_compareC"
> > > > > +  [(set (reg:CC_C CC_REGNUM)
> > > > > +       (compare:CC_C
> > > > > +         (minus:GPI
> > > > > +           (match_operand:GPI 1 "register_operand" "r")
> > > > > +           (match_operand:GPI 2 "register_operand" "r"))
> > > > > +         (match_dup 1)))
> > > > > +   (set (match_operand:GPI 0 "register_operand" "=r")
> > > > > +       (minus:GPI (match_dup 1) (match_dup 2)))]
> > > > > +  ""
> > > > > +  "subs\t%<w>0, %<w>1, %<w>2"
> > > > > +)
> > > > > +
> > > > >   (define_peephole2
> > > > >     [(set (match_operand:GPI 0 "aarch64_general_reg")
> > > > >          (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero")
> > > > > @@ -4455,6 +4469,68 @@
> > > > >     [(set_attr "type" "<su>div")]
> > > > >   )
> > > > > 
> > > > > +;; umax (a, add (a, b)) => [sum, ovf] = adds (a, b); !ovf ? sum : a
> > > > > +;; umin (a, add (a, b)) => [sum, ovf] = adds (a, b); !ovf ? a : sum
> > > > > +;; ... along with the commutative version of add (a, b) i.e. add (b, 
> > > > > a).
> > > > > +(define_insn_and_split 
> > > > > "*aarch64_plus_within_<optab><mode>3_<ovf_commutate>"
> > > > > +  [(set (match_operand:GPI 0 "register_operand" "=r")
> > > > > +       (UMAXMIN:GPI
> > > > > +         (plus:GPI (match_operand:GPI 1 "register_operand" "r")
> > > > > +                   (match_operand:GPI 2 "register_operand" "r"))
> > > > > +         (match_dup ovf_commutate)))
> > > > > +   (clobber (match_scratch:GPI 3))]
> > > > > +  "!TARGET_CSSC"
> > > > > +  "#"
> > > > > +  "&& !reload_completed"
> > > > > +  [(parallel
> > > > > +      [(set (reg:CC_C CC_REGNUM)
> > > > > +           (compare:CC_C (plus:GPI (match_dup ovf_commutate)
> > > > > +                                   (match_dup <ovf_comm_opp>))
> > > > > +                         (match_dup ovf_commutate)))
> > > > > +       (set (match_dup 3) (plus:GPI (match_dup ovf_commutate)
> > > > > +                                   (match_dup <ovf_comm_opp>)))])
> > > > > +   (set (match_dup 0)
> > > > > +       (if_then_else:GPI (<ovf_add_cmp> (reg:CC_C CC_REGNUM)
> > > > > +                                        (const_int 0))
> > > > > +                         (match_dup 3)
> > > > > +                         (match_dup ovf_commutate)))]
> > > > > +  {
> > > > > +    if (GET_CODE (operands[3]) == SCRATCH)
> > > > > +      operands[3] = gen_reg_rtx (<MODE>mode);
> > > > > +  }
> > > > > +)
> > > > > +
> > > > > +;; In this case the ovf represents an underflow.
> > > > > +;; umax (a, sub (a, b)) => [diff, ovf] = subs (a, b); ovf ? diff : a
> > > > > +;; umin (a, sub (a, b)) => [diff, ovf] = subs (a, b); ovf ? a : diff
> > > > > +(define_insn_and_split "*aarch64_minus_within_<optab><mode>3"
> > > > > +  [(set (match_operand:GPI 0 "register_operand" "=r")
> > > > > +       (UMAXMIN:GPI
> > > > > +         (minus:GPI (match_operand:GPI 1 "register_operand" "r")
> > > > > +                    (match_operand:GPI 2 "register_operand" "r"))
> > > > > +         (match_dup 1)))
> > > > > +   (clobber (match_scratch:GPI 3))]
> > > > > +  "!TARGET_CSSC"
> > > > > +  "#"
> > > > > +  "&& !reload_completed"
> > > > > +  [(parallel
> > > > > +      [(set (reg:CC_C CC_REGNUM)
> > > > > +           (compare:CC_C (minus:GPI (match_dup 1) (match_dup 2))
> > > > > +                         (match_dup 1)))
> > > > > +       (set (match_dup 3) (minus:GPI (match_dup 1) (match_dup 2)))])
> > > > > +   ;; There is an inverse mapping here from CC_C -> CC as this 
> > > > > requires the
> > > > > +   ;; inverse of the comparison from the above pattern.
> > > > > +   (set (match_dup 0)
> > > > > +           (if_then_else:GPI (<ovf_sub_cmp> (reg:CC CC_REGNUM)
> > > > > +                                               (const_int 0))
> > > > > +                             (match_dup 3)
> > > > > +                             (match_dup 1)))]
> > > > > +  {
> > > > > +    if (GET_CODE (operands[3]) == SCRATCH)
> > > > > +      operands[3] = gen_reg_rtx (<MODE>mode);
> > > > > +  }
> > > > > +)
> > > > > +
> > > > >   ;; 
> > > > > -------------------------------------------------------------------
> > > > >   ;; Comparison insns
> > > > >   ;; 
> > > > > -------------------------------------------------------------------
> > > > > diff --git a/gcc/config/aarch64/iterators.md 
> > > > > b/gcc/config/aarch64/iterators.md
> > > > > index c3771d9402b..a29243247bd 100644
> > > > > --- a/gcc/config/aarch64/iterators.md
> > > > > +++ b/gcc/config/aarch64/iterators.md
> > > > > @@ -2804,6 +2804,8 @@
> > > > > 
> > > > >   (define_code_iterator FMAXMIN [smax smin])
> > > > > 
> > > > > +(define_code_iterator UMAXMIN [umax umin])
> > > > > +
> > > > >   ;; Signed and unsigned max operations.
> > > > >   (define_code_iterator USMAX [smax umax])
> > > > > 
> > > > > @@ -3092,6 +3094,9 @@
> > > > > 
> > > > >   (define_code_attr maxminand [(smax "bic") (smin "and")])
> > > > > 
> > > > > +(define_code_attr ovf_add_cmp [(umax "geu") (umin "ltu")])
> > > > > +(define_code_attr ovf_sub_cmp [(umax "ltu") (umin "geu")])
> > > > > +
> > > > >   ;; MLA/MLS attributes.
> > > > >   (define_code_attr as [(ss_plus "a") (ss_minus "s")])
> > > > > 
> > > > > @@ -5007,3 +5012,7 @@
> > > > >      (UNSPEC_F2CVT "f2cvt")
> > > > >      (UNSPEC_F1CVTLT "f1cvtlt")
> > > > >      (UNSPEC_F2CVTLT "f2cvtlt")])
> > > > > +
> > > > > +;; Operand numbers for commutative operations
> > > > > +(define_int_iterator ovf_commutate [1 2])
> > > > > +(define_int_attr ovf_comm_opp [(1 "2") (2 "1")])
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-1.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-1.c
> > > > > new file mode 100644
> > > > > index 00000000000..f3bdb794318
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-1.c
> > > > > @@ -0,0 +1,120 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +/* { dg-final { check-function-bodies "**" "" "" } } */
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Single-use tests.  */
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +max (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +min (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +#define OPERATION(op, type, N, exp1, exp2)                           
> > > > >           \
> > > > > +  unsigned u##op##type##N (unsigned a, unsigned b) { return op 
> > > > > (exp1, exp2); }
> > > > > +
> > > > > +/*
> > > > > +** umaxadd1:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, add, 1, a, a + b)
> > > > > +
> > > > > +/*
> > > > > +** umaxadd2:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, add, 2, a, b + a)
> > > > > +
> > > > > +/*
> > > > > +** umaxadd3:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, add, 3, a + b, a)
> > > > > +
> > > > > +/*
> > > > > +** umaxadd4:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, add, 4, b + a, a)
> > > > > +
> > > > > +/*
> > > > > +** uminadd1:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, add, 1, a, a + b)
> > > > > +
> > > > > +/*
> > > > > +** uminadd2:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, add, 2, a, b + a)
> > > > > +
> > > > > +/*
> > > > > +** uminadd3:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, add, 3, a + b, a)
> > > > > +
> > > > > +/*
> > > > > +** uminadd4:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, add, 4, b + a, a)
> > > > > +
> > > > > +/* sub requires the inverse of the comparison from add.  */
> > > > > +
> > > > > +/*
> > > > > +** umaxsub1:
> > > > > +**     subs    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, sub, 1, a, a - b)
> > > > > +
> > > > > +/*
> > > > > +** umaxsub2:
> > > > > +**     subs    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cc
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (max, sub, 2, a - b, a)
> > > > > +
> > > > > +/*
> > > > > +** uminsub1:
> > > > > +**     subs    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, sub, 1, a, a - b)
> > > > > +
> > > > > +/*
> > > > > +** uminsub2:
> > > > > +**     subs    (w[0-9]+), w0, w1
> > > > > +**     csel    w0, \1, w0, cs
> > > > > +**     ret
> > > > > +*/
> > > > > +OPERATION (min, sub, 2, a - b, a)
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-2.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-2.c
> > > > > new file mode 100644
> > > > > index 00000000000..f2dd7b0bbb3
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-2.c
> > > > > @@ -0,0 +1,93 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Negative tests.  */
> > > > > +
> > > > > +static inline int __attribute__ ((always_inline))
> > > > > +smax (int a, int b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline int __attribute__ ((always_inline))
> > > > > +smin (int a, int b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +umax (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +umin (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +#define ASSUME(cond) if (!(cond)) __builtin_unreachable ();
> > > > > +
> > > > > +/* This transformation does not trigger on signed types.  */
> > > > > +
> > > > > +int
> > > > > +smax_add (int a, int b)
> > > > > +{
> > > > > +  ASSUME (b >= 0);
> > > > > +  return smax (a, a + b);
> > > > > +}
> > > > > +
> > > > > +int
> > > > > +smin_add (int a, int b)
> > > > > +{
> > > > > +  ASSUME (b >= 0);
> > > > > +  return smin (a, a + b);
> > > > > +}
> > > > > +
> > > > > +int
> > > > > +smax_sub (int a, int b)
> > > > > +{
> > > > > +  ASSUME (b >= 0);
> > > > > +  return smax (a, a - b);
> > > > > +}
> > > > > +
> > > > > +int
> > > > > +smin_sub (int a, int b)
> > > > > +{
> > > > > +  ASSUME (b >= 0);
> > > > > +  return smin (a, a - b);
> > > > > +}
> > > > > +
> > > > > +/* Invalid patterns.  */
> > > > > +
> > > > > +/* This can potentially be matched, but the RHS gets factored to
> > > > > +   (a + b) * b.  */
> > > > > +unsigned
> > > > > +umax_factored (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return umax (a * b, a * b + b * b);
> > > > > +}
> > > > > +
> > > > > +unsigned
> > > > > +umin_mult (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return umin (a, a * b);
> > > > > +}
> > > > > +
> > > > > +unsigned
> > > > > +umax_sub (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return umax (a, b - a);
> > > > > +}
> > > > > +
> > > > > +unsigned
> > > > > +umin_sub (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return umin (a, b - a);
> > > > > +}
> > > > > +
> > > > > +/* { dg-final { scan-assembler-not "adds\\t" } } */
> > > > > +/* { dg-final { scan-assembler-not "subs\\t" } } */
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-3.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-3.c
> > > > > new file mode 100644
> > > > > index 00000000000..f8050377116
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-3.c
> > > > > @@ -0,0 +1,62 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +/* { dg-final { check-function-bodies "**" "" "" } } */
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Multi-use tests.  */
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +max (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +min (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +/* FIXME: This should only generate one adds.  */
> > > > > +
> > > > > +/*
> > > > > +** umax_add_umin_add:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    \1, \1, w0, cc
> > > > > +**     adds    (w[0-9]+), w1, w0
> > > > > +**     csel    w0, \2, w1, cs
> > > > > +**     add     w0, \1, \2
> > > > > +**     ret
> > > > > +*/
> > > > > +unsigned
> > > > > +umax_add_umin_add (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return max (a, a + b) + min (a + b, b);
> > > > > +}
> > > > > +
> > > > > +/*
> > > > > +** umin_add_umax_add:
> > > > > +**     adds    (w[0-9]+), w0, w1
> > > > > +**     csel    \1, \1, w0, cs
> > > > > +**     adds    (w[0-9]+), w1, w0
> > > > > +**     csel    \2, \2, w1, cc
> > > > > +**     add     w0, \1, \2
> > > > > +**     ret
> > > > > +*/
> > > > > +unsigned
> > > > > +umin_add_umax_add (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return min (a, b + a) + max (b + a, b);
> > > > > +}
> > > > > +
> > > > > +/* FIXME: This pattern does not get optimized.  */
> > > > > +
> > > > > +unsigned
> > > > > +multiple_paths (unsigned a, unsigned b)
> > > > > +{
> > > > > +  if (a > 5)
> > > > > +    return max (a, a + b);
> > > > > +  else
> > > > > +    return min (a, a + b);
> > > > > +}
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-4.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-4.c
> > > > > new file mode 100644
> > > > > index 00000000000..c1be921334b
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-4.c
> > > > > @@ -0,0 +1,48 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Single-use tests with a use of the min-max in an if-condition.  */
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +max (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +min (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +#define OPERATION(op, type, N, exp1, exp2)                           
> > > > >           \
> > > > > +  unsigned u##op##type##N (unsigned a, unsigned b, unsigned c, 
> > > > > unsigned d,     \
> > > > > +                          unsigned e)                                
> > > > >          \
> > > > > +  {                                                                  
> > > > >           \
> > > > > +    unsigned result = op (exp1, exp2);                               
> > > > >           \
> > > > > +    if (result == c || result == c * 2)                              
> > > > >           \
> > > > > +      return d;                                                      
> > > > >           \
> > > > > +    else                                                             
> > > > >           \
> > > > > +      return e;                                                      
> > > > >           \
> > > > > +  }
> > > > > +
> > > > > +OPERATION (max, add, 1, a, a + b)
> > > > > +OPERATION (max, add, 2, a, b + a)
> > > > > +OPERATION (max, add, 3, a + b, a)
> > > > > +OPERATION (max, add, 4, b + a, a)
> > > > > +
> > > > > +OPERATION (min, add, 1, a, a + b)
> > > > > +OPERATION (min, add, 2, a, b + a)
> > > > > +OPERATION (min, add, 3, a + b, a)
> > > > > +OPERATION (min, add, 4, b + a, a)
> > > > > +
> > > > > +OPERATION (max, sub, 1, a, a - b)
> > > > > +OPERATION (max, sub, 2, a - b, a)
> > > > > +
> > > > > +OPERATION (min, sub, 1, a, a - b)
> > > > > +OPERATION (min, sub, 2, a - b, a)
> > > > > +
> > > > > +/* { dg-final { scan-assembler-times "adds\\t" 8 } } */
> > > > > +/* { dg-final { scan-assembler-times "subs\\t" 4 } } */
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-5.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-5.c
> > > > > new file mode 100644
> > > > > index 00000000000..015c868aec2
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-5.c
> > > > > @@ -0,0 +1,44 @@
> > > > > +/* { dg-do compile } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +
> > > > > +#pragma GCC target "+cssc"
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Make sure that umax/umin instructions are generated with CSSC.  */
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +max (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a > b ? a : b;
> > > > > +}
> > > > > +
> > > > > +static inline unsigned __attribute__ ((always_inline))
> > > > > +min (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return a < b ? a : b;
> > > > > +}
> > > > > +
> > > > > +#define OPERATION(op, type, N, exp1, exp2)                           
> > > > >           \
> > > > > +  unsigned u##op##type##N (unsigned a, unsigned b) { return op 
> > > > > (exp1, exp2); }
> > > > > +
> > > > > +OPERATION (max, add, 1, a, a + b)
> > > > > +OPERATION (max, add, 2, a, b + a)
> > > > > +OPERATION (max, add, 3, a + b, a)
> > > > > +OPERATION (max, add, 4, b + a, a)
> > > > > +
> > > > > +OPERATION (min, add, 1, a, a + b)
> > > > > +OPERATION (min, add, 2, a, b + a)
> > > > > +OPERATION (min, add, 3, a + b, a)
> > > > > +OPERATION (min, add, 4, b + a, a)
> > > > > +
> > > > > +OPERATION (max, sub, 1, a, a - b)
> > > > > +OPERATION (max, sub, 2, a - b, a)
> > > > > +
> > > > > +OPERATION (min, sub, 1, a, a - b)
> > > > > +OPERATION (min, sub, 2, a - b, a)
> > > > > +
> > > > > +/* { dg-final { scan-assembler-times "umax\\t" 6 } } */
> > > > > +/* { dg-final { scan-assembler-times "umin\\t" 6 } } */
> > > > > +/* { dg-final { scan-assembler-not "adds\\t" } } */
> > > > > +/* { dg-final { scan-assembler-not "subs\\t" } } */
> > > > > diff --git a/gcc/testsuite/gcc.target/aarch64/pr116815-6.c 
> > > > > b/gcc/testsuite/gcc.target/aarch64/pr116815-6.c
> > > > > new file mode 100644
> > > > > index 00000000000..2b5407bcfc2
> > > > > --- /dev/null
> > > > > +++ b/gcc/testsuite/gcc.target/aarch64/pr116815-6.c
> > > > > @@ -0,0 +1,60 @@
> > > > > +/* { dg-do run } */
> > > > > +/* { dg-options "-O2" } */
> > > > > +
> > > > > +/* PR middle-end/116815 */
> > > > > +
> > > > > +/* Verify that the transformation gives correct results */
> > > > > +
> > > > > +[[gnu::always_inline]]
> > > > > +inline unsigned min (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return (a < b) ? a : b;
> > > > > +}
> > > > > +
> > > > > +[[gnu::always_inline]]
> > > > > +inline unsigned max (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return (a > b) ? a : b;
> > > > > +}
> > > > > +
> > > > > +[[gnu::noipa]] unsigned
> > > > > +umaxadd (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return max (a + b, a);
> > > > > +}
> > > > > +
> > > > > +[[gnu::noipa]] unsigned
> > > > > +umaxsub (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return max (a - b, a);
> > > > > +}
> > > > > +
> > > > > +[[gnu::noipa]] unsigned
> > > > > +uminadd (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return min (a + b, a);
> > > > > +}
> > > > > +
> > > > > +[[gnu::noipa]] unsigned
> > > > > +uminsub (unsigned a, unsigned b)
> > > > > +{
> > > > > +  return min (a - b, a);
> > > > > +}
> > > > > +
> > > > > +int
> > > > > +main ()
> > > > > +{
> > > > > +  /* Overflows to 0x30000000.  */
> > > > > +  if (umaxadd (0x90000000, 0xa0000000) != 0x90000000)
> > > > > +    __builtin_abort ();
> > > > > +
> > > > > +  if (uminadd (0x90000000, 0xa0000000) != 0x30000000)
> > > > > +    __builtin_abort ();
> > > > > +
> > > > > +  /* Underflows to 0x60000000.  */
> > > > > +  if (umaxsub (0x00000000, 0xa0000000) != 0x60000000)
> > > > > +    __builtin_abort ();
> > > > > +
> > > > > +  if (uminsub (0x00000000, 0xa0000000) != 0x00000000)
> > > > > +    __builtin_abort ();
> > > > > +}
> > > > > -- 
> > > > > 2.44.0
> > > > > 
> > > > 
> > > > Ping 
> > > > (https://gcc.gnu.org/pipermail/gcc-patches/2025-August/692789.html).
> > > > 
> > > > -- 
> > > > Regards,
> > > > Dhruv
> > > 
> > > Ping (https://gcc.gnu.org/pipermail/gcc-patches/2025-August/692789.html).
> > > 
> > > -- 
> > > Regards,
> > > Dhruv
> > 
> > Ping (https://gcc.gnu.org/pipermail/gcc-patches/2025-August/692789.html).
> > 
> > -- 
> > Regards,
> > Dhruv
> 
> Ping (https://gcc.gnu.org/pipermail/gcc-patches/2025-August/692789.html).

Hi Dhruv,

Sorry for the long wait on this, I'm taking a look and this now and will
aim to get back to you in the next day or two.

Thanks,
Alex

> 
> -- 
> Regards,
> Dhruv

Reply via email to