[PATCH] Add "__RTL" to cc1 (v2)
David Malcolm
dmalcolm@redhat.com
Fri Oct 7 15:27:00 GMT 2016
On Wed, 2016-10-05 at 16:09 +0000, Joseph Myers wrote:
> On Wed, 5 Oct 2016, David Malcolm wrote:
>
> > @@ -1752,6 +1759,35 @@ c_parser_declaration_or_fndef (c_parser
> > *parser, bool fndef_ok,
> > c_parser_skip_to_end_of_block_or_statement (parser);
> > return;
> > }
> > +
> > + if (c_parser_next_token_is (parser, CPP_KEYWORD))
> > + {
> > + c_token *kw_token = c_parser_peek_token (parser);
> > + if (kw_token->keyword == RID_RTL)
>
> if (c_parser_next_token_is_keyword (parser, RID_RTL))
>
> You're missing an update to the comment above this function to show
> what
> the new syntax is.
Thanks. Here's an updated version of the patch which fixes that,
along with some other fixes:
* Use c_parser_next_token_is_keyword.
* Removed a stray "FIXME".
* Removed some debug code.
* Add more comments
* Fixed a typo in the ChangeLog ("__RID" -> "__RTL")
Blurb from original version:
This patch implements Richi's idea of having a custom __RTL marker
in C function definitions, to indicate that the body of the function
is to be parsed as RTL, rather than C:
int __RTL test_fn_1 (int i)
{
(function "times_two"
(insn-chain
(note 1 0 4 (nil) NOTE_INSN_DELETED)
;; etc
) ;; insn-chain
(crtl
(return_rtx
(reg/i:SI 0 ax)
) ;; return_rtx
) ;; crtl
) ;; function
}
This allows for decls and types to be declared in C, and to use
the function decl from the C frontend.
I added support for running a single pass by giving __RTL an optional
parameter (the name of the pass). For example:
int __RTL ("rtl-dfinit") test_fn_2 (int i)
{
(function "times_two"
(insn-chain
(note 1 0 4 (nil) NOTE_INSN_DELETED)
;; etc
) ;; insn-chain
(crtl
(return_rtx
(reg/i:SI 0 ax)
) ;; return_rtx
) ;; crtl
) ;; function
}
The top-level "function" directive is rather redundant; perhaps it should
be omitted? This would give e.g.:
int __RTL ("rtl-dfinit") test_fn_3 (int i)
{
(insn-chain
(note 1 0 4 (nil) NOTE_INSN_DELETED)
;; etc
) ;; insn-chain
(crtl
(return_rtx
(reg/i:SI 0 ax)
) ;; return_rtx
) ;; crtl
}
(Though maybe we want to keep it as a place to hold top-level metadata)
gcc/c-family/ChangeLog:
* c-common.c (c_common_reswords): Add "__RTL".
* c-common.h (enum rid): Add RID_RTL.
gcc/c/ChangeLog:
* c-parser.c: Include "read-rtl-function.h" and
"run-one-rtl-pass.h".
(c_parser_declaration_or_fndef): In the "GNU extensions" part of
the leading comment, add an alternate production for
"function-definition", along with new "rtl-body-specifier" and
"rtl-body-pass-specifier" productions. Handle "__RTL" by calling
c_parser_parse_rtl_body. Convert a timevar_push/pop pair
to an auto_timevar, to cope with early exit.
(c_parser_parse_rtl_body): New function.
gcc/ChangeLog:
* read-md.c (base_rtx_reader::read_char): Support filtering
the input to a subset of line numbers.
(base_rtx_reader::base_rtx_reader): Initialize fields
m_first_line and m_last_line.
(base_rtx_reader::read_file_fragment): New method.
* read-md.h (base_rtx_reader::read_file_fragment): New decl.
(base_rtx_reader::m_first_line): New field.
(base_rtx_reader::m_last_line): New field.
* read-rtl-function.c (function_reader::create_function): Only create
cfun if it doesn't already exist.
(read_rtl_function_body_from_file_range): New function.
* read-rtl-function.h (read_rtl_function_body_from_file_range):
New decl.
gcc/testsuite/ChangeLog:
* rtl.dg/rtl.exp: Add .c files below rtl.dg to "tests".
* rtl.dg/x86_64/different-structs.c: New file.
* rtl.dg/x86_64/test-return-const.c.after-expand.c: New file.
* rtl.dg/x86_64/test-return-const.c.before-fwprop.c: New file.
* rtl.dg/x86_64/test-rtl.c: New file.
* rtl.dg/x86_64/times-two.c.after-expand.c: New file.
* rtl.dg/x86_64/times-two.c.before-df.c: New file.
---
gcc/c-family/c-common.c | 1 +
gcc/c-family/c-common.h | 3 +
gcc/c/c-parser.c | 113 ++++++++++++++++++++-
gcc/read-md.c | 34 ++++++-
gcc/read-md.h | 7 ++
gcc/read-rtl-function.c | 78 ++++++++++----
gcc/read-rtl-function.h | 3 +
gcc/testsuite/rtl.dg/rtl.exp | 4 +-
gcc/testsuite/rtl.dg/x86_64/different-structs.c | 101 ++++++++++++++++++
.../x86_64/test-return-const.c.after-expand.c | 23 +++++
.../x86_64/test-return-const.c.before-fwprop.c | 27 +++++
gcc/testsuite/rtl.dg/x86_64/test-rtl.c | 95 +++++++++++++++++
.../rtl.dg/x86_64/times-two.c.after-expand.c | 40 ++++++++
.../rtl.dg/x86_64/times-two.c.before-df.c | 57 +++++++++++
14 files changed, 565 insertions(+), 21 deletions(-)
create mode 100644 gcc/testsuite/rtl.dg/x86_64/different-structs.c
create mode 100644 gcc/testsuite/rtl.dg/x86_64/test-return-const.c.after-expand.c
create mode 100644 gcc/testsuite/rtl.dg/x86_64/test-return-const.c.before-fwprop.c
create mode 100644 gcc/testsuite/rtl.dg/x86_64/test-rtl.c
create mode 100644 gcc/testsuite/rtl.dg/x86_64/times-two.c.after-expand.c
create mode 100644 gcc/testsuite/rtl.dg/x86_64/times-two.c.before-df.c
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 491c637..ecef32b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -524,6 +524,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
{ "__volatile", RID_VOLATILE, 0 },
{ "__volatile__", RID_VOLATILE, 0 },
+ { "__RTL", RID_RTL, 0 },
{ "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX11 | D_CXXWARN },
{ "asm", RID_ASM, D_ASM },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index c88619b..e19751e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -118,6 +118,9 @@ enum rid
RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
+ /* "__RTL", for the RTL-parsing extension to the C frontend. */
+ RID_RTL,
+
/* C11 */
RID_ALIGNAS, RID_GENERIC,
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 6bc42da..693d1bd 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -59,6 +59,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "context.h"
#include "gcc-rich-location.h"
+#include "read-rtl-function.h"
+#include "run-one-rtl-pass.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -1421,6 +1423,9 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
static void c_parser_cilk_grainsize (c_parser *, bool *);
+static void c_parser_parse_rtl_body (c_parser *parser,
+ const char *single_pass_name);
+
/* Parse a translation unit (C90 6.7, C99 6.9).
translation-unit:
@@ -1624,6 +1629,16 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
declaration-specifiers declarator declaration-list[opt]
compound-statement
+ function-definition:
+ declaration-specifiers rtl-body-specifier declarator declaration-list[opt]
+ compound-statement
+
+ rtl-body-specifier:
+ __RTL rtl-body-pass-specifier[opt]
+
+ rtl-body-pass-specifier:
+ ( string )
+
attribute ;
Objective-C:
@@ -1668,6 +1683,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tree all_prefix_attrs;
bool diagnosed_no_specs = false;
location_t here = c_parser_peek_token (parser)->location;
+ bool rtl_body_p = false;
+ const char *single_pass_name = NULL;
if (static_assert_ok
&& c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
@@ -1752,6 +1769,33 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
+
+ /* Handle GNU extension rtl-body-specifier by detecting "__RTL". */
+ if (c_parser_next_token_is_keyword (parser, RID_RTL))
+ {
+ rtl_body_p = true;
+ c_parser_consume_token (parser);
+
+ /* Handle the optional rtl-body-pass-specifier: parens wrapping
+ a string, giving a pass name. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ c_token *tok = c_parser_peek_token (parser);
+ if (tok->type != CPP_STRING)
+ {
+ c_parser_error (parser, "expected string");
+ c_parser_skip_to_end_of_block_or_statement (parser);
+ return;
+ }
+ gcc_assert (TREE_CODE (tok->value) == STRING_CST);
+ single_pass_name = TREE_STRING_POINTER (tok->value);
+ c_parser_consume_token (parser);
+
+ c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ }
+ }
+
finish_declspecs (specs);
bool auto_type_p = specs->typespec_word == cts_auto_type;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
@@ -2146,7 +2190,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tv = TV_PARSE_INLINE;
else
tv = TV_PARSE_FUNC;
- timevar_push (tv);
+ auto_timevar at (g_timer, tv);
/* Parse old-style parameter declarations. ??? Attributes are
not allowed to start declaration specifiers here because of a
@@ -2173,6 +2217,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
+
+ /* If we had an rtl-body-specifier, use the RTL parser now,
+ consuming the function body. */
+ if (rtl_body_p)
+ {
+ c_parser_parse_rtl_body (parser, single_pass_name);
+ return;
+ }
+
fnbody = c_parser_compound_statement (parser);
if (flag_cilkplus && contains_array_notation_expr (fnbody))
fnbody = expand_array_notation_exprs (fnbody);
@@ -2195,7 +2248,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
finish_function ();
}
- timevar_pop (tv);
break;
}
}
@@ -18313,4 +18365,61 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return value_tree;
}
+/* Parse the body of a function declaration marked with "__RTL".
+
+ The RTL parser works on the level of characters read from a
+ FILE *, whereas c_parser works at the level of tokens.
+ Square this circle by consuming all of the tokens up to and
+ including the closing brace, recording the start/end of the RTL
+ fragment, and reopening the file and re-reading the relevant
+ lines within the RTL parser.
+
+ This requires the opening and closing braces of the C function
+ to be on separate lines from the RTL they wrap. */
+
+void
+c_parser_parse_rtl_body (c_parser *parser, const char *single_pass_name)
+{
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ return;
+
+ location_t start_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume all tokens, up to the closing brace, handling
+ matching pairs of braces in the rtl dump. */
+ int num_open_braces = 1;
+ while (1)
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_BRACE:
+ num_open_braces++;
+ break;
+ case CPP_CLOSE_BRACE:
+ if (--num_open_braces == 0)
+ goto found_closing_brace;
+ break;
+ default:
+ break;
+ }
+ c_parser_consume_token (parser);
+ }
+
+ found_closing_brace:
+ /* At the closing brace; record its location. */
+ location_t end_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume the closing brace. */
+ c_parser_consume_token (parser);
+
+ /* Invoke the RTL parser. */
+ if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
+ return;
+
+ /* If -fsingle-pass=PASS_NAME was provided, locate and run PASS_NAME
+ on cfun, as created above. */
+ if (single_pass_name)
+ run_one_rtl_pass_by_name (single_pass_name);
+}
+
#include "gt-c-c-parser.h"
diff --git a/gcc/read-md.c b/gcc/read-md.c
index be55777..e713466 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -419,6 +419,16 @@ base_rtx_reader::read_char (void)
else
m_read_md_colno++;
+ /* If we're filtering lines, treat everything outside the
+ range of interest as a space. */
+ if (m_first_line && m_last_line)
+ {
+ if (m_read_md_lineno < m_first_line)
+ return ' ';
+ if (m_read_md_lineno > m_last_line)
+ return EOF;
+ }
+
return ch;
}
@@ -1000,7 +1010,9 @@ base_rtx_reader::base_rtx_reader ()
m_read_md_lineno (0),
m_read_md_colno (0),
m_first_dir_md_include (NULL),
- m_last_dir_md_include_ptr (&m_first_dir_md_include)
+ m_last_dir_md_include_ptr (&m_first_dir_md_include),
+ m_first_line (0),
+ m_last_line (0)
{
/* Set the global singleton pointer. */
base_rtx_reader_ptr = this;
@@ -1307,6 +1319,26 @@ base_rtx_reader::read_md_files (int argc, const char **argv,
return !have_error;
}
+/* Read FILENAME, filtering to just the given lines. */
+
+bool
+base_rtx_reader::read_file_fragment (const char *filename,
+ int first_line,
+ int last_line)
+{
+ 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;
+ }
+ m_first_line = first_line;
+ m_last_line = last_line;
+ handle_toplevel_file ();
+ return !have_error;
+}
+
/* class noop_reader : public base_rtx_reader */
/* A dummy implementation which skips unknown directives. */
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 4933912..2058002 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -98,6 +98,9 @@ class base_rtx_reader
virtual ~base_rtx_reader ();
bool read_md_files (int, const char **, bool (*) (const char *));
+ bool read_file_fragment (const char *filename,
+ int first_line,
+ int last_line);
/* A hook that handles a single .md-file directive, up to but not
including the closing ')'. It takes two arguments: the file position
@@ -159,6 +162,10 @@ class base_rtx_reader
/* A pointer to the null terminator of the md include chain. */
file_name_list **m_last_dir_md_include_ptr;
+
+ /* If non-zero, filter the input to just this subset of lines. */
+ int m_first_line;
+ int m_last_line;
};
/* Global singleton; constrast with rtx_reader_ptr below. */
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 0723585..73493ec 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -593,23 +593,31 @@ function_reader::create_function ()
else
rtl_register_cfg_hooks ();
- /* Create cfun. */
- tree fn_name = get_identifier (m_name ? m_name : "test_1");
- tree int_type = integer_type_node;
- tree return_type = int_type;
- tree arg_types[3] = {int_type, int_type, int_type};
- tree fn_type = build_function_type_array (return_type, 3, arg_types);
- tree fndecl = build_decl_stat (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name,
- fn_type);
- tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
- return_type);
- DECL_ARTIFICIAL (resdecl) = 1;
- DECL_IGNORED_P (resdecl) = 1;
- DECL_RESULT (fndecl) = resdecl;
- allocate_struct_function (fndecl, false);
- /* This sets cfun. */
-
- current_function_decl = fndecl;
+ /* When run from selftests or "rtl1", cfun is NULL.
+ When run from "cc1" for a C function tagged with __RTL, cfun is the
+ tagged function. */
+ if (!cfun)
+ {
+ tree fn_name = get_identifier (m_name ? m_name : "test_1");
+ tree int_type = integer_type_node;
+ tree return_type = int_type;
+ tree arg_types[3] = {int_type, int_type, int_type};
+ tree fn_type = build_function_type_array (return_type, 3, arg_types);
+ tree fndecl = build_decl_stat (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name,
+ fn_type);
+ tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
+ return_type);
+ DECL_ARTIFICIAL (resdecl) = 1;
+ DECL_IGNORED_P (resdecl) = 1;
+ DECL_RESULT (fndecl) = resdecl;
+ allocate_struct_function (fndecl, false);
+ /* This sets cfun. */
+ current_function_decl = fndecl;
+ }
+
+ gcc_assert (cfun);
+ gcc_assert (current_function_decl);
+ tree fndecl = current_function_decl;
cfun->curr_properties = (PROP_cfg | PROP_rtl);
@@ -1817,6 +1825,42 @@ read_rtl_function_body (int argc, const char **argv,
return true;
}
+/* Run the RTL dump parser on the range of lines between START_LOC and
+ END_LOC (including those lines). */
+
+bool
+read_rtl_function_body_from_file_range (location_t start_loc,
+ location_t end_loc)
+{
+ expanded_location exploc_start = expand_location (start_loc);
+ expanded_location exploc_end = expand_location (end_loc);
+
+ if (exploc_start.file != exploc_end.file)
+ {
+ error_at (end_loc, "start/end of RTL fragment are in different files");
+ return false;
+ }
+ if (exploc_start.line >= exploc_end.line)
+ {
+ error_at (end_loc,
+ "start of RTL fragment must be on an earlier line than end");
+ return false;
+ }
+
+ in_rtl_frontend_p = true;
+
+ initialize_rtl ();
+ init_emit ();
+ init_varasm_status ();
+
+ function_reader reader (NULL);
+ if (!reader.read_file_fragment (exploc_start.file, exploc_start.line,
+ exploc_end.line - 1))
+ return false;
+
+ return true;
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/read-rtl-function.h b/gcc/read-rtl-function.h
index d26c797..c69d308 100644
--- a/gcc/read-rtl-function.h
+++ b/gcc/read-rtl-function.h
@@ -34,4 +34,7 @@ extern bool read_rtl_function_body (int argc, const char **argv,
function_reader_policy *policy,
int *out_pseudo_offset);
+extern bool read_rtl_function_body_from_file_range (location_t start_loc,
+ location_t end_loc);
+
#endif /* GCC_READ_RTL_FUNCTION_H */
diff --git a/gcc/testsuite/rtl.dg/rtl.exp b/gcc/testsuite/rtl.dg/rtl.exp
index 71bebb9..6c7c7f4 100644
--- a/gcc/testsuite/rtl.dg/rtl.exp
+++ b/gcc/testsuite/rtl.dg/rtl.exp
@@ -29,8 +29,10 @@ if ![info exists DEFAULT_RTLFLAGS] then {
# Initialize `dg'.
dg-init
-# Gather a list of all tests.
+# Gather a list of all tests: both .rtl tests for use with rtl1, and .c tests
+# for use with cc1.
set tests [lsort [find $srcdir/$subdir *.rtl]]
+set tests [concat $tests [lsort [find $srcdir/$subdir *.c]]]
verbose "rtl.exp tests: $tests" 1
diff --git a/gcc/testsuite/rtl.dg/x86_64/different-structs.c b/gcc/testsuite/rtl.dg/x86_64/different-structs.c
new file mode 100644
index 0000000..d5c0bed
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/different-structs.c
@@ -0,0 +1,101 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+extern double sqrt(double x);
+
+struct foo
+{
+ double x;
+ double y;
+};
+
+struct bar
+{
+ double x;
+ double y;
+};
+
+double __RTL test (struct foo *f, const struct bar *b)
+{
+#if 0
+ /* Result of "expand" on this C code, compiled for x86_64 with -Os. */
+ f->x += b->x;
+ f->y += b->y;
+ return sqrt (f->x * f->x + f->y * f->y);
+#endif
+(function "test"
+ (insn-chain
+ (note 1 0 5 (nil) NOTE_INSN_DELETED)
+ (note 5 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (insn 2 5 3 2 (set (reg/v/f:DI 97 [ f ])
+ (reg:DI 5 di [ f ])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:16 -1
+ (nil))
+ (insn 3 2 4 2 (set (reg/v/f:DI 98 [ b ])
+ (reg:DI 4 si [ b ])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:16 -1
+ (nil))
+ (note 4 3 7 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 7 4 8 2 (set (reg:DF 99)
+ (mem:DF (reg/v/f:DI 97 [ f ]) [2 f_11(D)->x+0 S8 A64])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:17 -1
+ (nil))
+ (insn 8 7 9 2 (set (reg:DF 89 [ _3 ])
+ (plus:DF (reg:DF 99)
+ (mem:DF (reg/v/f:DI 98 [ b ]) [2 b_12(D)->x+0 S8 A64]))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:17 -1
+ (nil))
+ (insn 9 8 10 2 (set (mem:DF (reg/v/f:DI 97 [ f ]) [2 f_11(D)->x+0 S8 A64])
+ (reg:DF 89 [ _3 ])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:17 -1
+ (nil))
+ (insn 10 9 11 2 (set (reg:DF 100)
+ (mem:DF (plus:DI (reg/v/f:DI 97 [ f ])
+ (const_int 8 [0x8])) [2 f_11(D)->y+0 S8 A64])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:18 -1
+ (nil))
+ (insn 11 10 12 2 (set (reg:DF 92 [ _6 ])
+ (plus:DF (reg:DF 100)
+ (mem:DF (plus:DI (reg/v/f:DI 98 [ b ])
+ (const_int 8 [0x8])) [2 b_12(D)->y+0 S8 A64]))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:18 -1
+ (nil))
+ (insn 12 11 13 2 (set (mem:DF (plus:DI (reg/v/f:DI 97 [ f ])
+ (const_int 8 [0x8])) [2 f_11(D)->y+0 S8 A64])
+ (reg:DF 92 [ _6 ])) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:18 -1
+ (nil))
+ (insn 13 12 14 2 (set (reg:DF 101)
+ (mult:DF (reg:DF 89 [ _3 ])
+ (reg:DF 89 [ _3 ]))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:19 -1
+ (nil))
+ (insn 14 13 15 2 (set (reg:DF 102)
+ (mult:DF (reg:DF 92 [ _6 ])
+ (reg:DF 92 [ _6 ]))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:19 -1
+ (nil))
+ (insn 15 14 16 2 (set (reg:DF 103)
+ (plus:DF (reg:DF 101)
+ (reg:DF 102))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:19 -1
+ (nil))
+ (insn 16 15 17 2 (set (reg:DF 21 xmm0)
+ (reg:DF 103)) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:19 -1
+ (nil))
+ (call_insn/j 17 16 18 2 (set (reg:DF 21 xmm0)
+ (call (mem:QI (symbol_ref:DI ("sqrt") [flags 0x41] <function_decl 0x7f82b1429d00 sqrt>) [0 __builtin_sqrt S1 A8])
+ (const_int 0 [0]))) ../../src/gcc/testsuite/rtl.dg/x86_64/different-structs.c:19 -1
+ (expr_list:REG_CALL_DECL (symbol_ref:DI ("sqrt") [flags 0x41] <function_decl 0x7f82b1429d00 sqrt>)
+ (expr_list:REG_EH_REGION (const_int 0 [0])
+ (nil)))
+ (expr_list:DF (use (reg:DF 21 xmm0))
+ (nil)))
+ (barrier 18 17 0)
+ ) ;; insn-chain
+ (cfg
+ (bb 0
+ (edge 0 2 (flags 0x1))
+ ) ;; bb
+ (bb 2
+ (edge 2 1 (flags 0x1002))
+ ) ;; bb
+ (bb 1
+ ) ;; bb
+ ) ;; cfg
+ (crtl
+ (return_rtx
+ (reg/i:DF 21 xmm0)
+ ) ;; return_rtx
+ ) ;; crtl
+) ;; function "test"
+
+}
diff --git a/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.after-expand.c b/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.after-expand.c
new file mode 100644
index 0000000..11b6f24
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.after-expand.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+int __RTL test_returning_constant (void)
+{
+ /* C code:
+ return 42; */
+
+ (function "test_returning_constant"
+ (insn-chain
+ (note 1 0 3 (nil) NOTE_INSN_DELETED)
+ (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 5 2 9 2 (set (reg:SI 87 [ <retval> ])
+ (const_int 42 [0x2a])) test-return-const.c:3 -1
+ (nil))
+ (insn 9 5 10 2 (set (reg/i:SI 0 ax)
+ (reg:SI 87 [ <retval> ])) test-return-const.c:4 -1
+ (nil))
+ (insn 10 9 0 2 (use (reg/i:SI 0 ax)) test-return-const.c:4 -1
+ (nil))
+ ) ;; insn-chain
+ );; function
+}
diff --git a/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.before-fwprop.c b/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.before-fwprop.c
new file mode 100644
index 0000000..83594b3
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/test-return-const.c.before-fwprop.c
@@ -0,0 +1,27 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-options "-fdump-rtl-fwprop1" } */
+
+int __RTL ("rtl-fwprop1") test_returning_constant (void)
+{
+ /* C code:
+ return 42; */
+ (function "test"
+ (insn-chain
+ (note 3 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 5 2 9 2 (set (reg:SI 87 [ <retval> ])
+ (const_int 42 [0x2a])) test-return-const.c:3 82 {*movsi_internal}
+ (nil))
+ (insn 9 5 10 2 (set (reg/i:SI 0 ax)
+ (const_int 42 [0x2a])) test-return-const.c:4 82 {*movsi_internal}
+ (expr_list:REG_DEAD (reg:SI 87 [ <retval> ])
+ (nil)))
+ (insn 10 9 0 2 (use (reg/i:SI 0 ax)) test-return-const.c:4 -1
+ (nil))
+ ) ;; insn-chain
+ ) ;; function
+}
+
+/* Verify that insn 5 is eliminated. */
+/* { dg-final { scan-rtl-dump "deferring deletion of insn with uid = 5" "fwprop1" } } */
+/* { dg-final { scan-rtl-dump "Deleted 1 trivially dead insns" "fwprop1" } } */
diff --git a/gcc/testsuite/rtl.dg/x86_64/test-rtl.c b/gcc/testsuite/rtl.dg/x86_64/test-rtl.c
new file mode 100644
index 0000000..0ffeab7
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/test-rtl.c
@@ -0,0 +1,95 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+/* Test of embedding RTL dump in a C function, tagged with "__RTL".
+
+ This is a dump of test.c from immediately after "expand", for x86_64. */
+
+int __RTL test_1 (int i, int j, int k)
+{
+ /*
+ if (i < j)
+ return k + 4;
+ else
+ return -k;
+ */
+ (function "test_1"
+ (insn-chain
+ (note 1 0 6 (nil) NOTE_INSN_DELETED)
+(note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+(insn 2 6 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])
+ (reg:SI 5 di [ i ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1
+ (nil))
+(insn 3 2 4 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32])
+ (reg:SI 4 si [ j ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1
+ (nil))
+(insn 4 3 5 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])
+ (reg:SI 1 dx [ k ])) ../../src/gcc/testsuite/rtl.dg/test.c:2 -1
+ (nil))
+(note 5 4 8 2 NOTE_INSN_FUNCTION_BEG)
+(insn 8 5 9 2 (set (reg:SI 89)
+ (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1
+ (nil))
+(insn 9 8 10 2 (set (reg:CCGC 17 flags)
+ (compare:CCGC (reg:SI 89)
+ (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -8 [0xfffffffffffffff8])) [1 j+0 S4 A32]))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1
+ (nil))
+(jump_insn 10 9 11 2 (set (pc)
+ (if_then_else (ge (reg:CCGC 17 flags)
+ (const_int 0 [0]))
+ (label_ref 16)
+ (pc))) ../../src/gcc/testsuite/rtl.dg/test.c:3 -1
+ (nil)
+ -> 16)
+(note 11 10 12 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
+(insn 12 11 13 4 (set (reg:SI 90)
+ (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1
+ (nil))
+(insn 13 12 14 4 (parallel [
+ (set (reg:SI 87 [ _1 ])
+ (plus:SI (reg:SI 90)
+ (const_int 4 [0x4])))
+ (clobber (reg:CC 17 flags))
+ ]) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1
+ (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])
+ (const_int 4 [0x4]))
+ (nil)))
+(jump_insn 14 13 15 4 (set (pc)
+ (label_ref 20)) ../../src/gcc/testsuite/rtl.dg/test.c:4 -1
+ (nil)
+ -> 20)
+(barrier 15 14 16)
+(code_label 16 15 17 5 2 (nil) [1 uses])
+(note 17 16 18 5 [bb 5] NOTE_INSN_BASIC_BLOCK)
+(insn 18 17 19 5 (set (reg:SI 91)
+ (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32])) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1
+ (nil))
+(insn 19 18 20 5 (parallel [
+ (set (reg:SI 87 [ _1 ])
+ (neg:SI (reg:SI 91)))
+ (clobber (reg:CC 17 flags))
+ ]) ../../src/gcc/testsuite/rtl.dg/test.c:6 -1
+ (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -12 [0xfffffffffffffff4])) [1 k+0 S4 A32]))
+ (nil)))
+(code_label 20 19 21 6 3 (nil) [1 uses])
+(note 21 20 22 6 [bb 6] NOTE_INSN_BASIC_BLOCK)
+(insn 22 21 26 6 (set (reg:SI 88 [ <retval> ])
+ (reg:SI 87 [ _1 ])) -1
+ (nil))
+(insn 26 22 27 6 (set (reg/i:SI 0 ax)
+ (reg:SI 88 [ <retval> ])) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1
+ (nil))
+(insn 27 26 0 6 (use (reg/i:SI 0 ax)) ../../src/gcc/testsuite/rtl.dg/test.c:7 -1
+ (nil))
+
+ ) ;; insn-chain
+ ) ;; function
+}
diff --git a/gcc/testsuite/rtl.dg/x86_64/times-two.c.after-expand.c b/gcc/testsuite/rtl.dg/x86_64/times-two.c.after-expand.c
new file mode 100644
index 0000000..8536bf4
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/times-two.c.after-expand.c
@@ -0,0 +1,40 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+int __RTL times_two (int i)
+{
+ /* C function:
+ return i * 2; */
+ (function "times_two"
+ (insn-chain
+ (note 1 0 4 (nil) NOTE_INSN_DELETED)
+ (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (insn 2 4 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])
+ (reg:SI 5 di [ i ])) times-two.c:2 -1
+ (nil))
+ (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 6 3 7 2 (set (reg:SI 89)
+ (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) times-two.c:3 -1
+ (nil))
+ (insn 7 6 10 2 (parallel [
+ (set (reg:SI 87 [ _2 ])
+ (ashift:SI (reg:SI 89)
+ (const_int 1 [0x1])))
+ (clobber (reg:CC 17 flags))
+ ]) times-two.c:3 -1
+ (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI 82 virtual-stack-vars)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])
+ (const_int 1 [0x1]))
+ (nil)))
+ (insn 10 7 14 2 (set (reg:SI 88 [ <retval> ])
+ (reg:SI 87 [ _2 ])) times-two.c:3 -1
+ (nil))
+ (insn 14 10 15 2 (set (reg/i:SI 0 ax)
+ (reg:SI 88 [ <retval> ])) times-two.c:4 -1
+ (nil))
+ (insn 15 14 0 2 (use (reg/i:SI 0 ax)) times-two.c:4 -1
+ (nil))
+ ) ;; insn-chain
+ ) ;; function
+}
diff --git a/gcc/testsuite/rtl.dg/x86_64/times-two.c.before-df.c b/gcc/testsuite/rtl.dg/x86_64/times-two.c.before-df.c
new file mode 100644
index 0000000..b4d20a7
--- /dev/null
+++ b/gcc/testsuite/rtl.dg/x86_64/times-two.c.before-df.c
@@ -0,0 +1,57 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-options "-fdump-rtl-dfinit" } */
+
+int __RTL ("rtl-dfinit") times_two (int i)
+{
+ /* C function:
+ return i * 2; */
+ (function "times_two"
+ (insn-chain
+ (note 1 0 4 (nil) NOTE_INSN_DELETED)
+ (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (insn 2 4 3 2 (set (mem/c:SI (plus:DI (reg/f:DI 20 frame)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])
+ (reg:SI 5 di [ i ])) times-two.c:2 82 {*movsi_internal}
+ (nil))
+ (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 6 3 7 2 (set (reg:SI 89)
+ (mem/c:SI (plus:DI (reg/f:DI 20 frame)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])) times-two.c:3 82 {*movsi_internal}
+ (nil))
+ (insn 7 6 10 2 (parallel [
+ (set (reg:SI 87 [ _2 ])
+ (ashift:SI (reg:SI 89)
+ (const_int 1 [0x1])))
+ (clobber (reg:CC 17 flags))
+ ]) times-two.c:3 529 {*ashlsi3_1}
+ (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI 20 frame)
+ (const_int -4 [0xfffffffffffffffc])) [1 i+0 S4 A32])
+ (const_int 1 [0x1]))
+ (nil)))
+ (insn 10 7 14 2 (set (reg:SI 88 [ <retval> ])
+ (reg:SI 87 [ _2 ])) times-two.c:3 82 {*movsi_internal}
+ (nil))
+ (insn 14 10 15 2 (set (reg/i:SI 0 ax)
+ (reg:SI 88 [ <retval> ])) times-two.c:4 82 {*movsi_internal}
+ (nil))
+ (insn 15 14 0 2 (use (reg/i:SI 0 ax)) times-two.c:4 -1
+ (nil))
+ ) ;; insn-chain
+
+ (crtl
+ (return_rtx
+ (reg/i:SI 0 ax)
+ ) ;; return_rtx
+ ) ;; crtl
+ ) ;; function
+}
+
+/* Verify that the dataflow information matches what cc1 would have
+ generated. In particular, in earlier versions of the RTL
+ frontend, the exit block use of reg 0 (ax) wasn't picked up
+ on, due to not setting up crtl->return_rtx based on
+ DECL_RESULT (fndecl). */
+
+/* { dg-final { scan-rtl-dump ";; exit block uses.*0 .ax. 6 .bp. 7 .sp. 20 .frame." "dfinit" } } */
+
+/* { dg-final { scan-rtl-dump ";; regs ever live.*0 .ax. 5 .di. 17 .flags." "dfinit" } } */
--
1.8.5.3
More information about the Gcc-patches
mailing list