[PATCH] Avoid (almost) ix86_binary_operator_ok in sse.md (PR target/82855)
Jakub Jelinek
jakub@redhat.com
Tue Nov 7 07:48:00 GMT 2017
On Mon, Nov 06, 2017 at 11:27:27PM +0100, Uros Bizjak wrote:
> On Mon, Nov 6, 2017 at 10:18 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> > Hi!
> >
> > As this patch shows, we have tons of ix86_binary_operator_ok calls
> > in sse.md patterns, but I believe those are inappropriate in all these
> > spots, the function is for normal 2 operand binary instructions, where
> > we require that if one operand is memory, the destination is as well and
> > they match. That is generally not the case for 3 operand SSE*/AVX*
> > instructions, where the destination is always a register, and one of the
> > other operands can be a memory. All we care about and is what we express
> > in condition on many other sse.md instructions is that at most one input
> > operand is a memory, never both.
>
> !(MEM_P (operands[1]) && MEM_P (operands[2])) applies to AVX patterns
> only. Please note that ix86_binary_operator_ok also handles dst/src1
> operand matching and commutative operands in non-AVX SSE patterns.
> Looking at the patch, perhaps we should introduce
> ix86_fixup_sse_binary_operator and ix86_sse_binary_operator_ok that
> would bypass most of ix86_{fixup_,}binary_operator{,_ok} operand
> handling for TARGET_AVX? This way, we will still allow memory operands
> as operand1 and operand2 for commutative operators in AVX and non-AVX
> patterns and match src1 and dst of non-AVX patterns.
What I mean is that on randomly chosen SSE pattern:
(define_insn "*<plusminus_insn><mode>3"
[(set (match_operand:VI_AVX2 0 "register_operand" "=x,v")
(plusminus:VI_AVX2
(match_operand:VI_AVX2 1 "vector_operand" "<comm>0,v")
(match_operand:VI_AVX2 2 "vector_operand" "xBm,vm")))]
"TARGET_SSE2
&& ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"@
p<plusminus_mnemonic><ssemodesuffix>\t{%2, %0|%0, %2}
vp<plusminus_mnemonic><ssemodesuffix>\t{%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2}"
ix86_binary_operator_ok does:
1)
/* Both source operands cannot be in memory. */
if (MEM_P (src1) && MEM_P (src2))
return false;
This is what we care about
2)
/* Canonicalize operand order for commutative operators. */
if (ix86_swap_binary_operands_p (code, mode, operands))
std::swap (src1, src2);
Just helper for the further handling if commutative.
3)
/* If the destination is memory, we must have a matching source operand. */
if (MEM_P (dst) && !rtx_equal_p (dst, src1))
return false;
This is useless, because dst must satisfy register_operand, so will
never return false.
4)
/* Source 1 cannot be a constant. */
if (CONSTANT_P (src1))
return false;
This is useless, because both input operands are using
nonimmediate_operand or vector_operand or similar predicates,
which don't include immediates.
5)
/* Source 1 cannot be a non-matching memory. */
if (MEM_P (src1) && !rtx_equal_p (dst, src1))
/* Support "andhi/andsi/anddi" as a zero-extending move. */
return (code == AND
&& (mode == HImode
|| mode == SImode
|| (TARGET_64BIT && mode == DImode))
&& satisfies_constraint_L (src2));
Because dst is not a MEM, this means effectively that if (MEM_P (src1))
return false; but for commutative patterns 1) together with 2) already
ensured that (mode is not scalar).
You are right that for non-commutative 5) is needed, but for instructions
that are never commutative we can and already do ensure it by just
using register_operand predicate instead of
nonimmediate_operand/vector_operand (and then even 1) isn't needed
in the condition, because the predicates guarantee it is never true).
For always commutative insns, where we have explicit % in the constraints,
I believe !(MEM_P (operands[1]) && MEM_P (operands[2])) is also completely
sufficient.
The last category are insns with <comm> in constraints, sometimes
commutative, sometimes not, where !(MEM_P (operands[1]) && MEM_P (operands[2]))
is insufficent. I can introduce ix86_{fixup_,}sse_binary_operator{,_ok}
for those, sure.
The question is, for the always commutative insns like:
(define_insn "*mul<mode>3<mask_name><round_name>"
[(set (match_operand:VF 0 "register_operand" "=x,v")
(mult:VF
(match_operand:VF 1 "<round_nimm_predicate>" "%0,v")
(match_operand:VF 2 "<round_nimm_predicate>" "xBm,<round_constraint>")))]
"TARGET_SSE && ix86_binary_operator_ok (MULT, <MODE>mode, operands) && <mask_mode512bit_condition> && <round_mode512bit_condition>"
do you prefer !(MEM_P (operands[1]) && MEM_P (operands[2]))
in the condition, or ix86_fixup_sse_binary_operator_ok even
when it will in practice do the same thing?
Jakub
More information about the Gcc-patches
mailing list