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