On Mon, 2 Feb 2026, Tamar Christina wrote:
> If we defer an FMA creation the code tries to determine the order of the
> operands before deferring. To do this it compares the operands against the
> result expression (which should contain the multiplication expression).
>
> However the multiply might be wrapped in a conversion. This change has us
> strip
> one level of conversion (the most that convert_mult_to_fma) supports handling
> and only then do the comparison.
>
> We cannot strip ops[0] and ops[1] and store them stripped since after the
> deferrence, if we create an FMA we need to know the original types and
> convert_mult_to_fma handles the conversions during FMA creation anyway.
>
> There's probably a similar helper to strip_nop_view_converts but I couldn't
> find one, since many of the stripping helpers are recursive or don't support
> stripping VIEW_CONVERTS.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
>
> Ok for master?
>
> Thanks,
> Tamar
>
> gcc/ChangeLog:
>
> PR tree-optimization/123897
> * tree-ssa-math-opts.cc (strip_nop_view_converts): New.
> (convert_mult_to_fma): Use it.
>
> gcc/testsuite/ChangeLog:
>
> PR tree-optimization/123897
> * gcc.target/aarch64/sve/pr123898.c: New test.
>
> ---
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr123898.c
> b/gcc/testsuite/gcc.target/aarch64/sve/pr123898.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..a5741d5058e81b8c34bcfacca5f456bc015308a1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr123898.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2 --param avoid-fma-max-bits=512
> -march=armv9-a -msve-vector-bits=256 -fdump-tree-widening_mul" } */
> +
> +typedef __attribute__((__vector_size__(32))) char A;
> +typedef __attribute__((__vector_size__(32))) signed char D;
> +
> +A c;
> +char x;
> +
> +void
> +foo(D d)
> +{
> + d *= x;
> + c += (A)d;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "\.FMA" 1 "widening_mul" } } */
> diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
> index
> 9522532b7fc64678c57e9b72342940e7cac9d801..24f01c8359cbe9cdb06ea6192bb5baf9a7da92ee
> 100644
> --- a/gcc/tree-ssa-math-opts.cc
> +++ b/gcc/tree-ssa-math-opts.cc
> @@ -3353,6 +3353,29 @@ last_fma_candidate_feeds_initial_phi
> (fma_deferring_state *state,
> return false;
> }
>
> +/* If ARG is a view_convert that only changes the sign then strip the outer
> + conversion away. It does not strip conversions recursively. Otherwise
> + return ARG. */
> +
> +static tree
> +strip_nop_view_converts (tree arg)
> +{
> + if (TREE_CODE (arg) != SSA_NAME)
> + return arg;
> +
> + gimple *assign = SSA_NAME_DEF_STMT (arg);
> + tree lhs_type, var;
> + if (gimple_assign_cast_p (assign)
> + && (var = gimple_assign_rhs1 (assign))
> + && TREE_CODE (var) != SSA_NAME
> + && (var = TREE_OPERAND (var, 0))
This only works for V_C_Es, does the same issue not exist for
scalar NOP_EXPR conversions?
> + && (lhs_type = TREE_TYPE (var))
var_type would be less odd, not sure why you need a temporary here,
either. Indenting? For such purpose I usually write
&& ((lhs_type = TREE_TYPE (var), true)
to indicate there's not really any non-NULL test necessary.
> + && tree_nop_conversion_p (lhs_type, TREE_TYPE (arg)))
> + return var;
> +
> + return arg;
> +}
> +
> /* Combine the multiplication at MUL_STMT with operands MULOP1 and MULOP2
> with uses in additions and subtractions to form fused multiply-add
> operations. Returns true if successful and MUL_STMT should be removed.
> @@ -3613,11 +3636,11 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree
> op2,
> {
> gcc_checking_assert (!state->m_initial_phi);
> gphi *phi;
> - if (ops[0] == result)
> + if (strip_nop_view_converts (ops[0]) == result)
> phi = result_of_phi (ops[1]);
> else
> {
> - gcc_assert (ops[1] == result);
> + gcc_assert (strip_nop_view_converts (ops[1]) == result);
> phi = result_of_phi (ops[0]);
> }
>
>
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)