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