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?
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);
--
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);