On Fri, Oct 11, 2024 at 8:22 PM Richard Biener <rguent...@suse.de> wrote:
>
> The following helps the x86 backend by canonicalizing FMAs to have
> any negation done to one of the commutative multiplication operands
> be done to a register (and not a memory operand).  Likewise to
> put a register operand first and a memory operand second;
> swap_commutative_operands_p seems to treat REG_P and MEM_P the
> same but comments indicate "complex expressiosn should be first".
>
> In particular this does (fma MEM REG REG) -> (fma REG MEM REG) and
> (fma (neg MEM) REG REG) -> (fma (neg REG) MEM REG) which are the
> reasons for the testsuite regressions in gcc.target/i386/cond_op_fma*.c
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
>
> I'm not quite sure this is the correct approach - simplify-rtx
> doesn't seem to do "only canonicalization" but the existing FMA
> case looks odd in that context.
>
> Should the target simply reject cases with wrong "canonicalization"
> or does it need to cope with all variants in the patterns that fail
> matching during combine without the change?
Let me try the backend fix first.
>
> Thanks,
> Richard.
>
>         PR target/117072
>         * simplify-rtx.cc (simplify_context::simplify_ternary_operation):
>         Adjust FMA canonicalization.
> ---
>  gcc/simplify-rtx.cc | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
> index e8e60404ef6..8b4fa0d7aa4 100644
> --- a/gcc/simplify-rtx.cc
> +++ b/gcc/simplify-rtx.cc
> @@ -6830,10 +6830,21 @@ simplify_context::simplify_ternary_operation 
> (rtx_code code, machine_mode mode,
>             op0 = tem, op1 = XEXP (op1, 0), any_change = true;
>         }
>
> -      /* Canonicalize the two multiplication operands.  */
> +      /* Canonicalize the two multiplication operands.  A negation
> +        should go first and if possible the negation should be
> +        to a register.  */
>        /* a * -b + c  =>  -b * a + c.  */
> -      if (swap_commutative_operands_p (op0, op1))
> +      if (swap_commutative_operands_p (op0, op1)
> +         || (REG_P (op1) && !REG_P (op0) && GET_CODE (op0) != NEG))
>         std::swap (op0, op1), any_change = true;
> +      else if (GET_CODE (op0) == NEG && !REG_P (XEXP (op0, 0))
> +              && REG_P (op1))
> +       {
> +         op0 = XEXP (op0, 0);
> +         op1 = simplify_gen_unary (NEG, mode, op1, mode);
> +         std::swap (op0, op1);
> +         any_change = true;
> +       }
>
>        if (any_change)
>         return gen_rtx_FMA (mode, op0, op1, op2);
> --
> 2.43.0



-- 
BR,
Hongtao

Reply via email to