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/gensupport.c | |
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/gensupport.c')
-rw-r--r-- | gcc/gensupport.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 31a67d5..0150346 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -70,8 +70,8 @@ struct queue_elem rtx data; file_location loc; struct queue_elem *next; - /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT - points to the generated DEFINE_SPLIT. */ + /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or + DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */ struct queue_elem *split; }; @@ -485,6 +485,63 @@ remove_constraints (rtx part) } } +/* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs + with MATCH_OP_DUPs in X. */ + +static rtx +replace_operands_with_dups (rtx x) +{ + if (x == 0) + return x; + + rtx newx; + if (GET_CODE (x) == MATCH_OPERAND) + { + newx = rtx_alloc (MATCH_DUP); + XINT (newx, 0) = XINT (x, 0); + } + else if (GET_CODE (x) == MATCH_OPERATOR) + { + newx = rtx_alloc (MATCH_OP_DUP); + XINT (newx, 0) = XINT (x, 0); + XVEC (newx, 1) = XVEC (x, 2); + } + else + newx = shallow_copy_rtx (x); + + const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x)); + for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++) + switch (*format_ptr++) + { + case 'e': + case 'u': + XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i)); + break; + case 'E': + if (XVEC (x, i) != NULL) + { + XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i)); + for (int j = 0; j < XVECLEN (x, i); j++) + XVECEXP (newx, i, j) + = replace_operands_with_dups (XVECEXP (x, i, j)); + } + break; + } + return newx; +} + +/* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into + a sequence that should be generated by the splitter. */ + +static rtvec +gen_rewrite_sequence (rtvec vec) +{ + rtvec new_vec = rtvec_alloc (1); + rtx x = add_implicit_parallel (vec); + RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x); + return new_vec; +} + /* Process a top level rtx in some way, queuing as appropriate. */ static void @@ -527,6 +584,7 @@ process_rtx (rtx desc, file_location loc) break; case DEFINE_INSN_AND_SPLIT: + case DEFINE_INSN_AND_REWRITE: { const char *split_cond; rtx split; @@ -534,6 +592,7 @@ process_rtx (rtx desc, file_location loc) int i; struct queue_elem *insn_elem; struct queue_elem *split_elem; + int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6); /* Create a split with values from the insn_and_split. */ split = rtx_alloc (DEFINE_SPLIT); @@ -555,12 +614,17 @@ process_rtx (rtx desc, file_location loc) split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2), split_cond + 2); } + else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE) + error_at (loc, "the rewrite condition must start with `&&'"); XSTR (split, 1) = split_cond; - XVEC (split, 2) = XVEC (desc, 5); - XSTR (split, 3) = XSTR (desc, 6); + if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE) + XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1)); + else + XVEC (split, 2) = XVEC (desc, 5); + XSTR (split, 3) = XSTR (desc, split_code); /* Fix up the DEFINE_INSN. */ - attr = XVEC (desc, 7); + attr = XVEC (desc, split_code + 1); PUT_CODE (desc, DEFINE_INSN); XVEC (desc, 4) = attr; |