On Fri, Aug 21, 2026 at 1:34 AM Richard Biener <[email protected]> wrote:
>
> On Thu, 20 Aug 2026, [email protected] wrote:
>
> > From: Kyrylo Tkachov <[email protected]>
> >
> > The A - B -> A + (-B) rule uses negate_expr_p to decide whether B can be
> > negated cheaply.  The predicate rejects non-wrapping integral vector
> > constants, even when every encoded element can be negated without overflow.
> > This leaves vector subtraction in a noncanonical form and can hide an
> > encodable constant from target expansion.
> >
> >   typedef int v4si __attribute__ ((vector_size (16)));
> >
> >   v4si
> >   f (v4si x)
> >   {
> >     return x - (v4si) { -16711935, -16711935, -16711935, -16711935 };
> >   }
> >
> > aarch64 -O2 before:
> >
> >   f:
> >           adrp    x0, .LC0
> >           ldr     q31, [x0, #:lo12:.LC0]
> >           sub     v0.4s, v0.4s, v31.4s
> >           ret
> >
> > The function also needs a 16-byte constant in .rodata.
> >
> > After:
> >
> >   f:
> >           movi    v31.8h, 0xff
> >           add     v0.4s, v0.4s, v31.4s
> >           ret
> >
> > Accept a non-stepped integral vector constant when every encoded element can
> > be negated without overflow.  A stepped encoding can extrapolate an 
> > unencoded
> > signed minimum, so keep it in subtraction form.  Unsigned and -fwrapv 
> > vectors
> > already wrap and do not need an element scan.  Use vector-aware predicates
> > directly.  Keep the integral type check before TYPE_OVERFLOW_WRAPS because
> > fixed-point vectors can reach the predicate, but TYPE_OVERFLOW_WRAPS does 
> > not
> > accept them.  Keep a signed minimum element and an overflow-sanitized
> > subtraction.
> >
> > The canonical form remains visible before dead-code elimination in one
> > existing forwprop dump.  Adjust its addition count.
> >
> > Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-pc-linux-gnu.
> > Ok for trunk?
>
> See Andrews comments.  I'll add here that for REAL_CST we attempt to
> canonicalize to positive constants, so x + -5.0 -> x - 5.0 to
> optimize constant pool size.  Most vector constants are going to
> be materialized from the constant pool as well.  Not to say that
> this of course should not stand in the way of canonicalization
> but instead should possibly be applied late.

Just to come back to this discussion, I found the bug report which had
recorded this about vectors:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92436 .

Thanks,
Andrea

>
> Richard.
>
> > Thanks,
> > Kyrill
> >
> > gcc/ChangeLog:
> >
> >       * match.pd (negate_expr_p): Handle non-wrapping integral vector
> >       constants.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * gcc.dg/tree-ssa/forwprop-27.c: Adjust the expected addition count.
> >       * gcc.dg/tree-ssa/vector-sub-const-1.c: New test.
> >       * gcc.dg/tree-ssa/vector-sub-const-2.c: Likewise.
> >
> > Signed-off-by: Kyrylo Tkachov <[email protected]>
> > ---
> >  gcc/match.pd                                  | 27 ++++++++++--
> >  gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c   |  2 +-
> >  .../gcc.dg/tree-ssa/vector-sub-const-1.c      | 43 +++++++++++++++++++
> >  .../gcc.dg/tree-ssa/vector-sub-const-2.c      | 12 ++++++
> >  4 files changed, 80 insertions(+), 4 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index eae8717bcfe..e41f4c19bf4 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -2428,11 +2428,32 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> >  (match negate_expr_p
> >   REAL_CST
> >   (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (t)))))
> > -/* VECTOR_CST handling of non-wrapping types would recurse in unsupported
> > -   ways.  */
> > +/* A non-stepped, non-wrapping integral vector constant can be negated when
> > +   none of its encoded elements is the minimum value.  */
> >  (match negate_expr_p
> >   VECTOR_CST
> > - (if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))))
> > + (with
> > +  {
> > +    bool negatable = (FLOAT_TYPE_P (type)
> > +                   || (ANY_INTEGRAL_TYPE_P (type)
> > +                       && TYPE_OVERFLOW_WRAPS (type)));
> > +    if (!negatable
> > +     && ANY_INTEGRAL_TYPE_P (type)
> > +     && !TYPE_OVERFLOW_SANITIZED (type)
> > +     && !VECTOR_CST_STEPPED_P (t))
> > +      {
> > +     negatable = true;
> > +     for (unsigned int i = 0; i < vector_cst_encoded_nelts (t); ++i)
> > +       if (TREE_CODE (VECTOR_CST_ENCODED_ELT (t, i)) != INTEGER_CST
> > +           || !may_negate_without_overflow_p
> > +                (VECTOR_CST_ENCODED_ELT (t, i)))
> > +         {
> > +           negatable = false;
> > +           break;
> > +         }
> > +      }
> > +  }
> > +  (if (negatable))))
> >  (match negate_expr_p
> >   (minus @0 @1)
> >   (if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
> > index 6c71a4fc81c..29d39c67c79 100644
> > --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
> > @@ -33,7 +33,7 @@ void i (V *v1, V *v2){
> >    *v2 = (c1-*v2)+c2;
> >  }
> >
> > -/* { dg-final { scan-tree-dump-times "\\\+" 1 "forwprop1"} } */
> > +/* { dg-final { scan-tree-dump-times "\\\+" 2 "forwprop1"} } */
> >  /* { dg-final { scan-tree-dump "{ 0, 4 }" "forwprop1"} } */
> >  /* { dg-final { scan-tree-dump "{ 37, -5 }" "forwprop1"} } */
> >  /* { dg-final { scan-tree-dump "{ 27, 23 }" "forwprop1"} } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
> > new file mode 100644
> > index 00000000000..56e1c146d70
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-1.c
> > @@ -0,0 +1,43 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -Wno-psabi -fdump-tree-forwprop1" } */
> > +
> > +typedef __INT32_TYPE__ v4si __attribute__ ((vector_size (16)));
> > +typedef __UINT32_TYPE__ v4ui __attribute__ ((vector_size (16)));
> > +
> > +v4si
> > +sub_splat (v4si x)
> > +{
> > +  return x - (v4si) { 1, 1, 1, 1 };
> > +}
> > +
> > +v4si
> > +sub_mixed (v4si x)
> > +{
> > +  return x - (v4si) { 1, -2, 3, -4 };
> > +}
> > +
> > +v4si
> > +sub_encodable (v4si x)
> > +{
> > +  return x - (v4si) { -16711935, -16711935, -16711935, -16711935 };
> > +}
> > +
> > +v4si
> > +keep_min (v4si x)
> > +{
> > +  return x - (v4si) { -__INT32_MAX__ - 1, 1, 1, 1 };
> > +}
> > +
> > +v4si
> > +keep_stepped_min (v4si x)
> > +{
> > +  return x - (v4si) ((v4ui) { 2147483644u, 2147483645u,
> > +                            2147483646u, 2147483647u }
> > +                   + (v4ui) { 1, 1, 1, 1 });
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times " \\+ \\{ -1, -1, -1, -1 \\}" 1 
> > "forwprop1" } } */
> > +/* { dg-final { scan-tree-dump-times " \\+ \\{ -1, 2, -3, 4 \\}" 1 
> > "forwprop1" } } */
> > +/* { dg-final { scan-tree-dump-times " \\+ \\{ 16711935, 16711935, 
> > 16711935, 16711935 \\}" 1 "forwprop1" } } */
> > +/* { dg-final { scan-tree-dump-times " - \\{ -2147483648, 1, 1, 1 \\}" 1 
> > "forwprop1" } } */
> > +/* { dg-final { scan-tree-dump-times " - \\{ 2147483645, 2147483646, 
> > 2147483647, -2147483648 \\}" 1 "forwprop1" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
> > new file mode 100644
> > index 00000000000..27de9e77be2
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-sub-const-2.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -Wno-psabi -fsanitize=signed-integer-overflow 
> > -fdump-tree-forwprop1" } */
> > +
> > +typedef __INT32_TYPE__ v4si __attribute__ ((vector_size (16)));
> > +
> > +v4si
> > +f (v4si x)
> > +{
> > +  return x - (v4si) { 1, 1, 1, 1 };
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "\\.UBSAN_CHECK_SUB" 1 "forwprop1" } 
> > } */
> >
>
> --
> 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)

Reply via email to