On Mon, 2 Feb 2026, Tamar Christina wrote:
> Previously the types of the 3 operands would always be the same when you get
> to
> convert_mult_to_fma_1. However now they can differ untill we fold the to be
> the
> same. Using the type of the final expression is this incorrect and any
> intermediate operations need to happen in the type of the expression being
> folded.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
>
> Ok for master?
OK.
> Thanks,
> Tamar
>
> gcc/ChangeLog:
>
> PR tree-optimization/123897
> * tree-ssa-math-opts.cc (convert_mult_to_fma_1): Use type of variable
> being folder.
>
> gcc/testsuite/ChangeLog:
>
> PR tree-optimization/123897
> * gcc.target/aarch64/sve/pr123897.c: New test.
>
> ---
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr123897.c
> b/gcc/testsuite/gcc.target/aarch64/sve/pr123897.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..d74efabb7f89320ff2d9a651bdcd20e9be061d38
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr123897.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-O2 -march=armv9-a -msve-vector-bits=256
> -fdump-tree-widening_mul" } */
> +
> +typedef __attribute__((__vector_size__(sizeof(int)*8))) signed int v8i;
> +typedef __attribute__((__vector_size__(sizeof(int)*8))) unsigned int v8u;
> +void f(v8i *a,v8i *b,v8u *c)
> +{
> + *c = (v8u)(*a * *b) - *c;
> +}
> +
> +void g(v8i *a,v8i *b,v8u *c)
> +{
> + *c = *c - (v8u)(*a * *b);
> +}
> +
> +/* { dg-final { scan-tree-dump-times "\.FMA" 2 "widening_mul" } } */
> diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
> index
> 4b50a96ad3aa19857c5b8436ee8d6d3080d3c9ed..b1fa38a832af889972913553d75305a9420b7b53
> 100644
> --- a/gcc/tree-ssa-math-opts.cc
> +++ b/gcc/tree-ssa-math-opts.cc
> @@ -3105,7 +3105,6 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi,
> gimple *stmt,
> static void
> convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
> {
> - tree type = TREE_TYPE (mul_result);
> gimple *use_stmt;
> imm_use_iterator imm_iter;
> gcall *fma_stmt;
> @@ -3167,14 +3166,14 @@ convert_mult_to_fma_1 (tree mul_result, tree op1,
> tree op2)
> {
> if (ops[0] == result)
> /* a * b - c -> a * b + (-c) */
> - addop = gimple_build (&seq, NEGATE_EXPR, type, addop);
> + addop = gimple_build (&seq, NEGATE_EXPR, TREE_TYPE (addop), addop);
> else
> /* a - b * c -> (-b) * c + a */
> negate_p = !negate_p;
> }
>
> if (negate_p)
> - mulop1 = gimple_build (&seq, NEGATE_EXPR, type, mulop1);
> + mulop1 = gimple_build (&seq, NEGATE_EXPR, TREE_TYPE (mulop1), mulop1);
>
> if (seq)
> gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
>
>
>
--
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)