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
This commit is contained in:
parent
7f86d7de6b
commit
51b861137e
118
gcc/ChangeLog
118
gcc/ChangeLog
@ -1,3 +1,121 @@
|
||||
2017-01-05 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2017-01-05 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/i386.md (*testqi_ext_3): No need to handle memory
|
||||
|
@ -1420,6 +1420,9 @@ OBJS = \
|
||||
print-rtl-function.o \
|
||||
print-tree.o \
|
||||
profile.o \
|
||||
read-md.o \
|
||||
read-rtl.o \
|
||||
read-rtl-function.o \
|
||||
real.o \
|
||||
realmpfr.o \
|
||||
recog.o \
|
||||
@ -1447,6 +1450,7 @@ OBJS = \
|
||||
sel-sched-ir.o \
|
||||
sel-sched-dump.o \
|
||||
sel-sched.o \
|
||||
selftest-rtl.o \
|
||||
selftest-run-tests.o \
|
||||
sese.o \
|
||||
shrink-wrap.o \
|
||||
|
@ -64,6 +64,8 @@
|
||||
#include "sched-int.h"
|
||||
#include "target-globals.h"
|
||||
#include "common/common-target.h"
|
||||
#include "selftest.h"
|
||||
#include "selftest-rtl.h"
|
||||
|
||||
/* This file should be included last. */
|
||||
#include "target-def.h"
|
||||
@ -14605,6 +14607,52 @@ aarch64_excess_precision (enum excess_precision_type type)
|
||||
return FLT_EVAL_METHOD_UNPREDICTABLE;
|
||||
}
|
||||
|
||||
/* Target-specific selftests. */
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
/* Selftest for the RTL loader.
|
||||
Verify that the RTL loader copes with a dump from
|
||||
print_rtx_function. This is essentially just a test that class
|
||||
function_reader can handle a real dump, but it also verifies
|
||||
that lookup_reg_by_dump_name correctly handles hard regs.
|
||||
The presence of hard reg names in the dump means that the test is
|
||||
target-specific, hence it is in this file. */
|
||||
|
||||
static void
|
||||
aarch64_test_loading_full_dump ()
|
||||
{
|
||||
rtl_dump_test t (SELFTEST_LOCATION, locate_file ("aarch64/times-two.rtl"));
|
||||
|
||||
ASSERT_STREQ ("times_two", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
|
||||
|
||||
rtx_insn *insn_1 = get_insn_by_uid (1);
|
||||
ASSERT_EQ (NOTE, GET_CODE (insn_1));
|
||||
|
||||
rtx_insn *insn_15 = get_insn_by_uid (15);
|
||||
ASSERT_EQ (INSN, GET_CODE (insn_15));
|
||||
ASSERT_EQ (USE, GET_CODE (PATTERN (insn_15)));
|
||||
|
||||
/* Verify crtl->return_rtx. */
|
||||
ASSERT_EQ (REG, GET_CODE (crtl->return_rtx));
|
||||
ASSERT_EQ (0, REGNO (crtl->return_rtx));
|
||||
ASSERT_EQ (SImode, GET_MODE (crtl->return_rtx));
|
||||
}
|
||||
|
||||
/* Run all target-specific selftests. */
|
||||
|
||||
static void
|
||||
aarch64_run_selftests (void)
|
||||
{
|
||||
aarch64_test_loading_full_dump ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
#undef TARGET_ADDRESS_COST
|
||||
#define TARGET_ADDRESS_COST aarch64_address_cost
|
||||
|
||||
@ -14977,6 +15025,11 @@ aarch64_libgcc_floating_mode_supported_p
|
||||
#undef TARGET_OMIT_STRUCT_RETURN_REG
|
||||
#define TARGET_OMIT_STRUCT_RETURN_REG true
|
||||
|
||||
#if CHECKING_P
|
||||
#undef TARGET_RUN_TARGET_SELFTESTS
|
||||
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
#include "gt-aarch64.h"
|
||||
|
@ -51206,6 +51206,209 @@ ix86_test_dumping_memory_blockage ()
|
||||
" ] UNSPEC_MEMORY_BLOCKAGE)))\n", pat, &r);
|
||||
}
|
||||
|
||||
/* Verify loading an RTL dump; specifically a dump of copying
|
||||
a param on x86_64 from a hard reg into the frame.
|
||||
This test is target-specific since the dump contains target-specific
|
||||
hard reg names. */
|
||||
|
||||
static void
|
||||
ix86_test_loading_dump_fragment_1 ()
|
||||
{
|
||||
rtl_dump_test t (SELFTEST_LOCATION,
|
||||
locate_file ("x86_64/copy-hard-reg-into-frame.rtl"));
|
||||
|
||||
rtx_insn *insn = get_insn_by_uid (1);
|
||||
|
||||
/* The block structure and indentation here is purely for
|
||||
readability; it mirrors the structure of the rtx. */
|
||||
tree mem_expr;
|
||||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
ASSERT_EQ (SET, GET_CODE (pat));
|
||||
{
|
||||
rtx dest = SET_DEST (pat);
|
||||
ASSERT_EQ (MEM, GET_CODE (dest));
|
||||
/* Verify the "/c" was parsed. */
|
||||
ASSERT_TRUE (RTX_FLAG (dest, call));
|
||||
ASSERT_EQ (SImode, GET_MODE (dest));
|
||||
{
|
||||
rtx addr = XEXP (dest, 0);
|
||||
ASSERT_EQ (PLUS, GET_CODE (addr));
|
||||
ASSERT_EQ (DImode, GET_MODE (addr));
|
||||
{
|
||||
rtx lhs = XEXP (addr, 0);
|
||||
/* Verify that the "frame" REG was consolidated. */
|
||||
ASSERT_RTX_PTR_EQ (frame_pointer_rtx, lhs);
|
||||
}
|
||||
{
|
||||
rtx rhs = XEXP (addr, 1);
|
||||
ASSERT_EQ (CONST_INT, GET_CODE (rhs));
|
||||
ASSERT_EQ (-4, INTVAL (rhs));
|
||||
}
|
||||
}
|
||||
/* Verify the "[1 i+0 S4 A32]" was parsed. */
|
||||
ASSERT_EQ (1, MEM_ALIAS_SET (dest));
|
||||
/* "i" should have been handled by synthesizing a global int
|
||||
variable named "i". */
|
||||
mem_expr = MEM_EXPR (dest);
|
||||
ASSERT_NE (mem_expr, NULL);
|
||||
ASSERT_EQ (VAR_DECL, TREE_CODE (mem_expr));
|
||||
ASSERT_EQ (integer_type_node, TREE_TYPE (mem_expr));
|
||||
ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (DECL_NAME (mem_expr)));
|
||||
ASSERT_STREQ ("i", IDENTIFIER_POINTER (DECL_NAME (mem_expr)));
|
||||
/* "+0". */
|
||||
ASSERT_TRUE (MEM_OFFSET_KNOWN_P (dest));
|
||||
ASSERT_EQ (0, MEM_OFFSET (dest));
|
||||
/* "S4". */
|
||||
ASSERT_EQ (4, MEM_SIZE (dest));
|
||||
/* "A32. */
|
||||
ASSERT_EQ (32, MEM_ALIGN (dest));
|
||||
}
|
||||
{
|
||||
rtx src = SET_SRC (pat);
|
||||
ASSERT_EQ (REG, GET_CODE (src));
|
||||
ASSERT_EQ (SImode, GET_MODE (src));
|
||||
ASSERT_EQ (5, REGNO (src));
|
||||
tree reg_expr = REG_EXPR (src);
|
||||
/* "i" here should point to the same var as for the MEM_EXPR. */
|
||||
ASSERT_EQ (reg_expr, mem_expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that the RTL loader copes with a call_insn dump.
|
||||
This test is target-specific since the dump contains a target-specific
|
||||
hard reg name. */
|
||||
|
||||
static void
|
||||
ix86_test_loading_call_insn ()
|
||||
{
|
||||
/* The test dump includes register "xmm0", where requires TARGET_SSE
|
||||
to exist. */
|
||||
if (!TARGET_SSE)
|
||||
return;
|
||||
|
||||
rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/call-insn.rtl"));
|
||||
|
||||
rtx_insn *insn = get_insns ();
|
||||
ASSERT_EQ (CALL_INSN, GET_CODE (insn));
|
||||
|
||||
/* "/j". */
|
||||
ASSERT_TRUE (RTX_FLAG (insn, jump));
|
||||
|
||||
rtx pat = PATTERN (insn);
|
||||
ASSERT_EQ (CALL, GET_CODE (SET_SRC (pat)));
|
||||
|
||||
/* Verify REG_NOTES. */
|
||||
{
|
||||
/* "(expr_list:REG_CALL_DECL". */
|
||||
ASSERT_EQ (EXPR_LIST, GET_CODE (REG_NOTES (insn)));
|
||||
rtx_expr_list *note0 = as_a <rtx_expr_list *> (REG_NOTES (insn));
|
||||
ASSERT_EQ (REG_CALL_DECL, REG_NOTE_KIND (note0));
|
||||
|
||||
/* "(expr_list:REG_EH_REGION (const_int 0 [0])". */
|
||||
rtx_expr_list *note1 = note0->next ();
|
||||
ASSERT_EQ (REG_EH_REGION, REG_NOTE_KIND (note1));
|
||||
|
||||
ASSERT_EQ (NULL, note1->next ());
|
||||
}
|
||||
|
||||
/* Verify CALL_INSN_FUNCTION_USAGE. */
|
||||
{
|
||||
/* "(expr_list:DF (use (reg:DF 21 xmm0))". */
|
||||
rtx_expr_list *usage
|
||||
= as_a <rtx_expr_list *> (CALL_INSN_FUNCTION_USAGE (insn));
|
||||
ASSERT_EQ (EXPR_LIST, GET_CODE (usage));
|
||||
ASSERT_EQ (DFmode, GET_MODE (usage));
|
||||
ASSERT_EQ (USE, GET_CODE (usage->element ()));
|
||||
ASSERT_EQ (NULL, usage->next ());
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that the RTL loader copes a dump from print_rtx_function.
|
||||
This test is target-specific since the dump contains target-specific
|
||||
hard reg names. */
|
||||
|
||||
static void
|
||||
ix86_test_loading_full_dump ()
|
||||
{
|
||||
rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/times-two.rtl"));
|
||||
|
||||
ASSERT_STREQ ("times_two", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
|
||||
|
||||
rtx_insn *insn_1 = get_insn_by_uid (1);
|
||||
ASSERT_EQ (NOTE, GET_CODE (insn_1));
|
||||
|
||||
rtx_insn *insn_7 = get_insn_by_uid (7);
|
||||
ASSERT_EQ (INSN, GET_CODE (insn_7));
|
||||
ASSERT_EQ (PARALLEL, GET_CODE (PATTERN (insn_7)));
|
||||
|
||||
rtx_insn *insn_15 = get_insn_by_uid (15);
|
||||
ASSERT_EQ (INSN, GET_CODE (insn_15));
|
||||
ASSERT_EQ (USE, GET_CODE (PATTERN (insn_15)));
|
||||
|
||||
/* Verify crtl->return_rtx. */
|
||||
ASSERT_EQ (REG, GET_CODE (crtl->return_rtx));
|
||||
ASSERT_EQ (0, REGNO (crtl->return_rtx));
|
||||
ASSERT_EQ (SImode, GET_MODE (crtl->return_rtx));
|
||||
}
|
||||
|
||||
/* Verify that the RTL loader copes with UNSPEC and UNSPEC_VOLATILE insns.
|
||||
In particular, verify that it correctly loads the 2nd operand.
|
||||
This test is target-specific since these are machine-specific
|
||||
operands (and enums). */
|
||||
|
||||
static void
|
||||
ix86_test_loading_unspec ()
|
||||
{
|
||||
rtl_dump_test t (SELFTEST_LOCATION, locate_file ("x86_64/unspec.rtl"));
|
||||
|
||||
ASSERT_STREQ ("test_unspec", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
|
||||
|
||||
ASSERT_TRUE (cfun);
|
||||
|
||||
/* Test of an UNSPEC. */
|
||||
rtx_insn *insn = get_insns ();
|
||||
ASSERT_EQ (INSN, GET_CODE (insn));
|
||||
rtx set = single_set (insn);
|
||||
ASSERT_NE (NULL, set);
|
||||
rtx dst = SET_DEST (set);
|
||||
ASSERT_EQ (MEM, GET_CODE (dst));
|
||||
rtx src = SET_SRC (set);
|
||||
ASSERT_EQ (UNSPEC, GET_CODE (src));
|
||||
ASSERT_EQ (BLKmode, GET_MODE (src));
|
||||
ASSERT_EQ (UNSPEC_MEMORY_BLOCKAGE, XINT (src, 1));
|
||||
|
||||
rtx v0 = XVECEXP (src, 0, 0);
|
||||
|
||||
/* Verify that the two uses of the first SCRATCH have pointer
|
||||
equality. */
|
||||
rtx scratch_a = XEXP (dst, 0);
|
||||
ASSERT_EQ (SCRATCH, GET_CODE (scratch_a));
|
||||
|
||||
rtx scratch_b = XEXP (v0, 0);
|
||||
ASSERT_EQ (SCRATCH, GET_CODE (scratch_b));
|
||||
|
||||
ASSERT_EQ (scratch_a, scratch_b);
|
||||
|
||||
/* Verify that the two mems are thus treated as equal. */
|
||||
ASSERT_TRUE (rtx_equal_p (dst, v0));
|
||||
|
||||
/* Verify the the insn is recognized. */
|
||||
ASSERT_NE(-1, recog_memoized (insn));
|
||||
|
||||
/* Test of an UNSPEC_VOLATILE, which has its own enum values. */
|
||||
insn = NEXT_INSN (insn);
|
||||
ASSERT_EQ (INSN, GET_CODE (insn));
|
||||
|
||||
set = single_set (insn);
|
||||
ASSERT_NE (NULL, set);
|
||||
|
||||
src = SET_SRC (set);
|
||||
ASSERT_EQ (UNSPEC_VOLATILE, GET_CODE (src));
|
||||
ASSERT_EQ (UNSPECV_RDTSCP, XINT (src, 1));
|
||||
}
|
||||
|
||||
/* Run all target-specific selftests. */
|
||||
|
||||
static void
|
||||
@ -51213,6 +51416,13 @@ ix86_run_selftests (void)
|
||||
{
|
||||
ix86_test_dumping_hard_regs ();
|
||||
ix86_test_dumping_memory_blockage ();
|
||||
|
||||
/* Various tests of loading RTL dumps, here because they contain
|
||||
ix86-isms (e.g. names of hard regs). */
|
||||
ix86_test_loading_dump_fragment_1 ();
|
||||
ix86_test_loading_call_insn ();
|
||||
ix86_test_loading_full_dump ();
|
||||
ix86_test_loading_unspec ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
@ -1374,6 +1374,19 @@ maybe_set_first_label_num (rtx_code_label *x)
|
||||
if (CODE_LABEL_NUMBER (x) < first_label_num)
|
||||
first_label_num = CODE_LABEL_NUMBER (x);
|
||||
}
|
||||
|
||||
/* For use by the RTL function loader, when mingling with normal
|
||||
functions.
|
||||
Ensure that label_num is greater than the label num of X, to avoid
|
||||
duplicate labels in the generated assembler. */
|
||||
|
||||
void
|
||||
maybe_set_max_label_num (rtx_code_label *x)
|
||||
{
|
||||
if (CODE_LABEL_NUMBER (x) >= label_num)
|
||||
label_num = CODE_LABEL_NUMBER (x) + 1;
|
||||
}
|
||||
|
||||
|
||||
/* Return a value representing some low-order bits of X, where the number
|
||||
of low-order bits is given by MODE. Note that no conversion is done
|
||||
|
@ -510,4 +510,6 @@ extern int get_mem_align_offset (rtx, unsigned int);
|
||||
MODE and adjusted by OFFSET. */
|
||||
extern rtx widen_memory_access (rtx, machine_mode, HOST_WIDE_INT);
|
||||
|
||||
extern void maybe_set_max_label_num (rtx_code_label *x);
|
||||
|
||||
#endif /* GCC_EMIT_RTL_H */
|
||||
|
@ -421,7 +421,7 @@ verify_three_block_gimple_cfg (function *fun)
|
||||
|
||||
/* As above, but additionally verify the RTL insns are sane. */
|
||||
|
||||
static void
|
||||
void
|
||||
verify_three_block_rtl_cfg (function *fun)
|
||||
{
|
||||
verify_three_block_cfg (fun);
|
||||
|
@ -1909,7 +1909,8 @@ instantiate_decls (tree fndecl)
|
||||
instantiate_decl_rtl (DECL_RTL (DECL_VALUE_EXPR (decl)));
|
||||
|
||||
/* Now process all variables defined in the function or its subblocks. */
|
||||
instantiate_decls_1 (DECL_INITIAL (fndecl));
|
||||
if (DECL_INITIAL (fndecl))
|
||||
instantiate_decls_1 (DECL_INITIAL (fndecl));
|
||||
|
||||
FOR_EACH_LOCAL_DECL (cfun, ix, decl)
|
||||
if (DECL_RTL_SET_P (decl))
|
||||
|
@ -2233,7 +2233,7 @@ process_define_subst (void)
|
||||
class gen_reader : public rtx_reader
|
||||
{
|
||||
public:
|
||||
gen_reader () : rtx_reader () {}
|
||||
gen_reader () : rtx_reader (false) {}
|
||||
void handle_unknown_directive (file_location, const char *);
|
||||
};
|
||||
|
||||
|
@ -577,7 +577,7 @@ rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
|
||||
string:
|
||||
|
||||
if (str == 0)
|
||||
fputs (" \"\"", m_outfile);
|
||||
fputs (" (nil)", m_outfile);
|
||||
else
|
||||
fprintf (m_outfile, " (\"%s\")", str);
|
||||
m_sawclose = 1;
|
||||
|
@ -17,14 +17,32 @@ 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
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#ifdef GENERATOR_FILE
|
||||
#include "errors.h"
|
||||
#endif /* #ifdef GENERATOR_FILE */
|
||||
#include "statistics.h"
|
||||
#include "vec.h"
|
||||
#include "read-md.h"
|
||||
|
||||
#ifndef GENERATOR_FILE
|
||||
|
||||
/* Minimal reimplementation of errors.c for use by RTL frontend
|
||||
within cc1. */
|
||||
|
||||
int have_error = 0;
|
||||
|
||||
#endif /* #ifndef GENERATOR_FILE */
|
||||
|
||||
|
||||
/* Associates PTR (which can be a string, etc.) with the file location
|
||||
specified by FILENAME and LINENO. */
|
||||
struct ptr_loc {
|
||||
@ -424,8 +442,8 @@ md_reader::peek_char (void)
|
||||
/* Read an rtx code name into NAME. It is terminated by any of the
|
||||
punctuation chars of rtx printed syntax. */
|
||||
|
||||
void
|
||||
md_reader::read_name (struct md_name *name)
|
||||
bool
|
||||
md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
|
||||
{
|
||||
int c;
|
||||
size_t i;
|
||||
@ -433,6 +451,8 @@ md_reader::read_name (struct md_name *name)
|
||||
|
||||
c = read_skip_spaces ();
|
||||
|
||||
*out_loc = get_current_location ();
|
||||
|
||||
i = 0;
|
||||
angle_bracket_depth = 0;
|
||||
while (1)
|
||||
@ -464,7 +484,7 @@ md_reader::read_name (struct md_name *name)
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
fatal_with_file_and_line ("missing name or number");
|
||||
return false;
|
||||
|
||||
name->buffer[i] = 0;
|
||||
name->string = name->buffer;
|
||||
@ -485,6 +505,36 @@ md_reader::read_name (struct md_name *name)
|
||||
}
|
||||
while (def);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Read an rtx code name into NAME. It is terminated by any of the
|
||||
punctuation chars of rtx printed syntax. */
|
||||
|
||||
file_location
|
||||
md_reader::read_name (struct md_name *name)
|
||||
{
|
||||
file_location loc;
|
||||
if (!read_name_1 (name, &loc))
|
||||
fatal_with_file_and_line ("missing name or number");
|
||||
return loc;
|
||||
}
|
||||
|
||||
file_location
|
||||
md_reader::read_name_or_nil (struct md_name *name)
|
||||
{
|
||||
file_location loc;
|
||||
if (!read_name_1 (name, &loc))
|
||||
{
|
||||
file_location loc = get_current_location ();
|
||||
read_skip_construct (0, loc);
|
||||
/* Skip the ')'. */
|
||||
read_char ();
|
||||
name->buffer[0] = 0;
|
||||
name->string = name->buffer;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
/* Subroutine of the string readers. Handles backslash escapes.
|
||||
@ -630,6 +680,14 @@ md_reader::read_string (int star_if_braced)
|
||||
obstack_1grow (&m_string_obstack, '*');
|
||||
stringbuf = read_braced_string ();
|
||||
}
|
||||
else if (saw_paren && c == 'n')
|
||||
{
|
||||
/* Handle (nil) by returning NULL. */
|
||||
require_char ('i');
|
||||
require_char ('l');
|
||||
require_char_ws (')');
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
|
||||
|
||||
@ -924,8 +982,9 @@ md_reader::traverse_enum_types (htab_trav callback, void *info)
|
||||
|
||||
/* Constructor for md_reader. */
|
||||
|
||||
md_reader::md_reader ()
|
||||
: m_toplevel_fname (NULL),
|
||||
md_reader::md_reader (bool compact)
|
||||
: m_compact (compact),
|
||||
m_toplevel_fname (NULL),
|
||||
m_base_dir (NULL),
|
||||
m_read_md_file (NULL),
|
||||
m_read_md_filename (NULL),
|
||||
@ -1129,6 +1188,8 @@ md_reader::add_include_path (const char *arg)
|
||||
m_last_dir_md_include_ptr = &dirtmp->next;
|
||||
}
|
||||
|
||||
#ifdef GENERATOR_FILE
|
||||
|
||||
/* The main routine for reading .md files. Try to process all the .md
|
||||
files specified on the command line and return true if no error occurred.
|
||||
|
||||
@ -1235,6 +1296,24 @@ md_reader::read_md_files (int argc, const char **argv,
|
||||
return !have_error;
|
||||
}
|
||||
|
||||
#endif /* #ifdef GENERATOR_FILE */
|
||||
|
||||
/* Read FILENAME. */
|
||||
|
||||
bool
|
||||
md_reader::read_file (const char *filename)
|
||||
{
|
||||
m_read_md_filename = filename;
|
||||
m_read_md_file = fopen (m_read_md_filename, "r");
|
||||
if (m_read_md_file == 0)
|
||||
{
|
||||
perror (m_read_md_filename);
|
||||
return false;
|
||||
}
|
||||
handle_toplevel_file ();
|
||||
return !have_error;
|
||||
}
|
||||
|
||||
/* class noop_reader : public md_reader */
|
||||
|
||||
/* A dummy implementation which skips unknown directives. */
|
||||
|
@ -106,10 +106,11 @@ struct enum_type {
|
||||
class md_reader
|
||||
{
|
||||
public:
|
||||
md_reader ();
|
||||
md_reader (bool compact);
|
||||
virtual ~md_reader ();
|
||||
|
||||
bool read_md_files (int, const char **, bool (*) (const char *));
|
||||
bool read_file (const char *filename);
|
||||
|
||||
/* A hook that handles a single .md-file directive, up to but not
|
||||
including the closing ')'. It takes two arguments: the file position
|
||||
@ -119,10 +120,13 @@ class md_reader
|
||||
|
||||
file_location get_current_location () const;
|
||||
|
||||
bool is_compact () const { return m_compact; }
|
||||
|
||||
/* Defined in read-md.c. */
|
||||
int read_char (void);
|
||||
void unread_char (int ch);
|
||||
void read_name (struct md_name *name);
|
||||
file_location read_name (struct md_name *name);
|
||||
file_location read_name_or_nil (struct md_name *);
|
||||
void read_escape ();
|
||||
char *read_quoted_string ();
|
||||
char *read_braced_string ();
|
||||
@ -179,7 +183,12 @@ class md_reader
|
||||
void handle_include (file_location loc);
|
||||
void add_include_path (const char *arg);
|
||||
|
||||
bool read_name_1 (struct md_name *name, file_location *out_loc);
|
||||
|
||||
private:
|
||||
/* Are we reading a compact dump? */
|
||||
bool m_compact;
|
||||
|
||||
/* The name of the toplevel file that indirectly included
|
||||
m_read_md_file. */
|
||||
const char *m_toplevel_fname;
|
||||
@ -247,7 +256,7 @@ extern md_reader *md_reader_ptr;
|
||||
class noop_reader : public md_reader
|
||||
{
|
||||
public:
|
||||
noop_reader () : md_reader () {}
|
||||
noop_reader () : md_reader (false) {}
|
||||
|
||||
/* A dummy implementation which skips unknown directives. */
|
||||
void handle_unknown_directive (file_location, const char *);
|
||||
@ -261,14 +270,30 @@ class noop_reader : public md_reader
|
||||
class rtx_reader : public md_reader
|
||||
{
|
||||
public:
|
||||
rtx_reader ();
|
||||
rtx_reader (bool compact);
|
||||
~rtx_reader ();
|
||||
|
||||
bool read_rtx (const char *rtx_name, vec<rtx> *rtxen);
|
||||
rtx read_rtx_code (const char *code_name);
|
||||
void read_rtx_operand (rtx return_rtx, int idx);
|
||||
virtual rtx read_rtx_operand (rtx return_rtx, int idx);
|
||||
rtx read_nested_rtx ();
|
||||
rtx read_rtx_variadic (rtx form);
|
||||
char *read_until (const char *terminator_chars, bool consume_terminator);
|
||||
|
||||
virtual void handle_any_trailing_information (rtx) {}
|
||||
virtual rtx postprocess (rtx x) { return x; }
|
||||
|
||||
/* Hook to allow function_reader subclass to put STRINGBUF into gc-managed
|
||||
memory, rather than within an obstack.
|
||||
This base class implementation is a no-op. */
|
||||
virtual const char *finalize_string (char *stringbuf) { return stringbuf; }
|
||||
|
||||
protected:
|
||||
/* Analogous to rtx_writer's m_in_call_function_usage. */
|
||||
bool m_in_call_function_usage;
|
||||
|
||||
/* Support for "reuse_rtx" directives. */
|
||||
auto_vec<rtx> m_reuse_rtx_by_id;
|
||||
};
|
||||
|
||||
/* Global singleton; constrast with md_reader_ptr above. */
|
||||
|
2123
gcc/read-rtl-function.c
Normal file
2123
gcc/read-rtl-function.c
Normal file
File diff suppressed because it is too large
Load Diff
25
gcc/read-rtl-function.h
Normal file
25
gcc/read-rtl-function.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* read-rtl-function.h - Reader for RTL function dumps
|
||||
Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
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/>. */
|
||||
|
||||
#ifndef GCC_READ_RTL_FUNCTION_H
|
||||
#define GCC_READ_RTL_FUNCTION_H
|
||||
|
||||
extern bool read_rtl_function_body (const char *path);
|
||||
|
||||
#endif /* GCC_READ_RTL_FUNCTION_H */
|
260
gcc/read-rtl.c
260
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. */
|
||||
|
@ -200,6 +200,7 @@ test_single_set ()
|
||||
static void
|
||||
test_uncond_jump ()
|
||||
{
|
||||
set_new_first_and_last_insn (NULL, NULL);
|
||||
rtx_insn *label = gen_label_rtx ();
|
||||
rtx jump_pat = gen_rtx_SET (pc_rtx,
|
||||
gen_rtx_LABEL_REF (VOIDmode,
|
||||
|
@ -3712,7 +3712,9 @@ extern void init_varasm_once (void);
|
||||
extern rtx make_debug_expr_from_rtl (const_rtx);
|
||||
|
||||
/* In read-rtl.c */
|
||||
#ifdef GENERATOR_FILE
|
||||
extern bool read_rtx (const char *, vec<rtx> *);
|
||||
#endif
|
||||
|
||||
/* In alias.c */
|
||||
extern rtx canon_rtx (rtx);
|
||||
|
100
gcc/selftest-rtl.c
Normal file
100
gcc/selftest-rtl.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Selftest support for RTL.
|
||||
Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
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/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "selftest.h"
|
||||
#include "backend.h"
|
||||
#include "target.h"
|
||||
#include "rtl.h"
|
||||
#include "read-rtl-function.h"
|
||||
#include "read-md.h"
|
||||
#include "tree-core.h"
|
||||
#include "memmodel.h"
|
||||
#include "emit-rtl.h"
|
||||
#include "selftest-rtl.h"
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
/* Compare rtx EXPECTED and ACTUAL by pointer equality, calling
|
||||
::selftest::pass if they are equal, aborting if they are non-equal.
|
||||
LOC is the effective location of the assertion, MSG describes it. */
|
||||
|
||||
void
|
||||
assert_rtx_ptr_eq_at (const location &loc, const char *msg,
|
||||
rtx expected, rtx actual)
|
||||
{
|
||||
if (expected == actual)
|
||||
::selftest::pass (loc, msg);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s:%i: %s: FAIL: %s\n", loc.m_file, loc.m_line,
|
||||
loc.m_function, msg);
|
||||
fprintf (stderr, " expected (at %p): ", (void *)expected);
|
||||
print_rtl (stderr, expected);
|
||||
fprintf (stderr, "\n actual (at %p): ", (void *)actual);
|
||||
print_rtl (stderr, actual);
|
||||
fprintf (stderr, "\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Constructor for selftest::rtl_dump_test.
|
||||
Read a dumped RTL function from PATH.
|
||||
Takes ownership of PATH, freeing in dtor.
|
||||
Use LOC as the effective location when reporting failures. */
|
||||
|
||||
rtl_dump_test::rtl_dump_test (const location &loc, char *path)
|
||||
: m_path (path)
|
||||
{
|
||||
bool read_ok = read_rtl_function_body (path);
|
||||
ASSERT_TRUE_AT (loc, read_ok);
|
||||
}
|
||||
|
||||
/* Destructor for selftest::rtl_dump_test.
|
||||
Cleanup global state relating to the function, and free the path. */
|
||||
|
||||
selftest::rtl_dump_test::~rtl_dump_test ()
|
||||
{
|
||||
/* Cleanups. */
|
||||
current_function_decl = NULL;
|
||||
free_after_compilation (cfun);
|
||||
set_cfun (NULL);
|
||||
free (m_path);
|
||||
}
|
||||
|
||||
/* Get the insn with the given uid, or NULL if not found. */
|
||||
|
||||
rtx_insn *
|
||||
get_insn_by_uid (int uid)
|
||||
{
|
||||
for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_UID (insn) == uid)
|
||||
return insn;
|
||||
|
||||
/* Not found. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
@ -47,6 +47,43 @@ assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x,
|
||||
assert_rtl_dump_eq (SELFTEST_LOCATION, (EXPECTED_DUMP), (RTX), \
|
||||
(REUSE_MANAGER))
|
||||
|
||||
/* Evaluate rtx EXPECTED and ACTUAL and compare them with ==
|
||||
(i.e. pointer equality), calling ::selftest::pass if they are
|
||||
equal, aborting if they are non-equal. */
|
||||
|
||||
#define ASSERT_RTX_PTR_EQ(EXPECTED, ACTUAL) \
|
||||
SELFTEST_BEGIN_STMT \
|
||||
const char *desc = "ASSERT_RTX_PTR_EQ (" #EXPECTED ", " #ACTUAL ")"; \
|
||||
::selftest::assert_rtx_ptr_eq_at (SELFTEST_LOCATION, desc, (EXPECTED), \
|
||||
(ACTUAL)); \
|
||||
SELFTEST_END_STMT
|
||||
|
||||
/* Compare rtx EXPECTED and ACTUAL by pointer equality, calling
|
||||
::selftest::pass if they are equal, aborting if they are non-equal.
|
||||
LOC is the effective location of the assertion, MSG describes it. */
|
||||
|
||||
extern void assert_rtx_ptr_eq_at (const location &loc, const char *msg,
|
||||
rtx expected, rtx actual);
|
||||
|
||||
/* A class for testing RTL function dumps. */
|
||||
|
||||
class rtl_dump_test
|
||||
{
|
||||
public:
|
||||
/* Takes ownership of PATH. */
|
||||
rtl_dump_test (const location &loc, char *path);
|
||||
~rtl_dump_test ();
|
||||
|
||||
private:
|
||||
char *m_path;
|
||||
};
|
||||
|
||||
/* Get the insn with the given uid, or NULL if not found. */
|
||||
|
||||
extern rtx_insn *get_insn_by_uid (int uid);
|
||||
|
||||
extern void verify_three_block_rtl_cfg (function *fun);
|
||||
|
||||
} /* end of namespace selftest. */
|
||||
|
||||
#endif /* #if CHECKING_P */
|
||||
|
@ -72,6 +72,7 @@ selftest::run_tests ()
|
||||
tree_c_tests ();
|
||||
gimple_c_tests ();
|
||||
rtl_tests_c_tests ();
|
||||
read_rtl_function_c_tests ();
|
||||
|
||||
/* Higher-level tests, or for components that other selftests don't
|
||||
rely on. */
|
||||
|
@ -184,6 +184,7 @@ extern void hash_map_tests_c_tests ();
|
||||
extern void hash_set_tests_c_tests ();
|
||||
extern void input_c_tests ();
|
||||
extern void pretty_print_c_tests ();
|
||||
extern void read_rtl_function_c_tests ();
|
||||
extern void rtl_tests_c_tests ();
|
||||
extern void selftest_c_tests ();
|
||||
extern void spellcheck_c_tests ();
|
||||
|
@ -1,3 +1,27 @@
|
||||
2017-01-05 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2017-01-05 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
PR c++/78765
|
||||
|
36
gcc/testsuite/selftests/aarch64/times-two.rtl
Normal file
36
gcc/testsuite/selftests/aarch64/times-two.rtl
Normal file
@ -0,0 +1,36 @@
|
||||
(function "times_two"
|
||||
(insn-chain
|
||||
(cnote 1 NOTE_INSN_DELETED)
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK)
|
||||
(cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
|
||||
(const_int -4)) [1 i+0 S4 A32])
|
||||
(reg:SI x0 [ i ])) "../../src/times-two.c":2
|
||||
(nil))
|
||||
(cnote 3 NOTE_INSN_FUNCTION_BEG)
|
||||
(cinsn 6 (set (reg:SI <2>)
|
||||
(mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
|
||||
(const_int -4)) [1 i+0 S4 A32])) "../../src/times-two.c":3
|
||||
(nil))
|
||||
(cinsn 7 (set (reg:SI <0> [ _2 ])
|
||||
(ashift:SI (reg:SI <2>)
|
||||
(const_int 1))) "../../src/times-two.c":3
|
||||
(nil))
|
||||
(cinsn 10 (set (reg:SI <1> [ <retval> ])
|
||||
(reg:SI <0> [ _2 ])) "../../src/times-two.c":3
|
||||
(nil))
|
||||
(cinsn 14 (set (reg/i:SI x0)
|
||||
(reg:SI <1> [ <retval> ])) "../../src/times-two.c":4
|
||||
(nil))
|
||||
(cinsn 15 (use (reg/i:SI x0)) "../../src/times-two.c":4
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
(crtl
|
||||
(return_rtx
|
||||
(reg/i:SI x0)
|
||||
) ;; return_rtx
|
||||
) ;; crtl
|
||||
) ;; function "times_two"
|
24
gcc/testsuite/selftests/asr_div1.rtl
Normal file
24
gcc/testsuite/selftests/asr_div1.rtl
Normal file
@ -0,0 +1,24 @@
|
||||
;; Taken from
|
||||
;; gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53
|
||||
;; for aarch64, hand editing to the new format.
|
||||
|
||||
(function "f1"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1 (set (reg:DI <2>)
|
||||
(lshiftrt:DI (reg:DI <0>)
|
||||
(const_int 32)))
|
||||
"../../src/gcc/testsuite/gcc.dg/asr_div1.c":14
|
||||
(expr_list:REG_DEAD (reg:DI <0>)
|
||||
(nil)))
|
||||
(cinsn 2 (set (reg:SI <1>)
|
||||
(ashiftrt:SI (subreg:SI (reg:DI <2>) 0)
|
||||
(const_int 3)))
|
||||
"../../src/gcc/testsuite/gcc.dg/asr_div1.c":14
|
||||
(expr_list:REG_DEAD (reg:DI <2>)
|
||||
(nil)))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
8
gcc/testsuite/selftests/bb-index.rtl
Normal file
8
gcc/testsuite/selftests/bb-index.rtl
Normal file
@ -0,0 +1,8 @@
|
||||
(function "test_bb_index"
|
||||
(insn-chain
|
||||
(block 42
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 42
|
||||
) ;; insn-chain
|
||||
) ;; function
|
37
gcc/testsuite/selftests/cfg-test.rtl
Normal file
37
gcc/testsuite/selftests/cfg-test.rtl
Normal file
@ -0,0 +1,37 @@
|
||||
/* Example of a loading a CFG like this:
|
||||
0 (entry)
|
||||
|
|
||||
2
|
||||
/ \
|
||||
3 4
|
||||
\ /
|
||||
5
|
||||
|
|
||||
1 (exit). */
|
||||
|
||||
(function "cfg_test"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
|
||||
(edge-to 3 (flags "TRUE_VALUE"))
|
||||
(edge-to 4 (flags "FALSE_VALUE"))
|
||||
) ;; block 2
|
||||
(block 3
|
||||
(edge-from 2 (flags "TRUE_VALUE"))
|
||||
(cnote 2 [bb 3] NOTE_INSN_BASIC_BLOCK)
|
||||
(edge-to 5 (flags "FALLTHRU"))
|
||||
) ;; block 3
|
||||
(block 4
|
||||
(edge-from 2 (flags "FALSE_VALUE"))
|
||||
(cnote 3 [bb 4] NOTE_INSN_BASIC_BLOCK)
|
||||
(edge-to 5 (flags "FALLTHRU"))
|
||||
) ;; block 4
|
||||
(block 5
|
||||
(edge-from 3 (flags "FALLTHRU"))
|
||||
(edge-from 4 (flags "FALLTHRU"))
|
||||
(cnote 4 [bb 5] NOTE_INSN_BASIC_BLOCK)
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 5
|
||||
) ;; insn-chain
|
||||
) ;; function
|
20
gcc/testsuite/selftests/const-int.rtl
Normal file
20
gcc/testsuite/selftests/const-int.rtl
Normal file
@ -0,0 +1,20 @@
|
||||
(function "const_int_examples"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1
|
||||
(set (reg:SI <0>) (const_int 0))
|
||||
"test.c":2 (nil))
|
||||
(cinsn 2
|
||||
(set (reg:SI <1>) (const_int 1))
|
||||
"test.c":2 (nil))
|
||||
(cinsn 3
|
||||
(set (reg:SI <2>) (const_int -1))
|
||||
"test.c":2 (nil))
|
||||
(cinsn 4
|
||||
(set (reg:SI <3>) (const_int 256))
|
||||
"test.c":2 (nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
8
gcc/testsuite/selftests/example-labels.rtl
Normal file
8
gcc/testsuite/selftests/example-labels.rtl
Normal file
@ -0,0 +1,8 @@
|
||||
(function "example_labels"
|
||||
(insn-chain
|
||||
(block 6
|
||||
(clabel 100 30 (nil))
|
||||
(clabel 200 40 ("some_label_name"))
|
||||
) ;; block 6
|
||||
) ;; insn-chain
|
||||
) ;; function
|
7
gcc/testsuite/selftests/insn-with-mode.rtl
Normal file
7
gcc/testsuite/selftests/insn-with-mode.rtl
Normal file
@ -0,0 +1,7 @@
|
||||
(function "insn_with_mode"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(insn:TI 1 (set (reg:SI <0>) (reg:SI <1>)) (nil))
|
||||
) ;; block
|
||||
) ;; insn-chain
|
||||
) ;; function
|
17
gcc/testsuite/selftests/jump-to-label-ref.rtl
Normal file
17
gcc/testsuite/selftests/jump-to-label-ref.rtl
Normal file
@ -0,0 +1,17 @@
|
||||
(function "jump_to_label_ref"
|
||||
(insn-chain
|
||||
(block 4
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cjump_insn 1 (set (pc) (label_ref 100))
|
||||
"../../src/gcc/testsuite/rtl.dg/test.c":4)
|
||||
(edge-to 5)
|
||||
) ;; block 4
|
||||
(cbarrier 2)
|
||||
(block 5
|
||||
(edge-from 4)
|
||||
(clabel 100 2 (nil) [1 uses])
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 5
|
||||
) ;; insn-chain
|
||||
) ;; function
|
||||
|
11
gcc/testsuite/selftests/jump-to-return.rtl
Normal file
11
gcc/testsuite/selftests/jump-to-return.rtl
Normal file
@ -0,0 +1,11 @@
|
||||
(function "jump_to_return"
|
||||
(insn-chain
|
||||
(block 4
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cjump_insn 1 (return)
|
||||
"../../src/gcc/testsuite/rtl.dg/test.c":4
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 4
|
||||
) ;; insn-chain
|
||||
) ;; function
|
11
gcc/testsuite/selftests/jump-to-simple-return.rtl
Normal file
11
gcc/testsuite/selftests/jump-to-simple-return.rtl
Normal file
@ -0,0 +1,11 @@
|
||||
(function "jump_to_simple_return"
|
||||
(insn-chain
|
||||
(block 4
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cjump_insn 1 (simple_return)
|
||||
"../../src/gcc/testsuite/rtl.dg/test.c":4
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 4
|
||||
) ;; insn-chain
|
||||
) ;; function
|
9
gcc/testsuite/selftests/mem.rtl
Normal file
9
gcc/testsuite/selftests/mem.rtl
Normal file
@ -0,0 +1,9 @@
|
||||
(function "test_mem"
|
||||
(insn-chain
|
||||
(block 2
|
||||
;; Various nonsensical values, to exercise the parser:
|
||||
(cinsn 1 (set (mem:SI (reg:SI <10>) [42 i+17 S8 A128 AS5]) (reg:SI <1>)))
|
||||
(cinsn 2 (set (mem:SI (reg:SI <11>) [43 i+18 S9 AS6]) (reg:SI <2>)))
|
||||
) ;; block 6
|
||||
) ;; insn-chain
|
||||
) ;; function
|
5
gcc/testsuite/selftests/note-insn-deleted.rtl
Normal file
5
gcc/testsuite/selftests/note-insn-deleted.rtl
Normal file
@ -0,0 +1,5 @@
|
||||
(function "example_note"
|
||||
(insn-chain
|
||||
(cnote 1 NOTE_INSN_DELETED)
|
||||
) ;; insn-chain
|
||||
) ;; function
|
9
gcc/testsuite/selftests/note_insn_basic_block.rtl
Normal file
9
gcc/testsuite/selftests/note_insn_basic_block.rtl
Normal file
@ -0,0 +1,9 @@
|
||||
(function "example_of_note"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
16
gcc/testsuite/selftests/simple-cse.rtl
Normal file
16
gcc/testsuite/selftests/simple-cse.rtl
Normal file
@ -0,0 +1,16 @@
|
||||
(function "test"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1 (set (reg:SI <1>)
|
||||
(plus:SI (reg:SI <0>)
|
||||
(const_int 1))) (nil))
|
||||
(cinsn 2 (set (reg:SI <2>)
|
||||
(plus:SI (reg:SI <0>)
|
||||
(const_int 1))) (nil))
|
||||
(cinsn 3 (set (mem:SI (reg:SI <3>) [1 i+0 S4 A32])
|
||||
(mult:SI (reg:SI <1>) (reg:SI <2>))) (nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
13
gcc/testsuite/selftests/symbol-ref.rtl
Normal file
13
gcc/testsuite/selftests/symbol-ref.rtl
Normal file
@ -0,0 +1,13 @@
|
||||
(function "example_of_symbol_ref"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1
|
||||
(set (reg:SI <0>)
|
||||
(high:SI (symbol_ref:SI ("isl_obj_map_vtable") [flags 0xc0] <var_decl 0x7fa0363ea240 isl_obj_map_vtable>)))
|
||||
"y.c":12702
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
17
gcc/testsuite/selftests/x86_64/call-insn.rtl
Normal file
17
gcc/testsuite/selftests/x86_64/call-insn.rtl
Normal file
@ -0,0 +1,17 @@
|
||||
(function "test"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(ccall_insn/j 1
|
||||
(set (reg:DF xmm0)
|
||||
(call (mem:QI (symbol_ref:DI ("sqrt") [flags 0x41] <function_decl 0x7f82b1429d00 sqrt>) [0 __builtin_sqrt S1 A8])
|
||||
(const_int 0))) "test.c":19
|
||||
(expr_list:REG_CALL_DECL (symbol_ref:DI ("sqrt") [flags 0x41] <function_decl 0x7f82b1429d00 sqrt>)
|
||||
(expr_list:REG_EH_REGION (const_int 0)
|
||||
(nil)))
|
||||
(expr_list:DF (use (reg:DF xmm0))
|
||||
(nil)))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function "test"
|
15
gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl
Normal file
15
gcc/testsuite/selftests/x86_64/copy-hard-reg-into-frame.rtl
Normal file
@ -0,0 +1,15 @@
|
||||
(function "copy_hard_reg_into_frame"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1 (set (mem/c:SI
|
||||
(plus:DI
|
||||
(reg/f:DI frame)
|
||||
(const_int -4))
|
||||
[1 i+0 S4 A32])
|
||||
(reg:SI di [ i ])) "test.c":2
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
51
gcc/testsuite/selftests/x86_64/times-two.rtl
Normal file
51
gcc/testsuite/selftests/x86_64/times-two.rtl
Normal file
@ -0,0 +1,51 @@
|
||||
;; Dump of this C function:
|
||||
;;
|
||||
;; int times_two (int i)
|
||||
;; {
|
||||
;; return i * 2;
|
||||
;; }
|
||||
;;
|
||||
;; after expand for target==x86_64
|
||||
|
||||
(function "times_two"
|
||||
(insn-chain
|
||||
(cnote 1 NOTE_INSN_DELETED)
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK)
|
||||
(cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
|
||||
(const_int -4)) [1 i+0 S4 A32])
|
||||
(reg:SI di [ i ])) "../../src/times-two.c":2
|
||||
(nil))
|
||||
(cnote 3 NOTE_INSN_FUNCTION_BEG)
|
||||
(cinsn 6 (set (reg:SI <2>)
|
||||
(mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
|
||||
(const_int -4)) [1 i+0 S4 A32])) "../../src/times-two.c":3
|
||||
(nil))
|
||||
(cinsn 7 (parallel [
|
||||
(set (reg:SI <0> [ _2 ])
|
||||
(ashift:SI (reg:SI <2>)
|
||||
(const_int 1)))
|
||||
(clobber (reg:CC flags))
|
||||
]) "../../src/times-two.c":3
|
||||
(expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars)
|
||||
(const_int -4)) [1 i+0 S4 A32])
|
||||
(const_int 1))
|
||||
(nil)))
|
||||
(cinsn 10 (set (reg:SI <1> [ <retval> ])
|
||||
(reg:SI <0> [ _2 ])) "../../src/times-two.c":3
|
||||
(nil))
|
||||
(cinsn 14 (set (reg/i:SI ax)
|
||||
(reg:SI <1> [ <retval> ])) "../../src/times-two.c":4
|
||||
(nil))
|
||||
(cinsn 15 (use (reg/i:SI ax)) "../../src/times-two.c":4
|
||||
(nil))
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
(crtl
|
||||
(return_rtx
|
||||
(reg/i:SI ax)
|
||||
) ;; return_rtx
|
||||
) ;; crtl
|
||||
) ;; function "times_two"
|
20
gcc/testsuite/selftests/x86_64/unspec.rtl
Normal file
20
gcc/testsuite/selftests/x86_64/unspec.rtl
Normal file
@ -0,0 +1,20 @@
|
||||
(function "test_unspec"
|
||||
(insn-chain
|
||||
(block 2
|
||||
(edge-from entry (flags "FALLTHRU"))
|
||||
(cinsn 1 (set (mem/v:BLK (0|scratch:DI) [0 A8])
|
||||
(unspec:BLK [
|
||||
(mem/v:BLK (reuse_rtx 0) [0 A8])
|
||||
] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
|
||||
(nil))
|
||||
|
||||
(cinsn 2 (set (mem/v:BLK (1|scratch:DI) [0 A8])
|
||||
(unspec_volatile:BLK [
|
||||
(mem/v:BLK (reuse_rtx 1) [0 A8])
|
||||
] UNSPECV_RDTSCP)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2
|
||||
(nil))
|
||||
|
||||
(edge-to exit (flags "FALLTHRU"))
|
||||
) ;; block 2
|
||||
) ;; insn-chain
|
||||
) ;; function
|
@ -305,6 +305,11 @@ ssa_default_def (struct function *fn, tree var)
|
||||
gcc_assert (VAR_P (var)
|
||||
|| TREE_CODE (var) == PARM_DECL
|
||||
|| TREE_CODE (var) == RESULT_DECL);
|
||||
|
||||
/* Always NULL_TREE for rtl function dumps. */
|
||||
if (!fn->gimple_df)
|
||||
return NULL_TREE;
|
||||
|
||||
in.var = (tree)&ind;
|
||||
ind.uid = DECL_UID (var);
|
||||
return DEFAULT_DEFS (fn)->find_with_hash ((tree)&in, DECL_UID (var));
|
||||
|
Loading…
x
Reference in New Issue
Block a user