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:
David Malcolm 2017-01-05 19:32:09 +00:00 committed by David Malcolm
parent 7f86d7de6b
commit 51b861137e
42 changed files with 3414 additions and 32 deletions

View File

@ -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> 2017-01-05 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (*testqi_ext_3): No need to handle memory * config/i386/i386.md (*testqi_ext_3): No need to handle memory

View File

@ -1420,6 +1420,9 @@ OBJS = \
print-rtl-function.o \ print-rtl-function.o \
print-tree.o \ print-tree.o \
profile.o \ profile.o \
read-md.o \
read-rtl.o \
read-rtl-function.o \
real.o \ real.o \
realmpfr.o \ realmpfr.o \
recog.o \ recog.o \
@ -1447,6 +1450,7 @@ OBJS = \
sel-sched-ir.o \ sel-sched-ir.o \
sel-sched-dump.o \ sel-sched-dump.o \
sel-sched.o \ sel-sched.o \
selftest-rtl.o \
selftest-run-tests.o \ selftest-run-tests.o \
sese.o \ sese.o \
shrink-wrap.o \ shrink-wrap.o \

View File

@ -64,6 +64,8 @@
#include "sched-int.h" #include "sched-int.h"
#include "target-globals.h" #include "target-globals.h"
#include "common/common-target.h" #include "common/common-target.h"
#include "selftest.h"
#include "selftest-rtl.h"
/* This file should be included last. */ /* This file should be included last. */
#include "target-def.h" #include "target-def.h"
@ -14605,6 +14607,52 @@ aarch64_excess_precision (enum excess_precision_type type)
return FLT_EVAL_METHOD_UNPREDICTABLE; 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 #undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_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 #undef TARGET_OMIT_STRUCT_RETURN_REG
#define TARGET_OMIT_STRUCT_RETURN_REG true #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; struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h" #include "gt-aarch64.h"

View File

