diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-05-31 16:27:49 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-05-31 16:27:49 +0000 |
commit | f4fde1b378ad68fb2dec6719ed26c1b901488e03 (patch) | |
tree | a6089ff5ae9f140f131b42e288966eb32e0b353c /gcc/doc/md.texi | |
parent | b1bb4869e2708c1385352e4d960833e1b258859b (diff) | |
download | gcc-f4fde1b378ad68fb2dec6719ed26c1b901488e03.zip gcc-f4fde1b378ad68fb2dec6719ed26c1b901488e03.tar.gz gcc-f4fde1b378ad68fb2dec6719ed26c1b901488e03.tar.bz2 |
New .md construct: define_insn_and_rewrite
Several SVE patterns need define_insn_and_splits that generate the
same insn_code, but with different operands. That's probably a
niche requirement, but it's cropping up often enough on the ACLE
branch that I think it would be good to have a syntactic sugar for it.
This patch therefore adds a new construct called define_insn_and_rewrite.
It's basically a define_insn_and_split with an implicit split pattern,
obtained by copying the insn pattern and replacing match_operands with
match_dups and match_operators with match_op_dups.
2019-05-31 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* doc/md.texi: Document define_insn_and_rewrite.
* rtl.def (DEFINE_INSN_AND_REWRITE): New rtx code.
* gensupport.c (queue_elem): Update comment.
(replace_operands_with_dups): New function.
(gen_rewrite_sequence): Likewise.
(process_rtx): Handle DEFINE_INSN_AND_REWRITE.
* read-rtl.c (apply_subst_iterator): Likewise.
(add_condition_to_rtx, named_rtx_p): Likewise.
(rtx_reader::read_rtx_operand): Likewise.
* config/aarch64/aarch64-sve.md
(while_ult<GPI:mode><PRED_ALL:mode>_cc): Rename to...
(*while_ult<GPI:mode><PRED_ALL:mode>_cc): ...this and use
define_insn_and_rewrite.
(*cond_<optab><mode>_any): Turn into define_insn_and_rewrites.
Remove separate define_split.
From-SVN: r271815
Diffstat (limited to 'gcc/doc/md.texi')
-rw-r--r-- | gcc/doc/md.texi | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 775b8f5..4bc57d6 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -8498,6 +8498,119 @@ functionality as two separate @code{define_insn} and @code{define_split} patterns. It exists for compactness, and as a maintenance tool to prevent having to ensure the two patterns' templates match. +@findex define_insn_and_rewrite +It is sometimes useful to have a @code{define_insn_and_split} +that replaces specific operands of an instruction but leaves the +rest of the instruction pattern unchanged. You can do this directly +with a @code{define_insn_and_split}, but it requires a +@var{new-insn-pattern-1} that repeats most of the original @var{insn-pattern}. +There is also the complication that an implicit @code{parallel} in +@var{insn-pattern} must become an explicit @code{parallel} in +@var{new-insn-pattern-1}, which is easy to overlook. +A simpler alternative is to use @code{define_insn_and_rewrite}, which +is a form of @code{define_insn_and_split} that automatically generates +@var{new-insn-pattern-1} by replacing each @code{match_operand} +in @var{insn-pattern} with a corresponding @code{match_dup}, and each +@code{match_operator} in the pattern with a corresponding @code{match_op_dup}. +The arguments are otherwise identical to @code{define_insn_and_split}: + +@smallexample +(define_insn_and_rewrite + [@var{insn-pattern}] + "@var{condition}" + "@var{output-template}" + "@var{split-condition}" + "@var{preparation-statements}" + [@var{insn-attributes}]) +@end smallexample + +The @code{match_dup}s and @code{match_op_dup}s in the new +instruction pattern use any new operand values that the +@var{preparation-statements} store in the @code{operands} array, +as for a normal @code{define_insn_and_split}. @var{preparation-statements} +can also emit additional instructions before the new instruction. +They can even emit an entirely different sequence of instructions and +use @code{DONE} to avoid emitting a new form of the original +instruction. + +The split in a @code{define_insn_and_rewrite} is only intended +to apply to existing instructions that match @var{insn-pattern}. +@var{split-condition} must therefore start with @code{&&}, +so that the split condition applies on top of @var{condition}. + +Here is an example from the AArch64 SVE port, in which operand 1 is +known to be equivalent to an all-true constant and isn't used by the +output template: + +@smallexample +(define_insn_and_rewrite "*while_ult<GPI:mode><PRED_ALL:mode>_cc" + [(set (reg:CC CC_REGNUM) + (compare:CC + (unspec:SI [(match_operand:PRED_ALL 1) + (unspec:PRED_ALL + [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ") + (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")] + UNSPEC_WHILE_LO)] + UNSPEC_PTEST_PTRUE) + (const_int 0))) + (set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + (unspec:PRED_ALL [(match_dup 2) + (match_dup 3)] + UNSPEC_WHILE_LO))] + "TARGET_SVE" + "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3" + ;; Force the compiler to drop the unused predicate operand, so that we + ;; don't have an unnecessary PTRUE. + "&& !CONSTANT_P (operands[1])" + @{ + operands[1] = CONSTM1_RTX (<MODE>mode); + @} +) +@end smallexample + +The splitter in this case simply replaces operand 1 with the constant +value that it is known to have. The equivalent @code{define_insn_and_split} +would be: + +@smallexample +(define_insn_and_split "*while_ult<GPI:mode><PRED_ALL:mode>_cc" + [(set (reg:CC CC_REGNUM) + (compare:CC + (unspec:SI [(match_operand:PRED_ALL 1) + (unspec:PRED_ALL + [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ") + (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")] + UNSPEC_WHILE_LO)] + UNSPEC_PTEST_PTRUE) + (const_int 0))) + (set (match_operand:PRED_ALL 0 "register_operand" "=Upa") + (unspec:PRED_ALL [(match_dup 2) + (match_dup 3)] + UNSPEC_WHILE_LO))] + "TARGET_SVE" + "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3" + ;; Force the compiler to drop the unused predicate operand, so that we + ;; don't have an unnecessary PTRUE. + "&& !CONSTANT_P (operands[1])" + [(parallel + [(set (reg:CC CC_REGNUM) + (compare:CC + (unspec:SI [(match_dup 1) + (unspec:PRED_ALL [(match_dup 2) + (match_dup 3)] + UNSPEC_WHILE_LO)] + UNSPEC_PTEST_PTRUE) + (const_int 0))) + (set (match_dup 0) + (unspec:PRED_ALL [(match_dup 2) + (match_dup 3)] + UNSPEC_WHILE_LO))])] + @{ + operands[1] = CONSTM1_RTX (<MODE>mode); + @} +) +@end smallexample + @end ifset @ifset INTERNALS @node Including Patterns |