diff options
author | David Malcolm <dmalcolm@redhat.com> | 2017-01-05 19:32:09 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2017-01-05 19:32:09 +0000 |
commit | 51b861137ed73ae73e15a136949301fbaaf89202 (patch) | |
tree | fd9bdb64e3920b3c35272969864ac5576f4fdad5 /gcc/read-rtl.c | |
parent | 7f86d7de6b80f68a47fc48f82af1a3ec9dbda21a (diff) |
Introduce RTL function reader
This is the combination of these patches:
- [8a/9] Introduce class function_reader (v8)
- Add ASSERT_RTX_PTR_EQ
- [8b/9] Add target-independent selftests of RTL function reader (v2)
- [8c/9] Add aarch64-specific selftests for RTL function reader (v2)
- [8d/9] Add x86_64-specific selftests for RTL function reader (v2)
gcc/ChangeLog:
* Makefile.in (OBJS): Add read-md.o, read-rtl.o,
read-rtl-function.o, and selftest-rtl.o.
* config/aarch64/aarch64.c: Include selftest.h and
selftest-rtl.h.
(selftest::aarch64_test_loading_full_dump): New function.
(selftest::aarch64_run_selftests): New function.
(TARGET_RUN_TARGET_SELFTESTS): Wire it up to
selftest::aarch64_run_selftests.
* config/i386/i386.c
(selftest::ix86_test_loading_dump_fragment_1): New function.
(selftest::ix86_test_loading_call_insn): New function.
(selftest::ix86_test_loading_full_dump): New function.
(selftest::ix86_test_loading_unspec): New function.
(selftest::ix86_run_selftests): Call the new functions.
* emit-rtl.c (maybe_set_max_label_num): New function.
* emit-rtl.h (maybe_set_max_label_num): New decl.
* function.c (instantiate_decls): Guard call to
instantiate_decls_1 with if (DECL_INITIAL (fndecl)).
* function-tests.c (selftest::verify_three_block_rtl_cfg): Remove
"static".
* gensupport.c (gen_reader::gen_reader): Pass "false"
for new "compact" param of rtx_reader.
* print-rtl.c (rtx_writer::print_rtx_operand): Print "(nil)"
rather than an empty string for NULL strings.
* read-md.c: Potentially include config.h rather than bconfig.h.
Wrap include of errors.h with #ifdef GENERATOR_FILE.
(have_error): New global, copied from errors.c.
(md_reader::read_name): Rename to...
(md_reader::read_name_1): ...this, adding "out_loc" param,
and converting "missing name or number" to returning false, rather
than failing.
(md_reader::read_name): Reimplement in terms of read_name_1.
(md_reader::read_name_or_nil): New function.
(md_reader::read_string): Handle "(nil)" by returning NULL.
(md_reader::md_reader): Add new param "compact".
(md_reader::read_md_files): Wrap with #ifdef GENERATOR_FILE.
(md_reader::read_file): New method.
* read-md.h (md_reader::md_reader): Add new param "compact".
(md_reader::read_file): New method.
(md_reader::is_compact): New accessor.
(md_reader::read_name): Convert return type from void to
file_location.
(md_reader::read_name_or_nil): New decl.
(md_reader::read_name_1): New decl.
(md_reader::m_compact): New field.
(noop_reader::noop_reader): Pass "false" for new "compact" param
of rtx_reader.
(rtx_reader::rtx_reader): Add new "compact" param.
(rtx_reader::read_rtx_operand): Make virtual and convert return
type from void to rtx.
(rtx_reader::read_until): New decl.
(rtx_reader::handle_any_trailing_information): New virtual
function.
(rtx_reader::postprocess): New virtual function.
(rtx_reader::finalize_string): New virtual function.
(rtx_reader::m_in_call_function_usage): New field.
(rtx_reader::m_reuse_rtx_by_id): New field.
* read-rtl-function.c: New file.
* selftest-rtl.c (selftest::assert_rtx_ptr_eq_at): New function.
* selftest-rtl.h (ASSERT_RTX_PTR_EQ): New macro.
(selftest::verify_three_block_rtl_cfg): New decl.
* read-rtl-function.h: New file.
* read-rtl.c: Potentially include config.h rather than bconfig.h.
For host, include function.h, memmodel.h, and emit-rtl.h.
(one_time_initialization): New function.
(struct compact_insn_name): New struct.
(compact_insn_names): New array.
(find_code): Handle insn codes in compact dumps.
(apply_subst_iterator): Wrap with #ifdef GENERATOR_FILE.
(bind_subst_iter_and_attr): Likewise.
(add_condition_to_string): Likewise.
(add_condition_to_rtx): Likewise.
(apply_attribute_uses): Likewise.
(add_current_iterators): Likewise.
(apply_iterators): Likewise.
(initialize_iterators): Guard usage of apply_subst_iterator with
#ifdef GENERATOR_FILE.
(read_conditions): Wrap with #ifdef GENERATOR_FILE.
(md_reader::read_mapping): Likewise.
(add_define_attr_for_define_subst): Likewise.
(add_define_subst_attr): Likewise.
(read_subst_mapping): Likewise.
(check_code_iterator): Likewise.
(rtx_reader::read_rtx): Likewise. Move one-time initialization
logic to...
(one_time_initialization): New function.
(rtx_reader::read_until): New method.
(read_flags): New function.
(parse_reg_note_name): New function.
(rtx_reader::read_rtx_code): Initialize "iterator" to NULL.
Handle reuse_rtx ids.
Wrap iterator lookup within #ifdef GENERATOR_FILE.
Add parsing support for RTL dumps, mirroring the special-cases in
print_rtx, by calling read_flags, reading REG_NOTE names, INSN_UID
values, and calling handle_any_trailing_information.
(rtx_reader::read_rtx_operand): Convert return type from void
to rtx, returning return_rtx. Handle case 'e'. Call
finalize_string on XSTR and XTMPL fields.
(rtx_reader::read_nested_rtx): Handle dumps in which trailing
"(nil)" values were omitted. Call the postprocess vfunc on the
return_rtx.
(rtx_reader::rtx_reader): Add new "compact" param and pass to base
class ctor. Initialize m_in_call_function_usage. Call
one_time_initialization.
* rtl-tests.c (selftest::test_uncond_jump): Call
set_new_first_and_last_insn.
* rtl.h (read_rtx): Wrap decl with #ifdef GENERATOR_FILE.
* selftest-rtl.c: New file.
* selftest-rtl.h (class selftest::rtl_dump_test): New class.
(selftest::get_insn_by_uid): New decl.
* selftest-run-tests.c (selftest::run_tests): Call
read_rtl_function_c_tests.
* selftest.h (selftest::read_rtl_function_c_tests): New decl.
* tree-dfa.c (ssa_default_def): Return NULL_TREE for rtl function
dumps.
gcc/testsuite/ChangeLog:
* selftests/asr_div1.rtl: New file.
* selftests/aarch64: New subdirectory.
* selftests/aarch64/times-two.rtl: New file.
* selftests/bb-index.rtl: New file.
* selftests/cfg-test.rtl: New file.
* selftests/const-int.rtl: New file.
* selftests/example-labels.rtl: New file.
* selftests/insn-with-mode.rtl: New file.
* selftests/jump-to-label-ref.rtl: New file.
* selftests/jump-to-return.rtl: New file.
* selftests/jump-to-simple-return.rtl: New file.
* selftests/mem.rtl: New file.
* selftests/note-insn-deleted.rtl: New file.
* selftests/note_insn_basic_block.rtl: New file.
* selftests/simple-cse.rtl: New file.
* selftests/symbol-ref.rtl: New file.
* selftests/x86_64: New subdirectory.
* selftests/x86_64/call-insn.rtl: New file.
* selftests/x86_64/copy-hard-reg-into-frame.rtl: New file.
* selftests/x86_64/times-two.rtl: New file.
* selftests/x86_64/unspec.rtl: New file.
From-SVN: r244110
Diffstat (limited to 'gcc/read-rtl.c')
-rw-r--r-- | gcc/read-rtl.c | 260 |
1 files changed, 242 insertions, 18 deletions
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index a08ce5c9f08..e9c80682800 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -17,7 +17,13 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* This file is compiled twice: once for the generator programs + once for the compiler. */ +#ifdef GENERATOR_FILE #include "bconfig.h" +#else +#include "config.h" +#endif /* Disable rtl checking; it conflicts with the iterator handling. */ #undef ENABLE_RTL_CHECKING @@ -30,6 +36,12 @@ along with GCC; see the file COPYING3. If not see #include "read-md.h" #include "gensupport.h" +#ifndef GENERATOR_FILE +#include "function.h" +#include "memmodel.h" +#include "emit-rtl.h" +#endif + /* One element in a singly-linked list of (integer, string) pairs. */ struct map_value { struct map_value *next; @@ -106,6 +118,7 @@ htab_t subst_attr_to_iter_map = NULL; const char *current_iterator_name; static void validate_const_int (const char *); +static void one_time_initialization (void); /* Global singleton. */ rtx_reader *rtx_reader_ptr = NULL; @@ -142,6 +155,25 @@ apply_mode_iterator (void *loc, int mode) PUT_MODE ((rtx) loc, (machine_mode) mode); } +/* In compact dumps, the code of insns is prefixed with "c", giving "cinsn", + "cnote" etc, and CODE_LABEL is special-cased as "clabel". */ + +struct compact_insn_name { + RTX_CODE code; + const char *name; +}; + +static const compact_insn_name compact_insn_names[] = { + { DEBUG_INSN, "cdebug_insn" }, + { INSN, "cinsn" }, + { JUMP_INSN, "cjump_insn" }, + { CALL_INSN, "ccall_insn" }, + { JUMP_TABLE_DATA, "cjump_table_data" }, + { BARRIER, "cbarrier" }, + { CODE_LABEL, "clabel" }, + { NOTE, "cnote" } +}; + /* Implementations of the iterator_group callbacks for codes. */ static int @@ -153,6 +185,10 @@ find_code (const char *name) if (strcmp (GET_RTX_NAME (i), name) == 0) return i; + for (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); } @@ -181,6 +217,8 @@ apply_int_iterator (void *loc, int value) *(int *)loc = value; } +#ifdef GENERATOR_FILE + /* This routine adds attribute or does nothing depending on VALUE. When VALUE is 1, it does nothing - the first duplicate of original template is kept untouched when it's subjected to a define_subst. @@ -252,6 +290,8 @@ bind_subst_iter_and_attr (const char *iter, const char *attr) *slot = value; } +#endif /* #ifdef GENERATOR_FILE */ + /* Return name of a subst-iterator, corresponding to subst-attribute ATTR. */ static char* @@ -418,6 +458,8 @@ md_reader::copy_rtx_for_iterators (rtx original) return x; } +#ifdef GENERATOR_FILE + /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL has the form "&& ..." (as used in define_insn_and_splits), assume that EXTRA is already satisfied. Empty strings are treated like "true". */ @@ -581,6 +623,7 @@ apply_iterators (rtx original, vec<rtx> *queue) } } } +#endif /* #ifdef GENERATOR_FILE */ /* Add a new "mapping" structure to hashtable TABLE. NAME is the name of the mapping and GROUP is the group to which it belongs. */ @@ -655,7 +698,9 @@ initialize_iterators (void) substs.iterators = htab_create (13, leading_string_hash, leading_string_eq_p, 0); substs.find_builtin = find_int; /* We don't use it, anyway. */ +#ifdef GENERATOR_FILE substs.apply_iterator = apply_subst_iterator; +#endif lower = add_mapping (&modes, modes.attrs, "mode"); upper = add_mapping (&modes, modes.attrs, "MODE"); @@ -724,6 +769,8 @@ atoll (const char *p) } #endif + +#ifdef GENERATOR_FILE /* Process a define_conditions directive, starting with the optional space after the "define_conditions". The directive looks like this: @@ -765,6 +812,7 @@ md_reader::read_conditions () add_c_test (expr, value); } } +#endif /* #ifdef GENERATOR_FILE */ static void validate_const_int (const char *string) @@ -861,6 +909,8 @@ md_reader::record_potential_iterator_use (struct iterator_group *group, } } +#ifdef GENERATOR_FILE + /* Finish reading a declaration of the form: (define... <name> [<value1> ... <valuen>]) @@ -1020,15 +1070,6 @@ check_code_iterator (struct mapping *iterator) bool rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen) { - static bool initialized = false; - - /* Do one-time initialization. */ - if (!initialized) - { - initialize_iterators (); - initialized = true; - } - /* Handle various rtx-related declarations that aren't themselves encoded as rtxes. */ if (strcmp (rtx_name, "define_conditions") == 0) @@ -1082,6 +1123,103 @@ rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen) return true; } +#endif /* #ifdef GENERATOR_FILE */ + +/* Do one-time initialization. */ + +static void +one_time_initialization (void) +{ + static bool initialized = false; + + if (!initialized) + { + initialize_iterators (); + initialized = true; + } +} + +/* Consume characters until encountering a character in TERMINATOR_CHARS, + consuming the terminator character if CONSUME_TERMINATOR is true. + Return all characters before the terminator as an allocated buffer. */ + +char * +rtx_reader::read_until (const char *terminator_chars, bool consume_terminator) +{ + int ch = read_skip_spaces (); + unread_char (ch); + auto_vec<char> buf; + while (1) + { + ch = read_char (); + if (strchr (terminator_chars, ch)) + { + if (!consume_terminator) + unread_char (ch); + break; + } + buf.safe_push (ch); + } + buf.safe_push ('\0'); + return xstrdup (buf.address ()); +} + +/* Subroutine of read_rtx_code, for parsing zero or more flags. */ + +static void +read_flags (rtx return_rtx) +{ + while (1) + { + int ch = read_char (); + if (ch != '/') + { + unread_char (ch); + break; + } + + int flag_char = read_char (); + switch (flag_char) + { + case 's': + RTX_FLAG (return_rtx, in_struct) = 1; + break; + case 'v': + RTX_FLAG (return_rtx, volatil) = 1; + break; + case 'u': + RTX_FLAG (return_rtx, unchanging) = 1; + break; + case 'f': + RTX_FLAG (return_rtx, frame_related) = 1; + break; + case 'j': + RTX_FLAG (return_rtx, jump) = 1; + break; + case 'c': + RTX_FLAG (return_rtx, call) = 1; + break; + case 'i': + RTX_FLAG (return_rtx, return_val) = 1; + break; + default: + fatal_with_file_and_line ("unrecognized flag: `%c'", flag_char); + } + } +} + +/* Return the numeric value n for GET_REG_NOTE_NAME (n) for STRING, + or fail if STRING isn't recognized. */ + +static int +parse_reg_note_name (const char *string) +{ + for (int i = 0; i < REG_NOTE_MAX; i++) + if (0 == strcmp (string, GET_REG_NOTE_NAME (i))) + return i; + fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string); +} + /* 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. */ @@ -1090,11 +1228,12 @@ rtx rtx_reader::read_rtx_code (const char *code_name) { RTX_CODE code; - struct mapping *iterator; + struct mapping *iterator = NULL; const char *format_ptr; struct md_name name; rtx return_rtx; int c; + long reuse_id = -1; /* Linked list structure for making RTXs: */ struct rtx_list @@ -1103,13 +1242,37 @@ rtx_reader::read_rtx_code (const char *code_name) rtx value; /* Value of this node. */ }; + /* Handle reuse_rtx ids e.g. "(0|scratch:DI)". */ + if (ISDIGIT (code_name[0])) + { + reuse_id = atoi (code_name); + while (char ch = *code_name++) + if (ch == '|') + break; + } + + /* Handle "reuse_rtx". */ + if (strcmp (code_name, "reuse_rtx") == 0) + { + read_name (&name); + long idx = atoi (name.string); + /* Look it up by ID. */ + gcc_assert (idx < m_reuse_rtx_by_id.length ()); + return_rtx = m_reuse_rtx_by_id[idx]; + 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); @@ -1117,9 +1280,36 @@ rtx_reader::read_rtx_code (const char *code_name) memset (return_rtx, 0, RTX_CODE_SIZE (code)); PUT_CODE (return_rtx, code); + if (reuse_id != -1) + { + /* Store away for later reuse. */ + m_reuse_rtx_by_id.safe_grow_cleared (reuse_id + 1); + m_reuse_rtx_by_id[reuse_id] = return_rtx; + } + if (iterator) record_iterator_use (iterator, return_rtx); + /* Check for flags. */ + read_flags (return_rtx); + + /* Read REG_NOTE names for EXPR_LIST and INSN_LIST. */ + if ((GET_CODE (return_rtx) == EXPR_LIST + || GET_CODE (return_rtx) == INSN_LIST + || GET_CODE (return_rtx) == INT_LIST) + && !m_in_call_function_usage) + { + char ch = read_char (); + if (ch == ':') + { + read_name (&name); + PUT_MODE_RAW (return_rtx, + (machine_mode)parse_reg_note_name (name.string)); + } + else + unread_char (ch); + } + /* If what follows is `: mode ', read it and store the mode in the rtx. */ @@ -1132,8 +1322,19 @@ rtx_reader::read_rtx_code (const char *code_name) else unread_char (c); + if (INSN_CHAIN_CODE_P (code)) + { + read_name (&name); + INSN_UID (return_rtx) = atoi (name.string); + } + + /* Use the format_ptr to parse the various operands of this rtx. */ for (int idx = 0; format_ptr[idx] != 0; idx++) - read_rtx_operand (return_rtx, idx); + return_rtx = read_rtx_operand (return_rtx, idx); + + /* Handle any additional information that after the regular fields + (e.g. when parsing function dumps). */ + handle_any_trailing_information (return_rtx); if (CONST_WIDE_INT_P (return_rtx)) { @@ -1197,9 +1398,11 @@ rtx_reader::read_rtx_code (const char *code_name) /* Subroutine of read_rtx_code. Parse operand IDX within RETURN_RTX, based on the corresponding format character within GET_RTX_FORMAT - for the GET_CODE (RETURN_RTX). */ + for the GET_CODE (RETURN_RTX), and return RETURN_RTX. + This is a virtual function, so that function_reader can override + some parsing, and potentially return a different rtx. */ -void +rtx rtx_reader::read_rtx_operand (rtx return_rtx, int idx) { RTX_CODE code = GET_CODE (return_rtx); @@ -1217,6 +1420,9 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) break; case 'e': + XEXP (return_rtx, idx) = read_nested_rtx (); + break; + case 'u': XEXP (return_rtx, idx) = read_nested_rtx (); break; @@ -1273,7 +1479,6 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) { char *stringbuf; int star_if_braced; - struct obstack *string_obstack = get_string_obstack (); c = read_skip_spaces (); unread_char (c); @@ -1293,7 +1498,10 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) star_if_braced = (format_ptr[idx] == 'T'); stringbuf = read_string (star_if_braced); + if (!stringbuf) + break; +#ifdef GENERATOR_FILE /* For insn patterns, we want to provide a default name based on the file and line, like "*foo.md:12", if the given name is blank. These are only for define_insn and @@ -1303,6 +1511,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) && (GET_CODE (return_rtx) == DEFINE_INSN || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) { + struct obstack *string_obstack = get_string_obstack (); char line_name[20]; const char *read_md_filename = get_filename (); const char *fn = (read_md_filename ? read_md_filename : "rtx"); @@ -1348,11 +1557,14 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) if (m != 0) record_iterator_use (m, return_rtx); } +#endif /* #ifdef GENERATOR_FILE */ + + const char *string_ptr = finalize_string (stringbuf); if (star_if_braced) - XTMPL (return_rtx, idx) = stringbuf; + XTMPL (return_rtx, idx) = string_ptr; else - XSTR (return_rtx, idx) = stringbuf; + XSTR (return_rtx, idx) = string_ptr; } break; @@ -1398,6 +1610,8 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) default: gcc_unreachable (); } + + return return_rtx; } /* Read a nested rtx construct from the MD file and return it. */ @@ -1408,6 +1622,11 @@ rtx_reader::read_nested_rtx () struct md_name name; rtx return_rtx; + /* In compact dumps, trailing "(nil)" values can be omitted. + Handle such dumps. */ + if (peek_char () == ')') + return NULL_RTX; + require_char_ws ('('); read_name (&name); @@ -1418,6 +1637,8 @@ rtx_reader::read_nested_rtx () require_char_ws (')'); + return_rtx = postprocess (return_rtx); + return return_rtx; } @@ -1454,11 +1675,14 @@ rtx_reader::read_rtx_variadic (rtx form) /* Constructor for class rtx_reader. */ -rtx_reader::rtx_reader () -: md_reader () +rtx_reader::rtx_reader (bool compact) +: md_reader (compact), + m_in_call_function_usage (false) { /* Set the global singleton pointer. */ rtx_reader_ptr = this; + + one_time_initialization (); } /* Destructor for class rtx_reader. */ |