aboutsummaryrefslogtreecommitdiff
path: root/gcc/doc/md.texi
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-05-31 16:27:49 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-05-31 16:27:49 +0000
commitf4fde1b378ad68fb2dec6719ed26c1b901488e03 (patch)
treea6089ff5ae9f140f131b42e288966eb32e0b353c /gcc/doc/md.texi
parentb1bb4869e2708c1385352e4d960833e1b258859b (diff)
downloadgcc-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.texi113
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