@ -51206,6 +51206,209 @@ ix86_test_dumping_memory_blockage ()
" ] UNSPEC_MEMORY_BLOCKAGE)))\n", pat, &r); " ] 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. */ /* Run all target-specific selftests. */
static void static void
@ -51213,6 +51416,13 @@ ix86_run_selftests (void)
{ {
ix86_test_dumping_hard_regs (); ix86_test_dumping_hard_regs ();
ix86_test_dumping_memory_blockage (); 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 } // namespace selftest

View File

@ -1374,6 +1374,19 @@ maybe_set_first_label_num (rtx_code_label *x)
if (CODE_LABEL_NUMBER (x) < first_label_num) if (CODE_LABEL_NUMBER (x) < first_label_num)
first_label_num = CODE_LABEL_NUMBER (x); 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 /* 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 of low-order bits is given by MODE. Note that no conversion is done

View File

@ -510,4 +510,6 @@ extern int get_mem_align_offset (rtx, unsigned int);
MODE and adjusted by OFFSET. */ MODE and adjusted by OFFSET. */
extern rtx widen_memory_access (rtx, machine_mode, HOST_WIDE_INT); 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 */ #endif /* GCC_EMIT_RTL_H */

View File

@ -421,7 +421,7 @@ verify_three_block_gimple_cfg (function *fun)
/* As above, but additionally verify the RTL insns are sane. */ /* As above, but additionally verify the RTL insns are sane. */
static void void
verify_three_block_rtl_cfg (function *fun) verify_three_block_rtl_cfg (function *fun)
{ {
verify_three_block_cfg (fun); verify_three_block_cfg (fun);

View File

@ -1909,7 +1909,8 @@ instantiate_decls (tree fndecl)
instantiate_decl_rtl (DECL_RTL (DECL_VALUE_EXPR (decl))); instantiate_decl_rtl (DECL_RTL (DECL_VALUE_EXPR (decl)));
/* Now process all variables defined in the function or its subblocks. */ /* 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) FOR_EACH_LOCAL_DECL (cfun, ix, decl)
if (DECL_RTL_SET_P (decl)) if (DECL_RTL_SET_P (decl))

View File

@ -2233,7 +2233,7 @@ process_define_subst (void)
class gen_reader : public rtx_reader class gen_reader : public rtx_reader
{ {
public: public:
gen_reader () : rtx_reader () {} gen_reader () : rtx_reader (false) {}
void handle_unknown_directive (file_location, const char *); void handle_unknown_directive (file_location, const char *);
}; };

View File

@ -577,7 +577,7 @@ rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
string: string:
if (str == 0) if (str == 0)
fputs (" \"\"", m_outfile); fputs (" (nil)", m_outfile);
else else
fprintf (m_outfile, " (\"%s\")", str); fprintf (m_outfile, " (\"%s\")", str);
m_sawclose = 1; m_sawclose = 1;

View File

@ -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 along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <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" #include "bconfig.h"
#else
#include "config.h"
#endif
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
#ifdef GENERATOR_FILE
#include "errors.h" #include "errors.h"
#endif /* #ifdef GENERATOR_FILE */
#include "statistics.h" #include "statistics.h"
#include "vec.h" #include "vec.h"
#include "read-md.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 /* Associates PTR (which can be a string, etc.) with the file location
specified by FILENAME and LINENO. */ specified by FILENAME and LINENO. */
struct ptr_loc { 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 /* Read an rtx code name into NAME. It is terminated by any of the
punctuation chars of rtx printed syntax. */ punctuation chars of rtx printed syntax. */
void bool
md_reader::read_name (struct md_name *name) md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
{ {
int c; int c;
size_t i; size_t i;
@ -433,6 +451,8 @@ md_reader::read_name (struct md_name *name)
c = read_skip_spaces (); c = read_skip_spaces ();
*out_loc = get_current_location ();
i = 0; i = 0;
angle_bracket_depth = 0; angle_bracket_depth = 0;
while (1) while (1)
@ -464,7 +484,7 @@ md_reader::read_name (struct md_name *name)
} }
if (i == 0) if (i == 0)
fatal_with_file_and_line ("missing name or number"); return false;
name->buffer[i] = 0; name->buffer[i] = 0;
name->string = name->buffer; name->string = name->buffer;
@ -485,6 +505,36 @@ md_reader::read_name (struct md_name *name)
} }
while (def); 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. /* 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, '*'); obstack_1grow (&m_string_obstack, '*');
stringbuf = read_braced_string (); 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 else
fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c); 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. */ /* Constructor for md_reader. */
md_reader::md_reader () md_reader::md_reader (bool compact)
: m_toplevel_fname (NULL), : m_compact (compact),
m_toplevel_fname (NULL),
m_base_dir (NULL), m_base_dir (NULL),
m_read_md_file (NULL), m_read_md_file (NULL),
m_read_md_filename (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; m_last_dir_md_include_ptr = &dirtmp->next;
} }
#ifdef GENERATOR_FILE
/* The main routine for reading .md files. Try to process all the .md /* 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. 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; 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 */ /* class noop_reader : public md_reader */
/* A dummy implementation which skips unknown directives. */ /* A dummy implementation which skips unknown directives. */

View File

@ -106,10 +106,11 @@ struct enum_type {
class md_reader class md_reader
{ {
public: public:
md_reader (); md_reader (bool compact);
virtual ~md_reader (); virtual ~md_reader ();
bool read_md_files (int, const char **, bool (*) (const char *)); 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 /* A hook that handles a single .md-file directive, up to but not
including the closing ')'. It takes two arguments: the file position including the closing ')'. It takes two arguments: the file position
@ -119,10 +120,13 @@ class md_reader
file_location get_current_location () const; file_location get_current_location () const;
bool is_compact () const { return m_compact; }
/* Defined in read-md.c. */ /* Defined in read-md.c. */
int read_char (void); int read_char (void);
void unread_char (int ch); 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 (); void read_escape ();
char *read_quoted_string (); char *read_quoted_string ();
char *read_braced_string (); char *read_braced_string ();
@ -179,7 +183,12 @@ class md_reader
void handle_include (file_location loc); void handle_include (file_location loc);
void add_include_path (const char *arg); void add_include_path (const char *arg);
bool read_name_1 (struct md_name *name, file_location *out_loc);
private: private:
/* Are we reading a compact dump? */
bool m_compact;
/* The name of the toplevel file that indirectly included /* The name of the toplevel file that indirectly included
m_read_md_file. */ m_read_md_file. */
const char *m_toplevel_fname; const char *m_toplevel_fname;
@ -247,7 +256,7 @@ extern md_reader *md_reader_ptr;
class noop_reader : public md_reader class noop_reader : public md_reader
{ {
public: public:
noop_reader () : md_reader () {} noop_reader () : md_reader (false) {}
/* A dummy implementation which skips unknown directives. */ /* A dummy implementation which skips unknown directives. */
void handle_unknown_directive (file_location, const char *); void handle_unknown_directive (file_location, const char *);
@ -261,14 +270,30 @@ class noop_reader : public md_reader
class rtx_reader : public md_reader class rtx_reader : public md_reader
{ {
public: public:
rtx_reader (); rtx_reader (bool compact);
~rtx_reader (); ~rtx_reader ();
bool read_rtx (const char *rtx_name, vec<rtx> *rtxen); bool read_rtx (const char *rtx_name, vec<rtx> *rtxen);
rtx read_rtx_code (const char *code_name); 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_nested_rtx ();
rtx read_rtx_variadic (rtx form); 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. */ /* Global singleton; constrast with md_reader_ptr above. */

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
View 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 */

View File

@ -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 along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <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" #include "bconfig.h"
#else
#include "config.h"
#endif
/* Disable rtl checking; it conflicts with the iterator handling. */ /* Disable rtl checking; it conflicts with the iterator handling. */
#undef ENABLE_RTL_CHECKING #undef ENABLE_RTL_CHECKING
@ -30,6 +36,12 @@ along with GCC; see the file COPYING3. If not see
#include "read-md.h" #include "read-md.h"
#include "gensupport.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. */ /* One element in a singly-linked list of (integer, string) pairs. */
struct map_value { struct map_value {
struct map_value *next; struct map_value *next;
@ -106,6 +118,7 @@ htab_t subst_attr_to_iter_map = NULL;
const char *current_iterator_name; const char *current_iterator_name;
static void validate_const_int (const char *); static void validate_const_int (const char *);
static void one_time_initialization (void);
/* Global singleton. */ /* Global singleton. */
rtx_reader *rtx_reader_ptr = NULL; rtx_reader *rtx_reader_ptr = NULL;
@ -142,6 +155,25 @@ apply_mode_iterator (void *loc, int mode)
PUT_MODE ((rtx) loc, (machine_mode) 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. */ /* Implementations of the iterator_group callbacks for codes. */
static int static int
@ -153,6 +185,10 @@ find_code (const char *name)
if (strcmp (GET_RTX_NAME (i), name) == 0) if (strcmp (GET_RTX_NAME (i), name) == 0)
return i; 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); fatal_with_file_and_line ("unknown rtx code `%s'", name);
} }
@ -181,6 +217,8 @@ apply_int_iterator (void *loc, int value)
*(int *)loc = value; *(int *)loc = value;
} }
#ifdef GENERATOR_FILE
/* This routine adds attribute or does nothing depending on VALUE. When /* This routine adds attribute or does nothing depending on VALUE. When
VALUE is 1, it does nothing - the first duplicate of original VALUE is 1, it does nothing - the first duplicate of original
template is kept untouched when it's subjected to a define_subst. 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; *slot = value;
} }
#endif /* #ifdef GENERATOR_FILE */
/* Return name of a subst-iterator, corresponding to subst-attribute ATTR. */ /* Return name of a subst-iterator, corresponding to subst-attribute ATTR. */
static char* static char*
@ -418,6 +458,8 @@ md_reader::copy_rtx_for_iterators (rtx original)
return x; return x;
} }
#ifdef GENERATOR_FILE
/* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL /* Return a condition that must satisfy both ORIGINAL and EXTRA. If ORIGINAL
has the form "&& ..." (as used in define_insn_and_splits), assume that has the form "&& ..." (as used in define_insn_and_splits), assume that
EXTRA is already satisfied. Empty strings are treated like "true". */ 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 /* Add a new "mapping" structure to hashtable TABLE. NAME is the name
of the mapping and GROUP is the group to which it belongs. */ 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, substs.iterators = htab_create (13, leading_string_hash,
leading_string_eq_p, 0); leading_string_eq_p, 0);
substs.find_builtin = find_int; /* We don't use it, anyway. */ substs.find_builtin = find_int; /* We don't use it, anyway. */
#ifdef GENERATOR_FILE
substs.apply_iterator = apply_subst_iterator; substs.apply_iterator = apply_subst_iterator;
#endif
lower = add_mapping (&modes, modes.attrs, "mode"); lower = add_mapping (&modes, modes.attrs, "mode");
upper = add_mapping (&modes, modes.attrs, "MODE"); upper = add_mapping (&modes, modes.attrs, "MODE");
@ -724,6 +769,8 @@ atoll (const char *p)
} }
#endif #endif
#ifdef GENERATOR_FILE
/* Process a define_conditions directive, starting with the optional /* Process a define_conditions directive, starting with the optional
space after the "define_conditions". The directive looks like this: space after the "define_conditions". The directive looks like this:
@ -765,6 +812,7 @@ md_reader::read_conditions ()
add_c_test (expr, value); add_c_test (expr, value);
} }
} }
#endif /* #ifdef GENERATOR_FILE */
static void static void
validate_const_int (const char *string) 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: /* Finish reading a declaration of the form:
(define... <name> [<value1> ... <valuen>]) (define... <name> [<value1> ... <valuen>])
@ -1020,15 +1070,6 @@ check_code_iterator (struct mapping *iterator)
bool bool
rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen) 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 /* Handle various rtx-related declarations that aren't themselves
encoded as rtxes. */ encoded as rtxes. */
if (strcmp (rtx_name, "define_conditions") == 0) if (strcmp (rtx_name, "define_conditions") == 0)
@ -1082,6 +1123,103 @@ rtx_reader::read_rtx (const char *rtx_name, vec<rtx> *rtxen)
return true; 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 /* 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 either an rtx code or a code iterator. Parse the rest of the rtx and
return it. */ return it. */
@ -1090,11 +1228,12 @@ rtx
rtx_reader::read_rtx_code (const char *code_name) rtx_reader::read_rtx_code (const char *code_name)
{ {
RTX_CODE code; RTX_CODE code;
struct mapping *iterator; struct mapping *iterator = NULL;
const char *format_ptr; const char *format_ptr;
struct md_name name; struct md_name name;
rtx return_rtx; rtx return_rtx;
int c; int c;
long reuse_id = -1;
/* Linked list structure for making RTXs: */ /* Linked list structure for making RTXs: */
struct rtx_list struct rtx_list
@ -1103,13 +1242,37 @@ rtx_reader::read_rtx_code (const char *code_name)
rtx value; /* Value of this node. */ 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 /* If this code is an iterator, build the rtx using the iterator's
first value. */ first value. */
#ifdef GENERATOR_FILE
iterator = (struct mapping *) htab_find (codes.iterators, &code_name); iterator = (struct mapping *) htab_find (codes.iterators, &code_name);
if (iterator != 0) if (iterator != 0)
code = (enum rtx_code) iterator->values->number; code = (enum rtx_code) iterator->values->number;
else else
code = (enum rtx_code) codes.find_builtin (code_name); 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. */ /* If we end up with an insn expression then we free this space below. */
return_rtx = rtx_alloc (code); 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)); memset (return_rtx, 0, RTX_CODE_SIZE (code));
PUT_CODE (return_rtx, 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) if (iterator)
record_iterator_use (iterator, return_rtx); 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 /* If what follows is `: mode ', read it and
store the mode in the rtx. */ store the mode in the rtx. */
@ -1132,8 +1322,19 @@ rtx_reader::read_rtx_code (const char *code_name)
else else
unread_char (c); 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++) 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)) 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, /* Subroutine of read_rtx_code. Parse operand IDX within RETURN_RTX,
based on the corresponding format character within GET_RTX_FORMAT 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_reader::read_rtx_operand (rtx return_rtx, int idx)
{ {
RTX_CODE code = GET_CODE (return_rtx); RTX_CODE code = GET_CODE (return_rtx);
@ -1217,6 +1420,9 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
break; break;
case 'e': case 'e':
XEXP (return_rtx, idx) = read_nested_rtx ();
break;
case 'u': case 'u':
XEXP (return_rtx, idx) = read_nested_rtx (); XEXP (return_rtx, idx) = read_nested_rtx ();
break; break;
@ -1273,7 +1479,6 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
{ {
char *stringbuf; char *stringbuf;
int star_if_braced; int star_if_braced;
struct obstack *string_obstack = get_string_obstack ();
c = read_skip_spaces (); c = read_skip_spaces ();
unread_char (c); unread_char (c);
@ -1293,7 +1498,10 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
star_if_braced = (format_ptr[idx] == 'T'); star_if_braced = (format_ptr[idx] == 'T');
stringbuf = read_string (star_if_braced); stringbuf = read_string (star_if_braced);
if (!stringbuf)
break;
#ifdef GENERATOR_FILE
/* For insn patterns, we want to provide a default name /* For insn patterns, we want to provide a default name
based on the file and line, like "*foo.md:12", if the based on the file and line, like "*foo.md:12", if the
given name is blank. These are only for define_insn and 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
|| GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
{ {
struct obstack *string_obstack = get_string_obstack ();
char line_name[20]; char line_name[20];
const char *read_md_filename = get_filename (); const char *read_md_filename = get_filename ();
const char *fn = (read_md_filename ? read_md_filename : "rtx"); 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) if (m != 0)
record_iterator_use (m, return_rtx); record_iterator_use (m, return_rtx);
} }
#endif /* #ifdef GENERATOR_FILE */
const char *string_ptr = finalize_string (stringbuf);
if (star_if_braced) if (star_if_braced)
XTMPL (return_rtx, idx) = stringbuf; XTMPL (return_rtx, idx) = string_ptr;
else else
XSTR (return_rtx, idx) = stringbuf; XSTR (return_rtx, idx) = string_ptr;
} }
break; break;
@ -1398,6 +1610,8 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
return return_rtx;
} }
/* Read a nested rtx construct from the MD file and return it. */ /* 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; struct md_name name;
rtx return_rtx; rtx return_rtx;
/* In compact dumps, trailing "(nil)" values can be omitted.
Handle such dumps. */
if (peek_char () == ')')
return NULL_RTX;
require_char_ws ('('); require_char_ws ('(');
read_name (&name); read_name (&name);
@ -1418,6 +1637,8 @@ rtx_reader::read_nested_rtx ()
require_char_ws (')'); require_char_ws (')');
return_rtx = postprocess (return_rtx);
return return_rtx; return return_rtx;
} }
@ -1454,11 +1675,14 @@ rtx_reader::read_rtx_variadic (rtx form)
/* Constructor for class rtx_reader. */ /* Constructor for class rtx_reader. */
rtx_reader::rtx_reader () rtx_reader::rtx_reader (bool compact)
: md_reader () : md_reader (compact),
m_in_call_function_usage (false)
{ {
/* Set the global singleton pointer. */ /* Set the global singleton pointer. */
rtx_reader_ptr = this; rtx_reader_ptr = this;
one_time_initialization ();
} }
/* Destructor for class rtx_reader. */ /* Destructor for class rtx_reader. */

