From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 88597 invoked by alias); 2 Dec 2016 01:28:17 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 88465 invoked by uid 89); 2 Dec 2016 01:28:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.9 required=5.0 tests=BAYES_50,KAM_STOCKGEN autolearn=no version=3.3.2 spammy=transferring, base2, 989, sk:announc X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 02 Dec 2016 01:27:44 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cCcdR-0007Zw-FA for gcc-patches@gcc.gnu.org; Thu, 01 Dec 2016 20:27:42 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40444) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cCcdQ-0007X2-Vo for gcc-patches@gcc.gnu.org; Thu, 01 Dec 2016 20:27:33 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E12A461E5F for ; Fri, 2 Dec 2016 01:27:29 +0000 (UTC) Received: from c64.redhat.com (vpn-227-203.phx2.redhat.com [10.3.227.203]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uB21RPmB004592; Thu, 1 Dec 2016 20:27:29 -0500 From: David Malcolm To: Bernd Schmidt , gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 9/9] Add "__RTL" to cc1 (v6) Date: Fri, 02 Dec 2016 01:28:00 -0000 Message-Id: <1480644013-3660-5-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1480644013-3660-1-git-send-email-dmalcolm@redhat.com> References: <1480628601.24224.64.camel@redhat.com> <1480644013-3660-1-git-send-email-dmalcolm@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 X-IsSubscribed: yes X-SW-Source: 2016-12/txt/msg00151.txt.bz2 Changed in v6: - Handle EOF in c_parser_parse_rtl_body - Various fixups from review Changed in v5: - rebased from r242065 to r242392. In particular, this brings in the gimple FE; rewrote the "startwith" pass-skipping mechanism to work with both __GIMPLE and __RTL. - rewrote the "__RTL" parser so that it shares code with the "__GIMPLE" parser, within c_parser_declspecs. Updated all the test cases to use the 'startwith' syntax. The gimple FE has a "flag_gimple" to enable __GIMPLE; should I add an equivalent for __RTL? - eliminated the new "native_RTL" field, instead just using curr_properties & PROP_rtl. - added original_copy_tables_initialized_p and reinstate: gcc_assert (original_copy_bb_pool); within free_original_copy_tables. - added a test of multiple __RTL-marked functions within one test case. Links to previous versions: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00263.html https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00500.html **************************************************************************** gcc/ChangeLog: * Makefile.in (OBJS): Add run-rtl-passes.o. 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-rtl-passes.h". (c_parser_declaration_or_fndef): Rename "gimple-pass-list" in grammar to gimple-or-rtl-pass-list. Add rtl-function-definition production. Update for renaming of field "gimple_pass" to "gimple_or_rtl_pass". If __RTL was seen, call c_parser_parse_rtl_body. Convert a timevar_push/pop pair to an auto_timevar, to cope with early exit. (c_parser_declspecs): Update RID_GIMPLE handling for renaming of field "gimple_pass" to "gimple_or_rtl_pass", and for renaming of c_parser_gimple_pass_list to c_parser_gimple_or_rtl_pass_list. Handle RID_RTL. (c_parser_parse_rtl_body): New function. * c-tree.h (enum c_declspec_word): Add cdw_rtl. (struct c_declspecs): Rename field "gimple_pass" to "gimple_or_rtl_pass". Add field "rtl_p". * gimple-parser.c (c_parser_gimple_pass_list): Rename to... (c_parser_gimple_or_rtl_pass_list): ...this, updating accordingly. * gimple-parser.h (c_parser_gimple_pass_list): Rename to... (c_parser_gimple_or_rtl_pass_list): ...this. gcc/ChangeLog: * cfg.c (original_copy_tables_initialized_p): New function. * cfg.h (original_copy_tables_initialized_p): New decl. * cfgrtl.c (relink_block_chain): Guard the call to free_original_copy_tables with a call to original_copy_tables_initialized_p. * cgraph.h (symtab_node::native_rtl_p): New decl. * cgraphunit.c (symtab_node::native_rtl_p): New function. (symtab_node::needed_p): Don't assert for early assembly output for __RTL functions. (cgraph_node::finalize_function): Set "force_output" for __RTL functions. (cgraph_node::analyze): Bail out early for __RTL functions. (analyze_functions): Update assertion to support __RTL functions. (cgraph_node::expand): Bail out early for __RTL functions. * final.c (rest_of_clean_state): Don't call delete_tree_ssa for _RTL functions. * gimple-expr.c: Include "tree-pass.h". (gimple_has_body_p): Return false for __RTL functions. * pass_manager.h (gcc::pass_manager::get_rest_of_compilation): New accessor. (gcc::pass_manager::get_clean_slate): New accessor. * passes.c: Include "insn-addr.h". (execute_one_pass): Split out logic for skipping passes into... (determine_pass_name_match): ...this new function, ... (should_skip_pass_p): ...and this new function, adding logging and special-casing dfinit. (skip_pass): New function. * read-md.c (md_reader::read_char): Support filtering the input to a subset of line numbers. (md_reader::md_reader): Initialize fields m_first_line and m_last_line. (md_reader::read_file_fragment): New function. * read-md.h (md_reader::read_file_fragment): New decl. (md_reader::m_first_line): New field. (md_reader::int m_last_line): New field. * read-rtl-function.c (function_reader::create_function): Only create cfun if it doesn't already exist. Set PROP_rtl on cfun's curr_properties. Set DECL_INITIAL to a dummy block. (read_rtl_function_body_from_file_range): New function. * read-rtl-function.h (read_rtl_function_body_from_file_range): New decl. * run-rtl-passes.c: New file. * run-rtl-passes.h: New file. gcc/testsuite/ChangeLog: * gcc.dg/rtl/aarch64/asr_div1.c: New file. * gcc.dg/rtl/aarch64/pr71779.c: New file. * gcc.dg/rtl/rtl.exp: New file. * gcc.dg/rtl/test.c: New file. * gcc.dg/rtl/truncated-rtl-file.c: New file. * gcc.dg/rtl/unknown-rtx-code.c: New file. * gcc.dg/rtl/x86_64/dfinit.c: New file. * gcc.dg/rtl/x86_64/different-structs.c: New file. * gcc.dg/rtl/x86_64/final.c: New file. * gcc.dg/rtl/x86_64/into-cfglayout.c: New file. * gcc.dg/rtl/x86_64/ira.c: New file. * gcc.dg/rtl/x86_64/pro_and_epilogue.c: New file. * gcc.dg/rtl/x86_64/test-multiple-fns.c: New file. * gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c: New file. * gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c: New file. * gcc.dg/rtl/x86_64/test-rtl.c: New file. * gcc.dg/rtl/x86_64/test_1.h: New file. * gcc.dg/rtl/x86_64/times-two.c.after-expand.c: New file. * gcc.dg/rtl/x86_64/times-two.c.before-df.c: New file. * gcc.dg/rtl/x86_64/vregs.c: New file. --- gcc/Makefile.in | 1 + gcc/c-family/c-common.c | 1 + gcc/c-family/c-common.h | 3 + gcc/c/c-parser.c | 109 ++++++++++++++++- gcc/c/c-tree.h | 7 +- gcc/c/gimple-parser.c | 8 +- gcc/c/gimple-parser.h | 2 +- gcc/cfg.c | 9 ++ gcc/cfg.h | 1 + gcc/cfgrtl.c | 3 +- gcc/cgraph.h | 4 + gcc/cgraphunit.c | 41 ++++++- gcc/final.c | 3 +- gcc/function.h | 2 +- gcc/gimple-expr.c | 3 +- gcc/pass_manager.h | 6 + gcc/passes.c | 130 ++++++++++++++++---- gcc/read-md.c | 35 +++++- gcc/read-md.h | 7 ++ gcc/read-rtl-function.c | 83 ++++++++++--- gcc/read-rtl-function.h | 3 + gcc/run-rtl-passes.c | 88 ++++++++++++++ gcc/run-rtl-passes.h | 25 ++++ gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c | 41 +++++++ gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c | 50 ++++++++ gcc/testsuite/gcc.dg/rtl/rtl.exp | 41 +++++++ gcc/testsuite/gcc.dg/rtl/test.c | 31 +++++ gcc/testsuite/gcc.dg/rtl/truncated-rtl-file.c | 2 + 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 | 81 +++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/final.c | 133 +++++++++++++++++++++ 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 +++++++++++++++++ .../gcc.dg/rtl/x86_64/test-multiple-fns.c | 105 ++++++++++++++++ .../rtl/x86_64/test-return-const.c.after-expand.c | 39 ++++++ .../rtl/x86_64/test-return-const.c.before-fwprop.c | 42 +++++++ gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c | 101 ++++++++++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/test_1.h | 16 +++ .../gcc.dg/rtl/x86_64/times-two.c.after-expand.c | 70 +++++++++++ .../gcc.dg/rtl/x86_64/times-two.c.before-df.c | 54 +++++++++ gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c | 112 +++++++++++++++++ 43 files changed, 1891 insertions(+), 63 deletions(-) create mode 100644 gcc/run-rtl-passes.c create mode 100644 gcc/run-rtl-passes.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/truncated-rtl-file.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-multiple-fns.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/test_1.h 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 73d12dc..14ffb96 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1429,6 +1429,7 @@ OBJS = \ rtlhash.o \ rtlanal.o \ rtlhooks.o \ + run-rtl-passes.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 2997c83..7ba3539 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -437,6 +437,7 @@ const struct c_common_resword c_common_reswords[] = { "__volatile__", RID_VOLATILE, 0 }, { "__GIMPLE", RID_GIMPLE, D_CONLY }, { "__PHI", RID_PHI, D_CONLY }, + { "__RTL", RID_RTL, D_CONLY }, { "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 241b345..89a5f6f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -124,6 +124,9 @@ enum rid /* "__PHI", for parsing PHI function in GIMPLE FE. */ RID_PHI, + /* "__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 00fe731..fef882a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -61,6 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "gcc-rich-location.h" #include "c-parser.h" #include "gimple-parser.h" +#include "read-rtl-function.h" +#include "run-rtl-passes.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -1310,6 +1312,8 @@ 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, char *start_with_pass); + /* Parse a translation unit (C90 6.7, C99 6.9). translation-unit: @@ -1546,7 +1550,11 @@ static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); GIMPLE: gimple-function-definition: - declaration-specifiers[opt] __GIMPLE (gimple-pass-list) declarator + declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator + declaration-list[opt] compound-statement + + rtl-function-definition: + declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator declaration-list[opt] compound-statement */ static void @@ -2042,7 +2050,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 @@ -2074,12 +2082,28 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, function body as GIMPLE. */ if (specs->gimple_p) { - cfun->pass_startwith = specs->gimple_pass; + cfun->pass_startwith = specs->gimple_or_rtl_pass; bool saved = in_late_binary_op; in_late_binary_op = true; c_parser_parse_gimple_body (parser); in_late_binary_op = saved; } + /* Similarly, if it was marked with __RTL, use the RTL parser now, + consuming the function body. */ + else if (specs->rtl_p) + { + c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass); + + /* Normally, store_parm_decls sets next_is_function_body, + anticipating a function body. We need a push_scope/pop_scope + pair to flush out this state, or subsequent function parsing + will go wrong. */ + push_scope (); + pop_scope (); + + finish_function (); + return; + } else { fnbody = c_parser_compound_statement (parser); @@ -2110,7 +2134,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, if (specs->gimple_p) DECL_SAVED_TREE (fndecl) = NULL_TREE; - timevar_pop (tv); break; } } @@ -2602,7 +2625,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, c_parser_consume_token (parser); specs->gimple_p = true; specs->locations[cdw_gimple] = loc; - specs->gimple_pass = c_parser_gimple_pass_list (parser); + specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser); + break; + case RID_RTL: + c_parser_consume_token (parser); + specs->rtl_p = true; + specs->locations[cdw_rtl] = loc; + specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser); break; default: goto out; @@ -18258,4 +18287,74 @@ 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. + + Take ownership of START_WITH_PASS, if non-NULL. */ + +void +c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass) +{ + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + { + free (start_with_pass); + 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; + case CPP_EOF: + error_at (start_loc, "no closing brace"); + free (start_with_pass); + return; + 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)) + { + free (start_with_pass); + return; + } + + /* If a pass name was provided for START_WITH_PASS, run the backend + accordingly now, on the cfun created above, transferring + ownership of START_WITH_PASS. */ + if (start_with_pass) + run_rtl_passes (start_with_pass); +} + #include "gt-c-c-parser.h" diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index a8cf353..94821d8 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -268,6 +268,7 @@ enum c_declspec_word { cdw_alignas, cdw_address_space, cdw_gimple, + cdw_rtl, cdw_number_of_elements /* This one must always be the last enumerator. */ }; @@ -291,8 +292,8 @@ struct c_declspecs { NULL; attributes (possibly from multiple lists) will be passed separately. */ tree attrs; - /* The pass to start compiling a __GIMPLE function with. */ - char *gimple_pass; + /* The pass to start compiling a __GIMPLE or __RTL function with. */ + char *gimple_or_rtl_pass; /* The base-2 log of the greatest alignment required by an _Alignas specifier, in bytes, or -1 if no such specifiers with nonzero alignment. */ @@ -367,6 +368,8 @@ struct c_declspecs { BOOL_BITFIELD alignas_p : 1; /* Whether any __GIMPLE specifier was specified. */ BOOL_BITFIELD gimple_p : 1; + /* Whether any __RTL specifier was specified. */ + BOOL_BITFIELD rtl_p : 1; /* The address space that the declaration belongs to. */ addr_space_t address_space; }; diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index 9b6af13..f5b2c44 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -1000,18 +1000,18 @@ c_parser_gimple_label (c_parser *parser, gimple_seq *seq) return; } -/* Parse gimple pass list. +/* Parse gimple/RTL pass list. - gimple-pass-list: + gimple-or-rtl-pass-list: startwith("pass-name") */ char * -c_parser_gimple_pass_list (c_parser *parser) +c_parser_gimple_or_rtl_pass_list (c_parser *parser) { char *pass = NULL; - /* Accept __GIMPLE. */ + /* Accept __GIMPLE/__RTL. */ if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) return NULL; c_parser_consume_token (parser); diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h index f72b626..e3ab019 100644 --- a/gcc/c/gimple-parser.h +++ b/gcc/c/gimple-parser.h @@ -22,6 +22,6 @@ along with GCC; see the file COPYING3. If not see /* Gimple parsing functions. */ extern void c_parser_parse_gimple_body (c_parser *); -extern char *c_parser_gimple_pass_list (c_parser *); +extern char *c_parser_gimple_or_rtl_pass_list (c_parser *); #endif diff --git a/gcc/cfg.c b/gcc/cfg.c index 6604b02..1ca6592 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -1094,6 +1094,15 @@ free_original_copy_tables (void) original_copy_bb_pool = NULL; } +/* Return true iff we have had a call to initialize_original_copy_tables + without a corresponding call to free_original_copy_tables. */ + +bool +original_copy_tables_initialized_p (void) +{ + return original_copy_bb_pool != NULL; +} + /* Removes the value associated with OBJ from table TAB. */ static void diff --git a/gcc/cfg.h b/gcc/cfg.h index ad935e3..df1480f 100644 --- a/gcc/cfg.h +++ b/gcc/cfg.h @@ -110,6 +110,7 @@ extern void scale_bbs_frequencies_gcov_type (basic_block *, int, gcov_type, extern void initialize_original_copy_tables (void); extern void reset_original_copy_tables (void); extern void free_original_copy_tables (void); +extern bool original_copy_tables_initialized_p (void); extern void set_bb_original (basic_block, basic_block); extern basic_block get_bb_original (basic_block); extern void set_bb_copy (basic_block, basic_block); diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index d2719db..de53295 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -3647,7 +3647,8 @@ relink_block_chain (bool stay_in_cfglayout_mode) /* Maybe reset the original copy tables, they are not valid anymore when we renumber the basic blocks in compact_blocks. If we are are going out of cfglayout mode, don't re-allocate the tables. */ - free_original_copy_tables (); + if (original_copy_tables_initialized_p ()) + free_original_copy_tables (); if (stay_in_cfglayout_mode) initialize_original_copy_tables (); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index cc730d2..79e33da 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -328,6 +328,10 @@ public: configury. This function is used just during symbol creation. */ bool needed_p (void); + /* Return true if this symbol is a function from the C frontend specified + directly in RTL form (with "__RTL"). */ + bool native_rtl_p () const; + /* Return true when there are references to the node. */ bool referred_to_p (bool include_self = true); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index e315a77..aae7b2a 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -217,6 +217,19 @@ static void handle_alias_pairs (void); /* Used for vtable lookup in thunk adjusting. */ static GTY (()) tree vtable_entry_type; +/* Return true if this symbol is a function from the C frontend specified + directly in RTL form (with "__RTL"). */ + +bool +symtab_node::native_rtl_p () const +{ + if (TREE_CODE (decl) != FUNCTION_DECL) + return false; + if (!DECL_STRUCT_FUNCTION (decl)) + return false; + return DECL_STRUCT_FUNCTION (decl)->curr_properties & PROP_rtl; +} + /* Determine if symbol declaration is needed. That is, visible to something either outside this translation unit, something magic in the system configury */ @@ -225,8 +238,10 @@ symtab_node::needed_p (void) { /* Double check that no one output the function into assembly file early. */ - gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl) - || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); + if (!native_rtl_p ()) + gcc_checking_assert + (!DECL_ASSEMBLER_NAME_SET_P (decl) + || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); if (!definition) return false; @@ -435,6 +450,14 @@ cgraph_node::finalize_function (tree decl, bool no_collect) && !DECL_DISREGARD_INLINE_LIMITS (decl)) node->force_output = 1; + /* __RTL functions were already output as soon as they were parsed (due + to the large amount of global state in the backend). + Mark such functions as "force_output" to reflect the fact that they + will be in the asm file when considering the symbols they reference. + The attempt to output them later on will bail out immediately. */ + if (node->native_rtl_p ()) + node->force_output = 1; + /* When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions declared inline and nested functions. These were optimized out @@ -568,6 +591,12 @@ cgraph_node::add_new_function (tree fndecl, bool lowered) void cgraph_node::analyze (void) { + if (native_rtl_p ()) + { + analyzed = true; + return; + } + tree decl = this->decl; location_t saved_loc = input_location; input_location = DECL_SOURCE_LOCATION (decl); @@ -1226,7 +1255,8 @@ analyze_functions (bool first_time) gcc_assert (!cnode->definition || cnode->thunk.thunk_p || cnode->alias - || gimple_has_body_p (decl)); + || gimple_has_body_p (decl) + || cnode->native_rtl_p ()); gcc_assert (cnode->analyzed == cnode->definition); } node->aux = NULL; @@ -1965,6 +1995,11 @@ cgraph_node::expand (void) /* We ought to not compile any inline clones. */ gcc_assert (!global.inlined_to); + /* __RTL functions are compiled as soon as they are parsed, so don't + do it again. */ + if (native_rtl_p ()) + return; + announce_function (decl); process = 0; gcc_assert (lowered); diff --git a/gcc/final.c b/gcc/final.c index 5709d0e..c1afc57 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -4701,7 +4701,8 @@ rest_of_clean_state (void) free_bb_for_insn (); - delete_tree_ssa (cfun); + if (cfun->gimple_df) + delete_tree_ssa (cfun); /* We can reduce stack alignment on call site only when we are sure that the function body just produced will be actually used in the final diff --git a/gcc/function.h b/gcc/function.h index cabffb9..19c26c8 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -236,7 +236,7 @@ struct GTY(()) function { /* The loops in this function. */ struct loops *x_current_loops; - /* Filled by the GIMPLE FE, pass to start compilation with. */ + /* Filled by the GIMPLE and RTL FEs, pass to start compilation with. */ char *pass_startwith; /* The stack usage of this function. */ diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c index de5cce1..e60c607 100644 --- a/gcc/gimple-expr.c +++ b/gcc/gimple-expr.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "demangle.h" #include "hash-set.h" #include "rtl.h" +#include "tree-pass.h" /* ----- Type related ----- */ @@ -323,7 +324,7 @@ bool gimple_has_body_p (tree fndecl) { struct function *fn = DECL_STRUCT_FUNCTION (fndecl); - return (gimple_body (fndecl) || (fn && fn->cfg)); + return (gimple_body (fndecl) || (fn && fn->cfg && !(fn->curr_properties & PROP_rtl))); } /* Return a printable name for symbol DECL. */ diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h index 464e25f..7278d97 100644 --- a/gcc/pass_manager.h +++ b/gcc/pass_manager.h @@ -82,6 +82,12 @@ public: opt_pass *get_pass_by_name (const char *name); + opt_pass *get_rest_of_compilation () const + { + return pass_rest_of_compilation_1; + } + opt_pass *get_clean_slate () const { return pass_clean_state_1; } + public: /* The root of the compilation pass tree, once constructed. */ opt_pass *all_passes; diff --git a/gcc/passes.c b/gcc/passes.c index 51d0d84..5086868 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgrtl.h" #include "tree-ssa-live.h" /* For remove_unused_locals. */ #include "tree-cfgcleanup.h" +#include "insn-addr.h" /* for INSN_ADDRESSES_ALLOC. */ using namespace gcc; @@ -2273,6 +2274,106 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status) return gate_status; } +/* Determine if PASS_NAME matches CRITERION. + Not a pure predicate, since it can update CRITERION, to support + matching the Nth invocation of a pass. + Subroutine of should_skip_pass_p. */ + +static bool +determine_pass_name_match (const char *pass_name, char *criterion) +{ + size_t namelen = strlen (pass_name); + if (!strncmp (pass_name, criterion, namelen)) + { + /* The following supports starting with the Nth invocation + of a pass (where N does not necessarily is equal to the + dump file suffix). */ + if (criterion[namelen] == '\0' + || (criterion[namelen] == '1' + && criterion[namelen + 1] == '\0')) + return true; + else + { + if (criterion[namelen + 1] == '\0') + --criterion[namelen]; + return false; + } + } + else + return false; +} + +/* For skipping passes until "startwith" pass. + Return true iff PASS should be skipped. + Clear cfun->pass_startwith when encountering the "startwith" pass, + so that all subsequent passes are run. */ + +static bool +should_skip_pass_p (opt_pass *pass) +{ + if (!cfun) + return false; + if (!cfun->pass_startwith) + return false; + + /* We can't skip the lowering phase yet -- ideally we'd + drive that phase fully via properties. */ + if (pass->type == GIMPLE_PASS + && !(cfun->curr_properties & PROP_ssa)) + { + if (!quiet_flag) + fprintf (stderr, "running pass anyway: %s\n", pass->name); + return false; + } + + if (determine_pass_name_match (pass->name, cfun->pass_startwith)) + { + if (!quiet_flag) + fprintf (stderr, "found starting pass: %s\n", pass->name); + cfun->pass_startwith = NULL; + return false; + } + + /* Don't skip df init; later RTL passes need it. */ + if (strstr (pass->name, "dfinit") != NULL) + return false; + + if (!quiet_flag) + fprintf (stderr, "skipping pass: %s\n", pass->name); + return true; +} + +/* Skip the given pass, for handling passes before "startwith" + in __GIMPLE and__RTL-marked functions. + In theory, this ought to be a no-op, but some of the RTL passes + need additional processing here. */ + +static void +skip_pass (opt_pass *pass) +{ + /* Pass "reload" sets the global "reload_completed", and many + things depend on this (e.g. instructions in .md files). */ + if (strcmp (pass->name, "reload") == 0) + reload_completed = 1; + + /* The INSN_ADDRESSES vec is normally set up by + shorten_branches; set it up for the benefit of passes that + run after this. */ + if (strcmp (pass->name, "shorten") == 0) + INSN_ADDRESSES_ALLOC (get_max_uid ()); + + /* Update the cfg hooks as appropriate. */ + if (strcmp (pass->name, "into_cfglayout") == 0) + { + cfg_layout_rtl_register_cfg_hooks (); + cfun->curr_properties |= PROP_cfglayout; + } + if (strcmp (pass->name, "outof_cfglayout") == 0) + { + rtl_register_cfg_hooks (); + cfun->curr_properties &= ~PROP_cfglayout; + } +} /* Execute PASS. */ @@ -2313,33 +2414,10 @@ execute_one_pass (opt_pass *pass) return false; } - /* For skipping passes until startwith pass */ - if (cfun - && cfun->pass_startwith - /* But we can't skip the lowering phase yet -- ideally we'd - drive that phase fully via properties. */ - && (cfun->curr_properties & PROP_ssa)) + if (should_skip_pass_p (pass)) { - size_t namelen = strlen (pass->name); - if (! strncmp (pass->name, cfun->pass_startwith, namelen)) - { - /* The following supports starting with the Nth invocation - of a pass (where N does not necessarily is equal to the - dump file suffix). */ - if (cfun->pass_startwith[namelen] == '\0' - || (cfun->pass_startwith[namelen] == '1' - && cfun->pass_startwith[namelen + 1] == '\0')) - cfun->pass_startwith = NULL; - else - { - if (cfun->pass_startwith[namelen + 1] != '\0') - return true; - --cfun->pass_startwith[namelen]; - return true; - } - } - else - return true; + skip_pass (pass); + return true; } /* Pass execution event trigger: useful to identify passes being diff --git a/gcc/read-md.c b/gcc/read-md.c index a8462a6..25bc3c4 100644 --- a/gcc/read-md.c +++ b/gcc/read-md.c @@ -399,6 +399,16 @@ md_reader::read_char (void) else m_read_md_colno++; + /* If we're filtering lines, treat everything before the range of + interest as a space, and as EOF for everything after. */ + 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 @@ md_reader::md_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. */ md_reader_ptr = this; @@ -1284,6 +1296,27 @@ md_reader::read_md_files (int argc, const char **argv, return !have_error; } + +/* Read FILENAME, filtering to just the given lines. */ + +bool +md_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 md_reader */ /* A dummy implementation which skips unknown directives. */ diff --git a/gcc/read-md.h b/gcc/read-md.h index 06dc80e..674e1e4 100644 --- a/gcc/read-md.h +++ b/gcc/read-md.h @@ -98,6 +98,9 @@ class md_reader virtual ~md_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 md_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 07c0e7a..fb3059b 100644 --- a/gcc/read-rtl-function.c +++ b/gcc/read-rtl-function.c @@ -468,23 +468,38 @@ function_reader::create_function () /* We start in cfgrtl mode, rather than cfglayout mode. */ 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; + + /* Mark this function as being specified as __RTL. */ + cfun->curr_properties |= PROP_rtl; + + /* cc1 normally inits DECL_INITIAL (fndecl) to be error_mark_node. + Create a dummy block for it. */ + DECL_INITIAL (fndecl) = make_node (BLOCK); cfun->curr_properties = (PROP_cfg | PROP_rtl); @@ -1580,6 +1595,40 @@ 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; + } + + initialize_rtl (); + init_emit (); + init_varasm_status (); + + function_reader reader; + 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 b2a6e81..a69d3a2 100644 --- a/gcc/read-rtl-function.h +++ b/gcc/read-rtl-function.h @@ -23,4 +23,7 @@ along with GCC; see the file COPYING3. If not see extern bool read_rtl_function_body (int argc, const char **argv, bool (*parse_opt) (const char *)); +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/run-rtl-passes.c b/gcc/run-rtl-passes.c new file mode 100644 index 0000000..eefbad4 --- /dev/null +++ b/gcc/run-rtl-passes.c @@ -0,0 +1,88 @@ +/* run-rtl-passes.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 "bitmap.h" +#include "df.h" +#include "regs.h" +#include "insn-attr-common.h" /* for INSN_SCHEDULING. */ +#include "insn-attr.h" /* for init_sched_attrs. */ +#include "run-rtl-passes.h" + +/* Run the backend passes, starting at the given pass. + Take ownership of INITIAL_PASS_NAME. */ + +void +run_rtl_passes (char *initial_pass_name) +{ + cfun->pass_startwith = initial_pass_name; + max_regno = max_reg_num (); + + /* Pass "expand" normally sets this up. */ +#ifdef INSN_SCHEDULING + init_sched_attrs (); +#endif + + bitmap_obstack_initialize (NULL); + bitmap_obstack_initialize (®_obstack); + + opt_pass *rest_of_compilation + = g->get_passes ()->get_rest_of_compilation (); + gcc_assert (rest_of_compilation); + execute_pass_list (cfun, rest_of_compilation); + + opt_pass *clean_slate = g->get_passes ()->get_clean_slate (); + gcc_assert (clean_slate); + execute_pass_list (cfun, clean_slate); + + bitmap_obstack_release (®_obstack); + + cfun->curr_properties |= PROP_rtl; +} diff --git a/gcc/run-rtl-passes.h b/gcc/run-rtl-passes.h new file mode 100644 index 0000000..aa035c5 --- /dev/null +++ b/gcc/run-rtl-passes.h @@ -0,0 +1,25 @@ +/* run-rtl-passes.h - Run a subset of the RTL passes + 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_RTL_PASSES_H +#define GCC_RUN_RTL_PASSES_H + +extern void run_rtl_passes (char *initial_pass_name); + +#endif /* GCC_RUN_RTL_PASSES_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..bc39a70 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/asr_div1.c @@ -0,0 +1,41 @@ +/* { dg-do compile { target aarch64-*-* } } */ +/* { dg-options "-mtune=cortex-a53 -fdump-rtl-combine -O2" } */ + +/* Taken from + gcc/testsuite/gcc.dg/asr_div1.c -O2 -fdump-rtl-all -mtune=cortex-a53 + for aarch64, hand editing to the new format. */ + +int __RTL (startwith ("combine")) f1 (int n) +{ +(function "f1" + (param "n" + (DECL_RTL (reg/v:SI %1 [ n ])) + (DECL_RTL_INCOMING (reg:SI x0 [ n ])) + ) ;; param "n" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 8 (set (reg:DI %2) + (lshiftrt:DI (reg:DI %0) + (const_int 32))) + "../../src/gcc/testsuite/gcc.dg/asr_div1.c":14 + (expr_list:REG_DEAD (reg:DI %0))) + (cinsn 9 (set (reg:SI %1) + (ashiftrt:SI (subreg:SI (reg:DI %2) 0) + (const_int 3))) + "../../src/gcc/testsuite/gcc.dg/asr_div1.c":14 + (expr_list:REG_DEAD (reg:DI %2))) + + ;; Extra insn, to avoid all of the above from being deleted by DCE + (insn 10 (use (reg/i:SI %1))) + + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; 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: r\[0-9\]+:SI#0=r\[0-9\]+: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..91ae937 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/aarch64/pr71779.c @@ -0,0 +1,50 @@ +/* { 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" + hand-edited to the compact dump format. */ + +int __RTL (startwith ("cse1")) test (int n) +{ +(function "fragment" + (param "n" + (DECL_RTL (reg/v:SI %1 [ n ])) + (DECL_RTL_INCOMING (reg:SI x0 [ n ])) + ) ;; param "n" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + +;; MEM[(struct isl_obj *)&obj1] = &isl_obj_map_vtable; +(insn 1045 (set (reg:SI %480) + (high:SI (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ))) + y.c:12702) +(insn 1046 (set (reg/f:SI %479) + (lo_sum:SI (reg:SI %480) + (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ))) + y.c:12702 + (expr_list:REG_EQUAL (symbol_ref:SI ("isl_obj_map_vtable") + [flags 0xc0] + ))) +(insn 1047 (set (reg:DI %481) + (subreg:DI (reg/f:SI %479) 0)) y.c:12702) +(insn 1048 (set (zero_extract:DI (reg/v:DI %191 [ obj1D.17368 ]) + (const_int 32) + (const_int 0)) + (reg:DI %481)) y.c:12702) +;; Extra insn, to avoid all of the above from being deleted by DCE +(insn 1049 (set (mem:DI (reg:DI %191) [1 i+0 S4 A32]) + (const_int 1))) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; 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/truncated-rtl-file.c b/gcc/testsuite/gcc.dg/rtl/truncated-rtl-file.c new file mode 100644 index 0000000..4dd8214 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/truncated-rtl-file.c @@ -0,0 +1,2 @@ +void __RTL test (void) +{ /* { dg-error "no closing brace" } */ 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..8701c1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/dfinit.c @@ -0,0 +1,116 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-dfinit" } */ + +#include "test_1.h" + +/* Lightly-modified dump of test.c.261r.split1 for x86_64. */ + +int __RTL (startwith ("no-opt dfinit")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (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) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 29 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 5) + ) ;; block 3 + (cbarrier 30) + (block 4 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3) + (cnote 21 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 22 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ]))) + (cinsn 26 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (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 normally + 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..8db1161 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c @@ -0,0 +1,81 @@ +/* { 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 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 5 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (set (reg/v/f:DI %10 [ f ]) + (reg:DI di [ f ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":18) + (cinsn 3 (set (reg/v/f:DI %11 [ b ]) + (reg:DI si [ b ])) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":18) + (cnote 4 NOTE_INSN_FUNCTION_BEG) + (cinsn 7 (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) + (cinsn 8 (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) + (cinsn 9 (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) + (cinsn 10 (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) + (cinsn 11 (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) + (cinsn 12 (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) + (cinsn 13 (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) + (cinsn 14 (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) + (cinsn 15 (set (reg:DF %16) + (plus:DF (reg:DF %14) + (reg:DF %15))) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23) + (cinsn 16 (set (reg:DF xmm0) + (reg:DF %16)) "../../src/gcc/testsuite/gcc.dg/rtl/x86_64/different-structs.c":23) + (ccall_insn/j 17 (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))) + (expr_list:DF (use (reg:DF xmm0)))) + (edge-to exit (flags "ABNORMAL | SIBCALL")) + ) ;; block 2 + (cbarrier 18) + ) ;; 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..1b8ea09 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/final.c @@ -0,0 +1,133 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-final" } */ + +/* Lightly-modified dump of test.c.304r.dwarf2 for x86_64 target, + with various NOTE_INSN_CFI deleted by hand for now. */ + +int __RTL (startwith ("final")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn/f 32 (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) + (cinsn/f 33 (set (reg/f:DI bp) + (reg/f:DI sp)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2) + (cinsn 34 (set (mem/v:BLK (0|scratch:DI) [0 A8]) + (unspec:BLK [ + (mem/v:BLK (reuse_rtx 0) [0 A8]) + ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2) + (cnote 35 NOTE_INSN_PROLOGUE_END) + (cinsn 2 (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) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 29 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 5) + ) ;; block 3 + (cbarrier 30) + (block 4 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3) + (cnote 21 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cnote 36 NOTE_INSN_EPILOGUE_BEG) + (cinsn 37 (set (mem/v:BLK (1|scratch:DI) [0 A8]) + (unspec:BLK [ + (mem/v:BLK (reuse_rtx 1) [0 A8]) + ] UNSPEC_MEMORY_BLOCKAGE)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn/f 38 (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)))) + (cjump_insn 39 (simple_return) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (edge-to exit) + ) ;; block 5 + (cbarrier 40) + (cnote 31 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..ab92004 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/into-cfglayout.c @@ -0,0 +1,117 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-into_cfglayout" } */ + +/* Lightly-modified dump of test.c.226r.vregs for x86_64. */ + +#include "test_1.h" + +int __RTL (startwith ("into_cfglayout")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (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) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 14 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 6) + ) ;; block 4 + (cbarrier 15) + (block 5 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3) + (cnote 21 [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn 22 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ]))) + (cinsn 26 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (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" "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..d23cca4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/ira.c @@ -0,0 +1,111 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-ira" } */ + +/* Lightly-modified dump of test.c.265r.asmcons for x86_64. */ + +#include "test_1.h" + +int __RTL (startwith ("ira")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (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) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 29 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 5) + ) ;; block 3 + (cbarrier 30) + (block 4 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3) + (cnote 21 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 22 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ]))) + (cinsn 26 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (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..4ba3d6e --- /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.274r.split2 for x86_64. */ + +int __RTL (startwith ("pro_and_epilogue")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (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) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 3 (flags "FALLTHRU")) + (edge-to 4) + ) ;; block 2 + (block 3 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 3] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 29 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 5) + ) ;; block 3 + (cbarrier 30) + (block 4 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 5 (flags "FALLTHRU")) + ) ;; block 4 + (block 5 + (edge-from 4 (flags "FALLTHRU")) + (edge-from 3) + (clabel 20 3) + (cnote 21 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 5 + (cnote 31 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-multiple-fns.c b/gcc/testsuite/gcc.dg/rtl/x86_64/test-multiple-fns.c new file mode 100644 index 0000000..ac0ebe4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-multiple-fns.c @@ -0,0 +1,105 @@ +/* { dg-do run { target x86_64-*-* } } */ + +/* Verify that we can have multiple __RTL functions in one test case. + Each of these __RTL functions returns a const, dumped immediately after + expand. */ + +extern void abort (void); + +int __RTL (startwith ("vregs")) test_return_42 (void) +{ + /* C code: + return 42; */ +(function "test_return_42" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 5 (set (reg:SI %0 [ _1 ]) + (const_int 42)) "../../src/test-return-const.c":3) + (cinsn 8 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) "../../src/test-return-const.c":3) + (cinsn 12 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/test-return-const.c":4) + (cinsn 13 (use (reg/i:SI ax)) "../../src/test-return-const.c":4) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_return_42" +} + +int __RTL (startwith ("vregs")) test_return_43 (void) +{ + /* C code: + return 43; */ +(function "test_return_43" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 5 (set (reg:SI %0 [ _1 ]) + (const_int 43)) "../../src/test-return-const.c":3) + (cinsn 8 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) "../../src/test-return-const.c":3) + (cinsn 12 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/test-return-const.c":4) + (cinsn 13 (use (reg/i:SI ax)) "../../src/test-return-const.c":4) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_return_43" +} + +int __RTL (startwith ("vregs")) test_return_44 (void) +{ + /* C code: + return 44; */ +(function "test_return_44" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 5 (set (reg:SI %0 [ _1 ]) + (const_int 44)) "../../src/test-return-const.c":3) + (cinsn 8 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) "../../src/test-return-const.c":3) + (cinsn 12 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/test-return-const.c":4) + (cinsn 13 (use (reg/i:SI ax)) "../../src/test-return-const.c":4) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_return_44" +} + +int main (void) +{ + if (test_return_42 () != 42) + abort (); + if (test_return_43 () != 43) + abort (); + if (test_return_44 () != 44) + abort (); + return 0; +} 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..8753809 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.after-expand.c @@ -0,0 +1,39 @@ +/* { dg-do run { target x86_64-*-* } } */ + +extern void abort (void); + +int __RTL (startwith ("vregs")) test_returning_constant (void) +{ + /* C code: + return 42; */ +(function "test_returning_constant" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 5 (set (reg:SI %0 [ _1 ]) + (const_int 42)) "../../src/test-return-const.c":3) + (cinsn 8 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ])) "../../src/test-return-const.c":3) + (cinsn 12 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/test-return-const.c":4) + (cinsn 13 (use (reg/i:SI ax)) "../../src/test-return-const.c":4) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_returning_constant" +} + +int main (void) +{ + if (test_returning_constant () != 42) + abort (); + return 0; +} 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..603caa3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c @@ -0,0 +1,42 @@ +/* { dg-do run { target x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-fwprop1 -O2" } */ + +extern void abort (void); + +int __RTL (startwith ("fwprop1")) test_returning_constant (void) +{ + /* C code: + return 42; */ +(function "test_returning_constant" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 3 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 5 (set (reg:SI %0 [ ]) + (const_int 42)) "../../src/test-return-const.c":3) + (cinsn 9 (set (reg/i:SI ax) + (const_int 42)) "../../src/test-return-const.c":4 + (expr_list:REG_DEAD (reg:SI %0 [ ]))) + (cinsn 10 (use (reg/i:SI ax)) "../../src/test-return-const.c":4) + (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 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" } } */ + +int main (void) +{ + if (test_returning_constant () != 42) + abort (); + return 0; +} 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..b4d1e6d --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test-rtl.c @@ -0,0 +1,101 @@ +/* { 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 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 14 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 6) + ) ;; block 4 + (cbarrier 15) + (block 5 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3) + (cnote 21 [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn 22 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ]))) + (cinsn 26 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (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/test_1.h b/gcc/testsuite/gcc.dg/rtl/x86_64/test_1.h new file mode 100644 index 0000000..a783ea8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/test_1.h @@ -0,0 +1,16 @@ +/* Shared test code for the various __RTL tests of test_1 that + start at different passes. */ + +extern void abort (void); +extern int test_1 (int i, int j, int k); + +int main (void) +{ + if (test_1 (0, 0, 3) != -3) + abort (); + + if (test_1 (0, 1, 3) != 7) + abort (); + + return 0; +} 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..f6eb1c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.after-expand.c @@ -0,0 +1,70 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ + +extern void abort (void); + +int __RTL (startwith ("vregs")) times_two (int i) +{ + /* C function: + return i * 2; */ +(function "times_two" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ])) + ) ;; param "i" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/times-two.c":2 + (nil)) + (cnote 3 NOTE_INSN_FUNCTION_BEG) + (cinsn 6 (set (reg:SI %2) + (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32])) "../../src/times-two.c":3 + (nil)) + (cinsn 7 (parallel [ + (set (reg:SI %0 [ _2 ]) + (ashift:SI (reg:SI %2) + (const_int 1))) + (clobber (reg:CC flags)) + ]) "../../src/times-two.c":3 + (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32]) + (const_int 1)) + (nil))) + (cinsn 10 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _2 ])) "../../src/times-two.c":3 + (nil)) + (cinsn 14 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/times-two.c":4 + (nil)) + (cinsn 15 (use (reg/i:SI ax)) "../../src/times-two.c":4 + (nil)) + (edge-to exit (flags "FALLTHRU")) + ) ;; block 2 + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:SI ax) + ) ;; return_rtx + ) ;; crtl +) ;; function "times_two" +} + +int main (void) +{ + if (times_two (0) != 0) + abort (); + + if (times_two (1) != 2) + abort (); + + if (times_two (100) != 200) + abort (); + + return 0; +} 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..1321eaf --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/times-two.c.before-df.c @@ -0,0 +1,54 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-dfinit" } */ + +int __RTL (startwith ("rtl-dfinit")) times_two (int i) +{ + /* C function: + return i * 2; */ +(function "times_two" + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 4 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/times-two.c":2) + (cnote 3 NOTE_INSN_FUNCTION_BEG) + (cinsn 6 (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) + (cinsn 7 (parallel [ + (set (reg:SI %0 [ _2 ]) + (ashift:SI (reg:SI %2) + (const_int 1))) + (clobber (reg:CC flags)) + ]) "../../src/times-two.c":3 + (expr_list:REG_EQUAL (ashift:SI (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32]) + (const_int 1)))) + (cinsn 10 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _2 ])) "../../src/times-two.c":3) + (cinsn 14 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/times-two.c":4) + (cinsn 15 (use (reg/i:SI ax)) "../../src/times-two.c":4) + (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..50d90dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/x86_64/vregs.c @@ -0,0 +1,112 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-vregs" } */ + +/* Lightly-modified dump of test.c.225r.expand for x86_64. */ + +#include "test_1.h" + +int __RTL (startwith ("vregs")) test_1 (int i, int j, int k) +{ +(function "test_1" + (param "i" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -4)) [1 i+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI di [ i ]))) + (param "j" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -8)) [1 j+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI si [ j ]))) + (param "k" + (DECL_RTL (mem/c:SI (plus:DI (reg/f:DI frame) + (const_int -12)) [1 k+0 S4 A32])) + (DECL_RTL_INCOMING (reg:SI dx [ k ]))) + (insn-chain + (cnote 1 NOTE_INSN_DELETED) + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 6 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cinsn 2 (set (mem/c:SI (plus:DI (reg/f:DI virtual-stack-vars) + (const_int -4)) [1 i+0 S4 A32]) + (reg:SI di [ i ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":2) + (cinsn 3 (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) + (cinsn 4 (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) + (cnote 5 NOTE_INSN_FUNCTION_BEG) + (cinsn 8 (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) + (cinsn 9 (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) + (cjump_insn 10 (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) + (edge-to 4 (flags "FALLTHRU")) + (edge-to 5) + ) ;; block 2 + (block 4 + (edge-from 2 (flags "FALLTHRU")) + (cnote 11 [bb 4] NOTE_INSN_BASIC_BLOCK) + (cinsn 12 (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) + (cinsn 13 (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)))) + (cjump_insn 14 (set (pc) + (label_ref 20)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":4) + (edge-to 6) + ) ;; block 4 + (cbarrier 15) + (block 5 + (edge-from 2) + (clabel 16 2) + (cnote 17 [bb 5] NOTE_INSN_BASIC_BLOCK) + (cinsn 18 (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) + (cinsn 19 (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])))) + (edge-to 6 (flags "FALLTHRU")) + ) ;; block 5 + (block 6 + (edge-from 4) + (edge-from 5 (flags "FALLTHRU")) + (clabel 20 3) + (cnote 21 [bb 6] NOTE_INSN_BASIC_BLOCK) + (cinsn 22 (set (reg:SI %1 [ ]) + (reg:SI %0 [ _1 ]))) + (cinsn 26 (set (reg/i:SI ax) + (reg:SI %1 [ ])) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (cinsn 27 (use (reg/i:SI ax)) "../../src/gcc/testsuite/gcc.dg/rtl/test.c":7) + (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" } } */ -- 1.8.5.3