Hi,
When looking for FMA opportunities we can find a multiplication use in an
else operand:
vect_pretmp_50.23_121 = MEM <vector(2) charD.2> [(charD.2 *)&dD.2916 + 14B];
vect__28.25_123 = vect_pretmp_50.23_121 * { 2, 2 };
vect_patt_99.26_124 = .COND_ADD ({ -1, -1 }, vect_pretmp_50.23_121, { 14, 15
}, vect__28.25_123);
and build it:
vect_pretmp_50.23_121 = MEM <vector(2) charD.2> [(charD.2 *)&dD.2916 + 14B];
vect_patt_99.26_124 = .FMA (vect_pretmp_50.23_121, { 2, 2 },
vect_pretmp_50.23_121);
But that's invalid as the else operand is actually unused as the
conditional mask is always true.
In can_interpret_as_conditional_op_p we don't set cond and else if the
cond is always true. Therefore the existing check for else_value ==
result does not succeed.
This patch reinstates the cond and else operands and lets the callers
handle an always-true cond.
Bootstrapped and regtested on x86, power10, and aarch64.
Regtested on riscv64.
Regards
Robin
PR tree-optimization/123940
gcc/ChangeLog:
* internal-fn.cc (can_interpret_as_conditional_op_p): Don't set
cond and else to zero if cond is always true.
* tree-ssa-math-opts.cc (convert_mult_to_fma_1): Handle
always-true cond.
(convert_mult_to_fma): Ditto.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/autovec/pr123940.c: New test.
---
gcc/internal-fn.cc | 10 +-------
.../gcc.target/riscv/rvv/autovec/pr123940.c | 25 +++++++++++++++++++
gcc/tree-ssa-math-opts.cc | 10 +++++---
3 files changed, 32 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123940.c
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index d879568c6e3..3cab3a491de 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -4978,15 +4978,7 @@ can_interpret_as_conditional_op_p (gimple *stmt, tree
*cond_out,
for (unsigned int i = 0; i < 3; ++i)
ops[i] = i < nops ? gimple_call_arg (call, i + 1) : NULL_TREE;
*else_out = gimple_call_arg (call, nops + 1);
- if (len_index < 0)
- {
- if (integer_truep (*cond_out))
- {
- *cond_out = NULL_TREE;
- *else_out = NULL_TREE;
- }
- }
- else
+ if (len_index != -1)
{
*len = gimple_call_arg (call, len_index);
*bias = gimple_call_arg (call, len_index + 1);
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123940.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123940.c
new file mode 100644
index 00000000000..329e598f068
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123940.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -std=gnu99
-fdump-tree-widening_mul" } */
+
+long a;
+long long b;
+_Bool c[16];
+char d[16];
+char e = 0;
+int f = 1;
+
+int main ()
+{
+ for (long i = 0; i < 16; ++i)
+ c[i] = 40;
+ for (int j = 0; j < 16; j++)
+ {
+ e = (c[j] ? j : d[j]) + d[j];
+ a = f * c[j] ?: ~0;
+ }
+ b = (int) e;
+ if (b != 15)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "FMA" "widening_mul" } } */
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index 4b50a96ad3a..1f72ba7f1fc 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -3190,7 +3190,7 @@ convert_mult_to_fma_1 (tree mul_result, tree op1, tree
op2)
fma_stmt
= gimple_build_call_internal (IFN_COND_LEN_FMA, 7, cond, mulop1, op2,
addop, else_value, len, bias);
- else if (cond)
+ else if (!integer_truep (cond))
fma_stmt = gimple_build_call_internal (IFN_COND_FMA, 5, cond, mulop1,
op2, addop, else_value);
else
@@ -3560,10 +3560,12 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree
op2,
if (mul_cond && cond != mul_cond)
return false;
- if (cond)
+ if (cond == result || else_value == result)
+ return false;
+
+ /* For a real mask, use a conditional FMA. */
+ if (!integer_truep (cond))
{
- if (cond == result || else_value == result)
- return false;
if (!direct_internal_fn_supported_p (IFN_COND_FMA, type,
opt_type))
return false;
--
2.52.0