On Fri, Sep 25, 2026 at 10:31 AM Stefan Schulze Frielinghaus
<[email protected]> wrote:
>
> From: Stefan Schulze Frielinghaus <[email protected]>
>
> As a first step I went for implementing this during simplify RTX.
> However, in the end this works only partly.  For example, a candidate
> insn created during a 3-insn combine resulting from the simplification
> has a vector constant as an operand, now, which may have been previously
> a register operand.  This may lead to fail predicate general_operand in
> case the constant is not a legitimate one which leads to rejecting the
> insn instead of fixing it up during LRA.  This was the motivation for
> also doing the same on tree level.  Then we end up prior expand with a
> PLUS and MULT which in turn means after expand we do so, too, and
> combine can merge both (independent of the vector constant which may
> have been pushed into the constant pool at this particular time).
>
> Note, the RTX simplification still works for vector constants which are
> accepted by TARGET_LEGITIMATE_CONSTANT_P.  For s390, the different code
> paths are demonstrated in the subsequent patch where
> test_<mode>_minus_vrepi profits already from the rtx canonicalization,
> and test_<mode>_minus_constpool profits from the tree canonicalization.
>
> Of course, this is not uncontroversial.  In case the multiplication is
> used in more than one place, the combination might be undesired.  The
> same holds true in case the constant vector is used in multiple places
> but the negated version is not.  The former is partly addressed by
> match.pd requiring a single use for mult.  Of course, there still might
> be cases where this may prohibit CSE optimizations later on.
>
> If this is about to being accepted, then one could also introduce a
> mach.pd rule for A-((-B)*C) -> (B*C)+A which is already taken care of in
> simplify RTX due to the recursive call.
>
> This is motivated by the fact that on s390 we only have vector
> multiply-and-add but no subtract variant over the integers.
>
> Note, w.r.t. the SPEC CPU 2017 suite, the results are underwhelming in
> the sense that only two times the canonicalization helps for emitting a
> VMAL instead of VML+VS.  On the other hand the results are also a
> relieve in the sense that they show that no extra multiplications were
> introduced due to pulling in the minus.
>
> Side remark: We generously accept all scalar constants during
> TARGET_LEGITIMATE_CONSTANT_P, since those which do not end up as
> immediates, RA does a very nice job by reloading and sharing those
> reloads among insns.  In contrast, vector constants can never end up as
> immediates which is why putting those early into the constant pool leads
> generally to better code.  Only in those few cases where a constant can
> be constructed via a single instruction, we do not utilize the constant
> pool.
> ---
>  Bootstrapped and regtested on
>  - aarch64-unknown-linux-gnu
>  - powerpc64le-unknown-linux-gnu
>  - s390x-ibm-linux-gnu
>  - x86_64-pc-linux-gnu
>  If there is consensus to commit this, I would add A-((-B)*C) -> (B*C)+A
>  and give this another round of testing.
>
>  gcc/match.pd        | 12 ++++++++++++
>  gcc/simplify-rtx.cc | 17 ++++++++++++++++-
>  2 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 268bf3f11e5..a5a476e17a3 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -2532,6 +2532,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>   (if (!FIXED_POINT_TYPE_P (type))
>   (plus @0 (negate @1))))
>
> +/* A - (B * C) -> (B * (-C)) + A if C is a constant vector.  */

This should be catched by A - B -> A + (-B) when B can be easily
negated via negate_expr_p.  match.pd does not implement
the fold-const MULT_EXPR case and I remember Kyrylo messing
with negating of vectors, so CCed.

The negate_expr_p match will have the issue of single-uses as you
say.  So I'm not entirely convinced this is a good idea as this
"canonicalization" doesn't really help much, unlike for example
knowing that A - INTEGER_CST will never appear (besides for INT_MIN),
but it will be A + INTEGER_CST always.

> +/* Perform this only in case the multiplication has a single use.  */
> +(simplify
> + (minus @0 (mult:cs @1 VECTOR_CST@2))
> + (if (VECTOR_INTEGER_TYPE_P (type))
> +  (with { tree neg_const_vec = const_unop (NEGATE_EXPR, type, @2); }
> +    /* Be defensive here and check that the negation of a constant
> +       vector can be represented which may not be the case for
> +       scalable vectors.  */
> +   (if (neg_const_vec)
> +    (plus (mult @1 { neg_const_vec; }) @0)))))
> +
>  /* A - MIN (B, C) -> A + MAX (-B, -C)
>     A - MAX (B, C) -> A + MIN (-B, -C)  if B and C are easily negatable.  */
>  (for minmax (min max)
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index 38c8abfe3e7..ce3e5469812 100644
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -3690,12 +3690,27 @@ simplify_context::simplify_binary_operation_1 
> (rtx_code code,
>           && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
>         return tem;
>
> -      /* Handle vector series.  */
> +      /* Handle integer vector operations.  */
>        if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
>         {
>           tem = simplify_binary_operation_series (code, mode, op0, op1);
>           if (tem)
>             return tem;
> +
> +         /* Canonicalize A-(B*C) into (B*(-C))+A if C is a constant vector.  
> */
> +         rtx neg_const_vec;
> +         if (GET_CODE (op1) == MULT
> +             && CONST_VECTOR_P (XEXP (op1, 1))
> +             /* Be defensive here and check that the negation of a constant
> +                vector can be represented which may not be the case for
> +                scalable vectors.  */
> +             && (neg_const_vec
> +                 = simplify_unary_operation (NEG, mode, XEXP (op1, 1), 
> mode)))
> +           {
> +             rtx new_mult = simplify_gen_binary (MULT, mode, XEXP (op1, 0),
> +                                                 neg_const_vec);
> +             return simplify_gen_binary (PLUS, mode, new_mult, op0);
> +           }
>         }
>        break;
>
> --
> 2.55.0
>

Reply via email to