From fa55708817fe9641046a45a15517c8be79034e8d Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 17 Oct 2016 12:44:04 -0400 Subject: [PATCH 15/20] FIXME: Add "__RTL" to cc1 FIXME: ChangeLog needs updating Changed in this version: * Updated comment to c_parser_declaration_or_fndef to show the new syntax * 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: * Makefile.in (OBJS): Add run-one-rtl-pass.o. * 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. * rtl.c (in_rtl_frontend_p): New global. * rtl.h (in_rtl_frontend_p): New global decl. * run-one-rtl-pass.c: New file. * run-one-rtl-pass.h: New file. * toplev.c (compile_file): Bail out after the parse_file langhook if within the RTL frontend. gcc/testsuite/ChangeLog: * rtl.dg/rtl.exp: New file. * 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. FIXME: WIP on consolidating test cases --- gcc/Makefile.in | 1 + 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/rtl.c | 2 + gcc/rtl.h | 1 + gcc/run-one-rtl-pass.c | 120 +++++++++++++++++ gcc/run-one-rtl-pass.h | 25 ++++ gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c | 35 +++++ gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c | 47 +++++++ gcc/testsuite/gcc.dg/rtl/rtl.exp | 41 ++++++ gcc/testsuite/gcc.dg/rtl/test.c | 31 +++++ gcc/testsuite/gcc.dg/rtl/unknown-rtx-code.c | 8 ++ gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c | 116 ++++++++++++++++ .../gcc.dg/rtl/x86_64/different-structs.c | 95 +++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/final.c | 150 +++++++++++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c | 117 ++++++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/ira.c | 111 +++++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/pro_and_epilogue.c | 110 +++++++++++++++ .../rtl/x86_64/test-return-const.c.after-expand.c | 34 +++++ .../rtl/x86_64/test-return-const.c.before-fwprop.c | 36 +++++ gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c | 115 ++++++++++++++++ .../gcc.dg/rtl/x86_64/times-two.c.after-expand.c | 49 +++++++ .../gcc.dg/rtl/x86_64/times-two.c.before-df.c | 60 +++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c | 112 +++++++++++++++ gcc/toplev.c | 7 + 30 files changed, 1642 insertions(+), 20 deletions(-) create mode 100644 gcc/run-one-rtl-pass.c create mode 100644 gcc/run-one-rtl-pass.h create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c create mode 100644 gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c create mode 100644 gcc/testsuite/gcc.dg/rtl/rtl.exp create mode 100644 gcc/testsuite/gcc.dg/rtl/test.c create mode 100644 gcc/testsuite/gcc.dg/rtl/unknown-rtx-code.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/final.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/ira.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/pro_and_epilogue.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.after-expand.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.before-df.c create mode 100644 gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 83c1f29..8f54b0b 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1427,6 +1427,7 @@ OBJS = \ rtlhash.o \ rtlanal.o \ rtlhooks.o \ + run-one-rtl-pass.o \ sbitmap.o \ sched-deps.o \ sched-ebb.o \ diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index c4a0ce8..2441400 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -527,6 +527,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 8ef1d74..cebc282 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 e869e53..46e08fe 100644 --- a/gcc/read-md.c +++ b/gcc/read-md.c @@ -399,6 +399,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; } @@ -981,7 +991,9 @@ base_rtx_reader::base_rtx_reader (bool compact) 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; @@ -1284,6 +1296,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 dac76d3..2ad3bcd 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 @@ -232,6 +235,10 @@ class base_rtx_reader /* A table of enum_type structures, hashed by name. */ htab_t m_enum_types; + + /* 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 c315907..3e7adb7 100644 --- a/gcc/read-rtl-function.c +++ b/gcc/read-rtl-function.c @@ -576,23 +576,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); @@ -1657,6 +1665,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 036fcce..d5d12ab 100644 --- a/gcc/read-rtl-function.h +++ b/gcc/read-rtl-function.h @@ -33,4 +33,7 @@ extern bool read_rtl_function_body (int argc, const char **argv, bool (*parse_opt) (const char *), function_reader_policy *policy); +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/rtl.c b/gcc/rtl.c index a445cdc..9729c82 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -878,3 +878,5 @@ rtl_check_failed_flag (const char *name, const_rtx r, const char *file, name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); } #endif /* ENABLE_RTL_FLAG_CHECKING */ + +bool in_rtl_frontend_p = false; diff --git a/gcc/rtl.h b/gcc/rtl.h index 5541a78..65d917e 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3755,5 +3755,6 @@ struct GTY(()) cgraph_rtl_info { unsigned function_used_regs_valid: 1; }; +extern bool in_rtl_frontend_p; #endif /* ! GCC_RTL_H */ diff --git a/gcc/run-one-rtl-pass.c b/gcc/run-one-rtl-pass.c new file mode 100644 index 0000000..ecb7bf0 --- /dev/null +++ b/gcc/run-one-rtl-pass.c @@ -0,0 +1,120 @@ +/* run-one-rtl-pass.c - Run just one RTL pass + Copyright (C) 2016 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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "tree.h" +#include "gimple-expr.h" +#include "diagnostic.h" +#include "opts.h" +#include "fold-const.h" +#include "gimplify.h" +#include "stor-layout.h" +#include "debug.h" +#include "convert.h" +#include "langhooks.h" +#include "langhooks-def.h" +#include "common/common-target.h" +#include "read-md.h" +#include +#include "rtl.h" +#include "cfghooks.h" +#include "stringpool.h" +#include "function.h" +#include "tree-cfg.h" +#include "cfg.h" +#include "basic-block.h" +#include "cfgrtl.h" +#include "memmodel.h" +#include "emit-rtl.h" +#include "cgraph.h" +#include "tree-pass.h" +#include "context.h" +#include "pass_manager.h" +#include "toplev.h" +#include "bitmap.h" +#include "df.h" +#include "regs.h" +#include "varasm.h" +#include "insn-addr.h" + +/* Locate and run PASS_NAME on cfun. */ + +void +run_one_rtl_pass_by_name (const char *pass_name) +{ + opt_pass *pass = g->get_passes ()->get_pass_by_name (pass_name); + if (!pass) + { + error_at (UNKNOWN_LOCATION, "unrecognized pass: %qs", pass_name); + return; + } + + /* Forcibly create the dataflow instance. We'll need to do this on passes + that normally occur after pass_df_initialize/pass_df_initialize_no_opt. */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-cse1") + || 0 == strcmp (pass_name, "rtl-fwprop1") + || 0 == strcmp (pass_name, "rtl-combine") + || 0 == strcmp (pass_name, "rtl-ira") + || 0 == strcmp (pass_name, "rtl-reload") + || 0 == strcmp (pass_name, "rtl-pro_and_epilogue")) + { + opt_pass *df_pass = g->get_passes ()->get_pass_by_name ("rtl-dfinit"); + gcc_assert (df_pass); + current_function_decl = cfun->decl; + df_pass->execute (cfun); + + /* The dataflow instance should now exist. */ + gcc_assert (df); + + df_analyze (); + } + + /* Ensure reg_renumber is set up. */ + resize_reg_info (); + + max_regno = max_reg_num (); + + /* Pass "reload" sets the global "reload_completed", and many things + depend on this (e.g. instructions in .md files). */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-final")) + reload_completed = 1; + + /* The INSN_ADDRESSES vec is normally set up by shorten_branches; we must + manually set it up for passes that run after this. */ + /* FIXME: better conditional logic here. */ + if (0 == strcmp (pass_name, "rtl-final")) + INSN_ADDRESSES_ALLOC (get_max_uid ()); + + /* Run the user-specified pass. */ + bitmap_obstack_initialize (NULL); + bitmap_obstack_initialize (®_obstack); + pass_init_dump_file (pass); + current_function_decl = cfun->decl; + pass->execute (cfun); + current_function_decl = NULL; + if (dump_file) + print_rtl_with_bb (dump_file, get_insns (), dump_flags); + pass_fini_dump_file (pass); + bitmap_obstack_release (®_obstack); +} diff --git a/gcc/run-one-rtl-pass.h b/gcc/run-one-rtl-pass.h new file mode 100644 index 0000000..40d60ba --- /dev/null +++ b/gcc/run-one-rtl-pass.h @@ -0,0 +1,25 @@ +/* run-one-rtl-pass.h - Run just one RTL pass + Copyright (C) 2016 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 +. */ + +#ifndef GCC_RUN_ONE_RTL_PASS_H +#define GCC_RUN_ONE_RTL_PASS_H + +extern void run_one_rtl_pass_by_name (const char *pass_name); + +#endif /* GCC_RUN_ONE_RTL_PASS_H */ diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c b/gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c new file mode 100644 index 0000000..457519e --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c @@ -0,0 +1,35 @@ +/* { dg-do compile { target aarch64-*-* } } */ +/* { dg-options "-mtune=cortex-a53 -fdump-rtl-combine" } */ + +/* Taken from + gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53 + for aarch64, hand editing the prev/next insns to 0 as needed, and + editing whitespace to avoid over-long lines. */ + +int __RTL("rtl-combine") f1 (int n) +{ +(function "f1" + (insn-chain + +(insn 8 0 9 2 (set (reg:DI 78) + (lshiftrt:DI (reg:DI 76) + (const_int 32 [0x20]))) + ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 + 641 {*aarch64_lshr_sisd_or_int_di3} + (expr_list:REG_DEAD (reg:DI 76) + (nil))) +(insn 9 8 0 2 (set (reg:SI 79) + (ashiftrt:SI (subreg:SI (reg:DI 78) 0) + (const_int 3 [0x3]))) + ../../src/gcc/testsuite/gcc.dg/asr_div1.c:14 + 642 {*aarch64_ashr_sisd_or_int_si3} + (expr_list:REG_DEAD (reg:DI 78) + (nil))) + + ) ;; insn-chain +) ;; function +} + +/* Verify that insns 8 and 9 get combined into a shift of 35 (0x23) */ +/* { dg-final { scan-rtl-dump "allowing combination of insns 8 and 9" "combine" } } */ +/* { dg-final { scan-rtl-dump "modifying insn i3 9: r79:SI#0=r76:DI>>0x23" "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c b/gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c new file mode 100644 index 0000000..545e85a --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c @@ -0,0 +1,47 @@ +/* { dg-do compile { target aarch64-*-* } } */ +/* { dg-options "-fdump-rtl-cse1" } */ + +/* Dump taken from comment 2 of PR 71779, of + "...the relevant memory access coming out of expand" + with basic block IDs added, and prev/next insns set to + 0 at ends, and 'p' added to pseudo regnos. */ + +int __RTL("rtl-cse1") test (int n) +{ +(function "fragment" + (insn-chain + +;; MEM[(struct isl_obj *)&obj1] = &isl_obj_map_vtable; +(insn 1045 0 1046 2 (set (reg:SI 480) + (high:SI (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ))) + y.c:12702 -1 + (nil)) +(insn 1046 1045 1047 2 (set (reg/f:SI 479) + (lo_sum:SI (reg:SI 480) + (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ))) + y.c:12702 -1 + (expr_list:REG_EQUAL (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ) + (nil))) +(insn 1047 1046 1048 2 (set (reg:DI 481) + (subreg:DI (reg/f:SI 479) 0)) y.c:12702 -1 + (nil)) +(insn 1048 1047 1049 2 (set (zero_extract:DI (reg/v:DI 191 [ obj1D.17368 ]) + (const_int 32 [0x20]) + (const_int 0 [0])) + (reg:DI 481)) y.c:12702 -1 + (nil)) +;; Extra insn, to avoid all of the above from being deleted by DCE +(insn 1049 1048 0 2 (set (mem:DI (reg:DI 191) [1 i+0 S4 A32]) + (const_int 1 [0x1])) -1 (nil)) + + ) ;; insn-chain +) ;; function +} + +/* TODO: scan the dump. */ diff --git a/gcc/testsuite/gcc.dg/rtl/rtl.exp b/gcc/testsuite/gcc.dg/rtl/rtl.exp new file mode 100644 index 0000000..3c6648b --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/rtl.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2016 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_RTLFLAGS +if ![info exists DEFAULT_RTLFLAGS] then { + set DEFAULT_RTLFLAGS "" + # -fdump-tree-rtl-raw +} + +# Initialize `dg'. +dg-init + +# Gather a list of all tests. +set tests [lsort [find $srcdir/$subdir *.c]] + +verbose "rtl.exp tests: $tests" 1 + +# Main loop. +dg-runtest $tests "" $DEFAULT_RTLFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.dg/rtl/test.c b/gcc/testsuite/gcc.dg/rtl/test.c new file mode 100644 index 0000000..ebb8aef --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/test.c @@ -0,0 +1,31 @@ +int test_1 (int i, int j, int k) +{ + if (i < j) + return k + 4; + else + return -k; +} + +/* Example showing: + - data structure + - loop + - call to "abort". */ + +struct foo +{ + int count; + float *data; +}; + +float test_2 (struct foo *lhs, struct foo *rhs) +{ + float result = 0.0f; + + if (lhs->count != rhs->count) + __builtin_abort (); + + for (int i = 0; i < lhs->count; i++) + result += lhs->data[i] * rhs->data[i]; + + return result; +} diff --git a/gcc/testsuite/gcc.dg/rtl/unknown-rtx-code.c b/gcc/testsuite/gcc.dg/rtl/unknown-rtx-code.c new file mode 100644 index 0000000..dd252f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/unknown-rtx-code.c @@ -0,0 +1,8 @@ +void __RTL test (void) +{ + (function "test" + (insn-chain + (not-a-valid-kind-of-insn 1 0 0) ;; { dg-error "unknown rtx code" } + ) ;; insn-chain + ) ;; function +} diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c b/gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c new file mode 100644 index 0000000..51a5e9f --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c @@ -0,0 +1,116 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-dfinit" } */ + +/* Lightly-modified dump of test.c.257r.split1 for x86_64. */ + +int __RTL("rtl-dfinit") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %3) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (plus:SI (reg:SI %3) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 5) + ) ;; block 3 + (cbarrier) + (block 4 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %4) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (neg:SI (reg:SI %4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 5 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* 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. 1 .dx. 4 .si. 5 .di. 17 .flags." "dfinit" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c b/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c new file mode 100644 index 0000000..5390146 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c @@ -0,0 +1,95 @@ +/* { 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 + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg/v/f:DI %10 [ f ]) + (reg:DI di [ f ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":18 + (nil)) + (cinsn (set (reg/v/f:DI %11 [ b ]) + (reg:DI si [ b ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":18 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:DF %12) + (mem:DF (reg/v/f:DI %10 [ f ]) [2 f_11(D)->x+0 S8 A64])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":21 + (nil)) + (cinsn (set (reg:DF %2 [ _3 ]) + (plus:DF (reg:DF %12) + (mem:DF (reg/v/f:DI %11 [ b ]) [2 b_12(D)->x+0 S8 A64]))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":21 + (nil)) + (cinsn (set (mem:DF (reg/v/f:DI %10 [ f ]) [2 f_11(D)->x+0 S8 A64]) + (reg:DF %2 [ _3 ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":21 + (nil)) + (cinsn (set (reg:DF %13) + (mem:DF (plus:DI (reg/v/f:DI %10 [ f ]) + (const_int 8)) [2 f_11(D)->y+0 S8 A64])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":22 + (nil)) + (cinsn (set (reg:DF %5 [ _6 ]) + (plus:DF (reg:DF %13) + (mem:DF (plus:DI (reg/v/f:DI %11 [ b ]) + (const_int 8)) [2 b_12(D)->y+0 S8 A64]))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":22 + (nil)) + (cinsn (set (mem:DF (plus:DI (reg/v/f:DI %10 [ f ]) + (const_int 8)) [2 f_11(D)->y+0 S8 A64]) + (reg:DF %5 [ _6 ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":22 + (nil)) + (cinsn (set (reg:DF %14) + (mult:DF (reg:DF %2 [ _3 ]) + (reg:DF %2 [ _3 ]))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 + (nil)) + (cinsn (set (reg:DF %15) + (mult:DF (reg:DF %5 [ _6 ]) + (reg:DF %5 [ _6 ]))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 + (nil)) + (cinsn (set (reg:DF %16) + (plus:DF (reg:DF %14) + (reg:DF %15))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 + (nil)) + (cinsn (set (reg:DF xmm0) + (reg:DF %16)) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 + (nil)) + (ccall_insn/j (set (reg:DF xmm0) + (call (mem:QI (symbol_ref:DI ("sqrt") [flags 0x41] ) [0 __builtin_sqrt S1 A8]) + (const_int 0))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23 + (expr_list:REG_CALL_DECL (symbol_ref:DI ("sqrt") [flags 0x41] ) + (expr_list:REG_EH_REGION (const_int 0) + (nil))) + (expr_list:DF (use (reg:DF xmm0)) + (nil))) + (edge-to exit (flags "ABNORMAL | SIBCALL")) + ) ;; block 2 + (cbarrier) + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:DF xmm0) + ) ;; return_rtx + ) ;; crtl +) ;; function "test" + +} diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/final.c b/gcc/testsuite/gcc.dg/rtl/x86_64/final.c new file mode 100644 index 0000000..81d1031 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/final.c @@ -0,0 +1,150 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-final" } */ + +/* Lightly-modified dump of test.c.300r.dwarf2 for x86_64 target. */ + +int __RTL("rtl-final") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn/f (set (mem:DI (pre_dec:DI (reg/f:DI sp)) [0 S8 A8]) + (reg/f:DI bp)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote + .cfi_def_cfa_offset 16 + NOTE_INSN_CFI) + (cnote + .cfi_offset 6, -16 + NOTE_INSN_CFI) + (cinsn/f (set (reg/f:DI bp) + (reg/f:DI sp)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote + .cfi_def_cfa_register 6 + NOTE_INSN_CFI) + (cinsn (set (mem/v:BLK (scratch:DI) [0 A8]) + (unspec:BLK [ + (mem/v:BLK (scratch:DI) [0 A8]) + ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_PROLOGUE_END) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI ax [89]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI ax [89]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI ax [90]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI ax [orig:87 _1 ] [87]) + (plus:SI (reg:SI ax [90]) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 5) + ) ;; block 3 + (cbarrier) + (block 4 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI ax [91]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI ax [orig:87 _1 ] [87]) + (neg:SI (reg:SI ax [91]))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cnote NOTE_INSN_EPILOGUE_BEG) + (cinsn (set (mem/v:BLK (scratch:DI) [0 A8]) + (unspec:BLK [ + (mem/v:BLK (scratch:DI) [0 A8]) + ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn/f (set (reg/f:DI bp) + (mem:DI (post_inc:DI (reg/f:DI sp)) [0 S8 A8])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (expr_list:REG_CFA_DEF_CFA (plus:DI (reg/f:DI sp) + (const_int 8)) + (nil))) + (cnote + .cfi_def_cfa 7, 8 + NOTE_INSN_CFI) + (cjump_insn (simple_return) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit) + ) ;; block 5 + (cbarrier) + (cnote NOTE_INSN_DELETED) + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* Verify that asm was emitted. */ +/* { dg-final { scan-assembler "test_1:" } } */ +/* { dg-final { scan-assembler ".cfi_startproc" } } */ +/* { dg-final { scan-assembler ".cfi_endproc" } } */ + +/* Verify that the "simple_return" was recognized. + FIXME: this assumes i386.md. */ +/* { dg-final { scan-assembler "ret" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c b/gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c new file mode 100644 index 0000000..4c1cf8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c @@ -0,0 +1,117 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-into_cfglayout" } */ + +/* Lightly-modified dump of test.c.222r.vregs for x86_64. */ + +int __RTL("rtl-into_cfglayout") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %3) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (plus:SI (reg:SI %3) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 6) + ) ;; block 4 + (cbarrier) + (block 5 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %4) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (neg:SI (reg:SI %4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3 (nil)) + (cnote [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 6 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* The conversion to cfglayout should eliminate unconditional jump + instructions... */ +/* { dg-final { scan-rtl-dump "Removing jump 14." "into_cfglayout" } } */ +/* { dg-final { scan-rtl-dump-not "jump_insn 14" "into_cfglayout" } } */ +/* { dg-final { scan-rtl-dump-not "barrier 15" "into_cfglayout" } } */ + +/* ...but conditional jumps should be preserved. */ +/* { dg-final { scan-rtl-dump "jump_insn 10" "into_cfglayout" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/ira.c b/gcc/testsuite/gcc.dg/rtl/x86_64/ira.c new file mode 100644 index 0000000..3d0efa4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/ira.c @@ -0,0 +1,111 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-ira" } */ + +/* Lightly-modified dump of test.c.261r.asmcons for x86_64. */ + +int __RTL ("rtl-ira") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %3) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (plus:SI (reg:SI %3) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 5) + ) ;; block 3 + (cbarrier) + (block 4 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %4) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (neg:SI (reg:SI %4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 5 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* Verify that IRA was run. */ +/* { dg-final { scan-rtl-dump "Building IRA IR" "ira" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/pro_and_epilogue.c b/gcc/testsuite/gcc.dg/rtl/x86_64/pro_and_epilogue.c new file mode 100644 index 0000000..d94206b --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/pro_and_epilogue.c @@ -0,0 +1,110 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-pro_and_epilogue" } */ + +/* Lightly-modified dump of test.c.270r.split2 for x86_64. */ + +int __RTL("rtl-pro_and_epilogue") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI ax [89]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI ax [89]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI ax [90]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI ax [orig:87 _1 ] [87]) + (plus:SI (reg:SI ax [90]) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 5) + ) ;; block 3 + (cbarrier) + (block 4 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI ax [91]) + (mem/c:SI (plus:DI (reg/f:DI bp) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI ax [orig:87 _1 ] [87]) + (neg:SI (reg:SI ax [91]))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 5 + (cnote NOTE_INSN_DELETED) + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* Verify that the prologue and epilogue were added. */ +/* { dg-final { scan-rtl-dump-times "NOTE_INSN_PROLOGUE_END" 1 "pro_and_epilogue" } } */ + +/* We expect a jump_insn to "simple_return". */ +/* { dg-final { scan-rtl-dump-times "simple_return" 2 "pro_and_epilogue" } } */ + diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c new file mode 100644 index 0000000..b080f84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target x86_64-*-* } } */ + +int __RTL test_returning_constant (void) +{ + /* C code: + return 42; */ +(function "test_returning_constant" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %0 [ _1 ]) + (const_int 42)) "../../src/test-return-const.c":3 + (nil)) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) "../../src/test-return-const.c":3 + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/test-return-const.c":4 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/test-return-const.c":4 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_returning_constant" +} diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c new file mode 100644 index 0000000..37cd10c --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c @@ -0,0 +1,36 @@ +/* { 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_returning_constant" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %0 [ ]) + (const_int 42)) "../../src/test-return-const.c":3 + (nil)) + (cinsn (set (reg/i:SI ax) + (const_int 42)) "../../src/test-return-const.c":4 + (expr_list:REG_DEAD (reg:SI %0 [ ]) + (nil))) + (cinsn (use (reg/i:SI ax)) "../../src/test-return-const.c":4 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_returning_constant" +} + +/* Verify that insn 3 is eliminated. */ +/* { dg-final { scan-rtl-dump "deferring deletion of insn with uid = 3" "fwprop1" } } */ +/* { dg-final { scan-rtl-dump "Deleted 1 trivially dead insns" "fwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c b/gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c new file mode 100644 index 0000000..9bd1bf1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c @@ -0,0 +1,115 @@ +/* { 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 + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (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/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %3) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (plus:SI (reg:SI %3) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 6) + ) ;; block 4 + (cbarrier) + (block 5 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %4) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (neg:SI (reg:SI %4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3 (nil)) + (cnote [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 6 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.after-expand.c b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.after-expand.c new file mode 100644 index 0000000..232ff0d --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.after-expand.c @@ -0,0 +1,49 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ + +int __RTL times_two (int i) +{ + /* C function: + return i * 2; */ +(function "times_two" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (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 NOTE_INSN_FUNCTION_BEG) + (cinsn (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 (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 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _2 ])) "../../src/times-two.c":3 + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/times-two.c":4 + (nil)) + (cinsn (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" +} diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.before-df.c b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.before-df.c new file mode 100644 index 0000000..0cccbd7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.before-df.c @@ -0,0 +1,60 @@ +/* { 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 + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/times-two.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) "../../src/times-two.c":3 + (nil)) + (cinsn (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 frame) + (const_int -4)) [1 i+0 S4 A32]) + (const_int 1)) + (nil))) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _2 ])) "../../src/times-two.c":3 + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/times-two.c":4 + (nil)) + (cinsn (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" +} + +/* 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" } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c b/gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c new file mode 100644 index 0000000..6250aa7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c @@ -0,0 +1,112 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-vregs" } */ + +/* Lightly-modified dump of test.c.221r.expand for x86_64. */ + +int __RTL("rtl-vregs") test_1 (int i, int j, int k) +{ +(function "test_1" + (insn-chain + (cnote NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn (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/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -8)) [1 j+0 S4 A32]) + (reg:SI si [ j ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cinsn (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32]) + (reg:SI dx [ k ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2 + (nil)) + (cnote NOTE_INSN_FUNCTION_BEG) + (cinsn (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cinsn (set (reg:CCGC flags) + (compare:CCGC (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -8)) [1 j+0 S4 A32]))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (cjump_insn (set (pc) + (if_then_else (ge (reg:CCGC flags) + (const_int 0)) + (label_ref 16) + (pc))) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":3 + (nil)) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %3) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (plus:SI (reg:SI %3) + (const_int 4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (expr_list:REG_EQUAL (plus:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32]) + (const_int 4)) + (nil))) + (cjump_insn (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4 + (nil)) + (edge-to 6) + ) ;; block 4 + (cbarrier) + (block 5 + (edge-from 2) + (clabel 16 2 (nil)) + (cnote [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %4) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (nil)) + (cinsn (parallel [ + (set (reg:SI %0 [ _1 ]) + (neg:SI (reg:SI %4))) + (clobber (reg:CC flags)) + ]) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":6 + (expr_list:REG_EQUAL (neg:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -12)) [1 k+0 S4 A32])) + (nil))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3 (nil)) + (cnote [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) + (nil)) + (cinsn (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (cinsn (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 6 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_1" +} + +/* The 9 instances of "virtual-stack-vars" should now all be "frame". */ +/* { dg-final { scan-rtl-dump-times "frame" 9 "vregs" } } */ +/* { dg-final { scan-rtl-dump-not "virtual-stack-vars" "vregs" } } */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 1df80d0..9e266a3 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -479,6 +479,13 @@ compile_file (void) if (flag_syntax_only || flag_wpa) return; + /* The RTL frontend is currently only capable of running one pass; this + is done from within the parse_file langhook. + Hence we must return early here. Fixing this would require + being able to run passes from a certain point onwards. */ + if (in_rtl_frontend_p) + return; + /* Reset maximum_field_alignment, it can be adjusted by #pragma pack and this shouldn't influence any types built by the middle-end from now on (like gcov_info_type). */ -- 1.8.5.3