aboutsummaryrefslogtreecommitdiff
path: root/gcc/gensupport.c
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/gensupport.c
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/gensupport.c')
-rw-r--r--gcc/gensupport.c74
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;