From: Richard Sandiford Date: Sun, 12 May 2019 11:28:01 +0000 (+0000) Subject: Accept code attributes as rtx codes in .md files X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=75df257b38bd4cdcb750fc893c5023363230cfe8;p=gcc.git Accept code attributes as rtx codes in .md files The recent AArch64 absolute difference patterns had to go through some hoops to pair max/min rtx codes with the same signedness. I also need to pair signed/unsigned codes with sign/zero extension for some SVE ACLE patterns. This patch therefore supports <...> as rtx codes, like we already do for modes. 2019-05-12 Richard Sandiford gcc/ * doc/md.texi: Document use of code attributes in rtx patterns. * read-md.h (rtx_reader::rtx_alloc_for_name): New member function. * read-rtl.c (find_code): Split out search loops into... (maybe_find_code): ...this new function. (check_code_iterator): Make the error message more informative. (check_code_attribute): New function. (rtx_reader::rtx_alloc_for_name): Likewise. (rtx_reader::read_rtx_code): Use rtx_alloc_for_name. * config/aarch64/predicates.md (aarch64_smin, aarch64_umin): Delete. * config/aarch64/aarch64-simd.md (*aarch64_abd_3): Use directly as an rtx code instead of via a match_operator. * config/aarch64/aarch64-sve.md (aarch64_abd_3): Likewise. (abd_3): Update accordingly. From-SVN: r271107 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2628c240010..1a9c8c1e181 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2019-05-12 Richard Sandiford + + * doc/md.texi: Document use of code attributes in rtx patterns. + * read-md.h (rtx_reader::rtx_alloc_for_name): New member function. + * read-rtl.c (find_code): Split out search loops into... + (maybe_find_code): ...this new function. + (check_code_iterator): Make the error message more informative. + (check_code_attribute): New function. + (rtx_reader::rtx_alloc_for_name): Likewise. + (rtx_reader::read_rtx_code): Use rtx_alloc_for_name. + * config/aarch64/predicates.md (aarch64_smin, aarch64_umin): Delete. + * config/aarch64/aarch64-simd.md (*aarch64_abd_3): Use + directly as an rtx code instead of via a match_operator. + * config/aarch64/aarch64-sve.md (aarch64_abd_3): Likewise. + (abd_3): Update accordingly. + 2019-05-12 Iain Sandoe * config/rs6000/rs6000.c (debug_stack_info): When -mdebug=stack diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index e3852c5d182..2b7a0029146 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -716,9 +716,9 @@ (USMAX:VDQ_BHSI (match_operand:VDQ_BHSI 1 "register_operand" "w") (match_operand:VDQ_BHSI 2 "register_operand" "w")) - (match_operator 3 "aarch64_" - [(match_dup 1) - (match_dup 2)])))] + (:VDQ_BHSI + (match_dup 1) + (match_dup 2))))] "TARGET_SIMD" "abd\t%0., %1., %2." [(set_attr "type" "neon_abd")] diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index e94801d9f86..b9cb1fae98c 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -3149,8 +3149,7 @@ [(set_attr "movprfx" "*,yes")] ) -;; Helper expander for aarch64_abd_3 to save the callers -;; the hassle of constructing the other arm of the MINUS. +;; Unpredicated integer absolute difference. (define_expand "abd_3" [(use (match_operand:SVE_I 0 "register_operand")) (USMAX:SVE_I (match_operand:SVE_I 1 "register_operand") @@ -3158,9 +3157,8 @@ "TARGET_SVE" { rtx pred = force_reg (mode, CONSTM1_RTX (mode)); - rtx other_arm = gen_rtx_ (mode, operands[1], operands[2]); emit_insn (gen_aarch64_abd_3 (operands[0], pred, operands[1], - operands[2], other_arm)); + operands[2])); DONE; } ) @@ -3174,9 +3172,9 @@ (USMAX:SVE_I (match_operand:SVE_I 2 "register_operand" "0, w") (match_operand:SVE_I 3 "register_operand" "w, w")) - (match_operator 4 "aarch64_" - [(match_dup 2) - (match_dup 3)]))] + (:SVE_I + (match_dup 2) + (match_dup 3)))] UNSPEC_MERGE_PTRUE))] "TARGET_SVE" "@ diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 8e1b784217b..10100ca830a 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -323,12 +323,6 @@ (ior (match_operand 0 "register_operand") (match_operand 0 "const_scalar_int_operand"))) -(define_predicate "aarch64_smin" - (match_code "smin")) - -(define_predicate "aarch64_umin" - (match_code "umin")) - ;; True for integer comparisons and for FP comparisons other than LTGT or UNEQ. (define_special_predicate "aarch64_comparison_operator" (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered, diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 30612a6aecb..b35bcaace00 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -10979,6 +10979,27 @@ Other attributes are defined using: (define_code_attr @var{name} [(@var{code1} "@var{value1}") @dots{} (@var{coden} "@var{valuen}")]) @end smallexample +Instruction patterns can use code attributes as rtx codes, which can be +useful if two sets of codes act in tandem. For example, the following +@code{define_insn} defines two patterns, one calculating a signed absolute +difference and another calculating an unsigned absolute difference: + +@smallexample +(define_code_iterator any_max [smax umax]) +(define_code_attr paired_min [(smax "smin") (umax "umin")]) +(define_insn @dots{} + [(set (match_operand:SI 0 @dots{}) + (minus:SI (any_max:SI (match_operand:SI 1 @dots{}) + (match_operand:SI 2 @dots{})) + (:SI (match_dup 1) (match_dup 2))))] + @dots{}) +@end smallexample + +The signed version of the instruction uses @code{smax} and @code{smin} +while the unsigned version uses @code{umax} and @code{umin}. There +are no versions that pair @code{smax} with @code{umin} or @code{umax} +with @code{smin}. + Here's an example of code iterators in action, taken from the MIPS port: @smallexample diff --git a/gcc/read-md.h b/gcc/read-md.h index 18426f71d77..327f378eac0 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -337,6 +337,7 @@ class rtx_reader : public md_reader ~rtx_reader (); bool read_rtx (const char *rtx_name, vec *rtxen); + rtx rtx_alloc_for_name (const char *); rtx read_rtx_code (const char *code_name); virtual rtx read_rtx_operand (rtx return_rtx, int idx); rtx read_nested_rtx (); diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index ebd69bde531..f72b2c35c7d 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -194,22 +194,31 @@ static const compact_insn_name compact_insn_names[] = { { NOTE, "cnote" } }; -/* Implementations of the iterator_group callbacks for codes. */ +/* Return the rtx code for NAME, or UNKNOWN if NAME isn't a valid rtx code. */ -static int -find_code (const char *name) +static rtx_code +maybe_find_code (const char *name) { - int i; - - for (i = 0; i < NUM_RTX_CODE; i++) + for (int i = 0; i < NUM_RTX_CODE; i++) if (strcmp (GET_RTX_NAME (i), name) == 0) - return i; + return (rtx_code) i; - for (i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++) + for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++) if (strcmp (compact_insn_names[i].name, name) == 0) return compact_insn_names[i].code; - fatal_with_file_and_line ("unknown rtx code `%s'", name); + return UNKNOWN; +} + +/* Implementations of the iterator_group callbacks for codes. */ + +static int +find_code (const char *name) +{ + rtx_code code = maybe_find_code (name); + if (code == UNKNOWN) + fatal_with_file_and_line ("unknown rtx code `%s'", name); + return code; } static void @@ -1306,7 +1315,37 @@ check_code_iterator (struct mapping *iterator) for (v = iterator->values->next; v != 0; v = v->next) if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0) fatal_with_file_and_line ("code iterator `%s' combines " - "different rtx formats", iterator->name); + "`%s' and `%s', which have different " + "rtx formats", iterator->name, + GET_RTX_NAME (bellwether), + GET_RTX_NAME (v->number)); +} + +/* Check that all values of attribute ATTR are rtx codes that have a + consistent format. Return a representative code. */ + +static rtx_code +check_code_attribute (mapping *attr) +{ + rtx_code bellwether = UNKNOWN; + for (map_value *v = attr->values; v != 0; v = v->next) + { + rtx_code code = maybe_find_code (v->string); + if (code == UNKNOWN) + fatal_with_file_and_line ("code attribute `%s' contains " + "unrecognized rtx code `%s'", + attr->name, v->string); + if (bellwether == UNKNOWN) + bellwether = code; + else if (strcmp (GET_RTX_FORMAT (bellwether), + GET_RTX_FORMAT (code)) != 0) + fatal_with_file_and_line ("code attribute `%s' combines " + "`%s' and `%s', which have different " + "rtx formats", attr->name, + GET_RTX_NAME (bellwether), + GET_RTX_NAME (code)); + } + return bellwether; } /* Read an rtx-related declaration from the MD file, given that it @@ -1467,6 +1506,54 @@ parse_reg_note_name (const char *string) fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string); } +/* Allocate an rtx for code NAME. If NAME is a code iterator or code + attribute, record its use for later and use one of its possible + values as an interim rtx code. */ + +rtx +rtx_reader::rtx_alloc_for_name (const char *name) +{ +#ifdef GENERATOR_FILE + size_t len = strlen (name); + if (name[0] == '<' && name[len - 1] == '>') + { + /* Copy the attribute string into permanent storage, without the + angle brackets around it. */ + obstack *strings = get_string_obstack (); + obstack_grow0 (strings, name + 1, len - 2); + char *deferred_name = XOBFINISH (strings, char *); + + /* Find the name of the attribute. */ + const char *attr = strchr (deferred_name, ':'); + if (!attr) + attr = deferred_name; + + /* Find the attribute itself. */ + mapping *m = (mapping *) htab_find (codes.attrs, &attr); + if (!m) + fatal_with_file_and_line ("unknown code attribute `%s'", attr); + + /* Pick the first possible code for now, and record the attribute + use for later. */ + rtx x = rtx_alloc (check_code_attribute (m)); + record_attribute_use (&codes, x, 0, deferred_name); + return x; + } + + mapping *iterator = (mapping *) htab_find (codes.iterators, &name); + if (iterator != 0) + { + /* Pick the first possible code for now, and record the iterator + use for later. */ + rtx x = rtx_alloc (rtx_code (iterator->values->number)); + record_iterator_use (iterator, x, 0); + return x; + } +#endif + + return rtx_alloc (rtx_code (codes.find_builtin (name))); +} + /* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of either an rtx code or a code iterator. Parse the rest of the rtx and return it. */ @@ -1475,7 +1562,6 @@ rtx rtx_reader::read_rtx_code (const char *code_name) { RTX_CODE code; - struct mapping *iterator = NULL; const char *format_ptr; struct md_name name; rtx return_rtx; @@ -1509,20 +1595,9 @@ rtx_reader::read_rtx_code (const char *code_name) return return_rtx; } - /* If this code is an iterator, build the rtx using the iterator's - first value. */ -#ifdef GENERATOR_FILE - iterator = (struct mapping *) htab_find (codes.iterators, &code_name); - if (iterator != 0) - code = (enum rtx_code) iterator->values->number; - else - code = (enum rtx_code) codes.find_builtin (code_name); -#else - code = (enum rtx_code) codes.find_builtin (code_name); -#endif - /* If we end up with an insn expression then we free this space below. */ - return_rtx = rtx_alloc (code); + return_rtx = rtx_alloc_for_name (code_name); + code = GET_CODE (return_rtx); format_ptr = GET_RTX_FORMAT (code); memset (return_rtx, 0, RTX_CODE_SIZE (code)); PUT_CODE (return_rtx, code); @@ -1534,9 +1609,6 @@ rtx_reader::read_rtx_code (const char *code_name) m_reuse_rtx_by_id[reuse_id] = return_rtx; } - if (iterator) - record_iterator_use (iterator, return_rtx, 0); - /* Check for flags. */ read_flags (return_rtx);