View File

@ -200,6 +200,7 @@ test_single_set ()
static void static void
test_uncond_jump () test_uncond_jump ()
{ {
set_new_first_and_last_insn (NULL, NULL);
rtx_insn *label = gen_label_rtx (); rtx_insn *label = gen_label_rtx ();
rtx jump_pat = gen_rtx_SET (pc_rtx, rtx jump_pat = gen_rtx_SET (pc_rtx,
gen_rtx_LABEL_REF (VOIDmode, gen_rtx_LABEL_REF (VOIDmode,

View File

@ -3712,7 +3712,9 @@ extern void init_varasm_once (void);
extern rtx make_debug_expr_from_rtl (const_rtx); extern rtx make_debug_expr_from_rtl (const_rtx);
/* In read-rtl.c */ /* In read-rtl.c */
#ifdef GENERATOR_FILE
extern bool read_rtx (const char *, vec<rtx> *); extern bool read_rtx (const char *, vec<rtx> *);
#endif
/* In alias.c */ /* In alias.c */
extern rtx canon_rtx (rtx); extern rtx canon_rtx (rtx);

100
gcc/selftest-rtl.c Normal file
View 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 */

View File

@ -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), \ assert_rtl_dump_eq (SELFTEST_LOCATION, (EXPECTED_DUMP), (RTX), \
(REUSE_MANAGER)) (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. */ } /* end of namespace selftest. */
#endif /* #if CHECKING_P */ #endif /* #if CHECKING_P */

View File

@ -72,6 +72,7 @@ selftest::run_tests ()
tree_c_tests (); tree_c_tests ();
gimple_c_tests (); gimple_c_tests ();
rtl_tests_c_tests (); rtl_tests_c_tests ();
read_rtl_function_c_tests ();
/* Higher-level tests, or for components that other selftests don't /* Higher-level tests, or for components that other selftests don't
rely on. */ rely on. */

View File

@ -184,6 +184,7 @@ extern void hash_map_tests_c_tests ();
extern void hash_set_tests_c_tests (); extern void hash_set_tests_c_tests ();
extern void input_c_tests (); extern void input_c_tests ();
extern void pretty_print_c_tests (); extern void pretty_print_c_tests ();
extern void read_rtl_function_c_tests ();
extern void rtl_tests_c_tests (); extern void rtl_tests_c_tests ();
extern void selftest_c_tests (); extern void selftest_c_tests ();
extern void spellcheck_c_tests (); extern void spellcheck_c_tests ();

View File

@ -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> 2017-01-05 Nathan Sidwell <nathan@acm.org>
PR c++/78765 PR c++/78765

View 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"

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@ -0,0 +1,5 @@
(function "example_note"
(insn-chain
(cnote 1 NOTE_INSN_DELETED)
) ;; insn-chain
) ;; function

View 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

View 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

View 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

View 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"

View 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

View 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"

View 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

View File

@ -305,6 +305,11 @@ ssa_default_def (struct function *fn, tree var)
gcc_assert (VAR_P (var) gcc_assert (VAR_P (var)
|| TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == PARM_DECL
|| TREE_CODE (var) == RESULT_DECL); || TREE_CODE (var) == RESULT_DECL);
/* Always NULL_TREE for rtl function dumps. */
if (!fn->gimple_df)
return NULL_TREE;
in.var = (tree)&ind; in.var = (tree)&ind;
ind.uid = DECL_UID (var); ind.uid = DECL_UID (var);
return DEFAULT_DEFS (fn)->find_with_hash ((tree)&in, DECL_UID (var)); return DEFAULT_DEFS (fn)->find_with_hash ((tree)&in, DECL_UID (var));