On Wed, Feb 4, 2026 at 5:08 PM Robin Dapp <[email protected]> wrote:
>
> 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;

But the function comment documents this.

> -                 }
> -             }
> -           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;

It seems to be the fix is to check ops[] properly?  But maybe I
mis-understand the failure
mode.

> +
> +         /* 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

Reply via email to