The following patch removes the partial support present for "pass list", thereby simplifying the middle-end changes, isolating them to execute_one_pass plus a field in struct function (plus the SSA name allocation support).
Tested on x86_64-unknown-linux-gnu, a bootstrap is in progress. Will push to GIT soon. What is left is to add a dump modifier (thinking of -gimple) to guard the dump changes that otherwise will break a lot of testsuite scans. Another option would be to drop them for now (and require unit tests to be manually converted from "dumpfile GIMPLE" to "FE GIMPLE"). Thanks, Richard. 2016-10-26 Richard Biener <rguent...@suse.de> c/ * c-parser.c (c_parser_declaration_or_fndef): Adjust for GIMPLE FE start-with change. * gimple-parser.c (c_parser_gimple_pass_list_params): Remove. (c_parser_gimple_pass_list): Parse only startwith. * function.h (pass_startwith): Change to char *. (startwith): Remove redundant flag. * coretypes.h: Revert all branch changes. * cgraphunit.c: Likewise. * tree-pass.h: Likewise. * passes.c: Likewise. (execute_one_pass): Handle startwith solely here. * tree-ssanames.c (make_ssa_name_fn): Document extended interface. testsuite/ * gcc.dg/gimplefe-12.c: Adjust startwith pass. * gcc.dg/gimplefe-13.c: Likewise. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 9b51c48..542b83b 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1487,8 +1487,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool diagnosed_no_specs = false; location_t here = c_parser_peek_token (parser)->location; bool gimple_body_p = false; - opt_pass *pass = NULL; - bool startwith_p = false; + char *pass = NULL; if (static_assert_ok && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) @@ -1581,7 +1580,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, { gimple_body_p = true; c_parser_consume_token (parser); - c_parser_gimple_pass_list (parser, &pass, &startwith_p); + c_parser_gimple_pass_list (parser, &pass); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } @@ -2001,12 +2000,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, true, false, NULL, vNULL); store_parm_decls (); - if (pass) - { - cfun->pass_startwith = pass; - cfun->startwith = startwith_p; - } - if (omp_declare_simd_clauses.exists () || !vec_safe_is_empty (parser->cilk_simd_fn_tokens)) c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, @@ -2018,6 +2011,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, if (gimple_body_p && flag_gimple) { + cfun->pass_startwith = pass; bool saved = in_late_binary_op; in_late_binary_op = true; c_parser_parse_gimple_body (parser); diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c index 30e8d88..c19f417 100644 --- a/gcc/c/gimple-parser.c +++ b/gcc/c/gimple-parser.c @@ -66,7 +66,6 @@ static struct c_expr c_parser_gimple_postfix_expression (c_parser *); static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *, location_t, struct c_expr); -static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **); static void c_parser_gimple_declaration (c_parser *); static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *); static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *); @@ -112,7 +111,12 @@ c_parser_parse_gimple_body (c_parser *parser) gimple_bind_set_body (bind_stmt, seq); gimple_seq_add_stmt (&body, bind_stmt); gimple_set_body (current_function_decl, body); - cfun->curr_properties = PROP_gimple_any; + + /* While we have SSA names in the IL we do not have a CFG built yet + and PHIs are represented using a PHI internal function. We do + have lowered control flow and exception handling (well, we do not + have parser support for EH yet). */ + cfun->curr_properties = PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh; return; } @@ -931,8 +935,7 @@ c_parser_gimple_label (c_parser *parser, gimple_seq *seq) */ void -c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, - bool *startwith_p) +c_parser_gimple_pass_list (c_parser *parser, char **pass) { if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return; @@ -946,11 +949,17 @@ c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, c_parser_consume_token (parser); if (! strcmp (op, "startwith")) { - *pass = c_parser_gimple_pass_list_params (parser, pass); - if (! *pass) + if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return; - - *startwith_p = true; + if (c_parser_next_token_is_not (parser, CPP_STRING)) + { + error_at (c_parser_peek_token (parser)->location, + "expected pass name"); + return; + } + *pass = xstrdup (TREE_STRING_POINTER + (c_parser_peek_token (parser)->value)); + c_parser_consume_token (parser); if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) return; } @@ -970,66 +979,6 @@ c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, return; } -/* Support function for c_parser_gimple_pass_list. */ - -static opt_pass * -c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass) -{ - opt_pass *pass_start = NULL, *new_pass; - if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return NULL; - - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - return NULL; - - while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - { - if (c_parser_next_token_is (parser, CPP_EOF)) - { - error_at (c_parser_peek_token (parser)->location, - "expected pass names"); - return NULL; - } - - if (c_parser_next_token_is (parser, CPP_STRING)) - { - const char *name = NULL; - name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - new_pass = g->get_passes ()->get_pass_by_name (name); - - if (! new_pass) - { - error_at (c_parser_peek_token (parser)->location, - "invalid pass name"); - parser->error = true; - c_parser_consume_token (parser); - return NULL; - } - if (*pass) - { - (*pass)->next = new_pass; - (*pass) = (*pass)->next; - } - else - { - *pass = new_pass; - pass_start = *pass; - } - } - else if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - { - error_at (c_parser_peek_token (parser)->location, - "invalid pass name"); - c_parser_consume_token (parser); - return NULL; - } - } - return pass_start; -} - /* Parse gimple local declaration. declaration-specifiers: diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h index d88d9e5..860695b 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 void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *); +extern void c_parser_gimple_pass_list (c_parser *, char **); #endif diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 8c447f7..b1812b2 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1960,7 +1960,6 @@ cgraph_node::assemble_thunks_and_aliases (void) void cgraph_node::expand (void) { - bool startwith_p = true; location_t saved_loc; /* We ought to not compile any inline clones. */ @@ -1999,7 +1998,7 @@ cgraph_node::expand (void) /* Signal the start of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); - execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p); + execute_pass_list (cfun, g->get_passes ()->all_passes); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); @@ -2052,8 +2051,7 @@ cgraph_node::expand (void) timevar_pop (TV_REST_OF_COMPILATION); /* Make sure that BE didn't give up on compiling. */ - if (!(flag_gimple && cfun->pass_startwith)) /* FIXME : for gimplefe custom_pass_list */ - gcc_assert (TREE_ASM_WRITTEN (decl)); + gcc_assert (TREE_ASM_WRITTEN (decl)); if (cfun) pop_cfun (); diff --git a/gcc/coretypes.h b/gcc/coretypes.h index c0f22c9..869f858 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -85,7 +85,6 @@ typedef const union tree_node *const_tree; struct gimple; typedef gimple *gimple_seq; struct gimple_stmt_iterator; -class opt_pass; /* Forward decls for leaf gimple subclasses (for individual gimple codes). Keep this in the same order as the corresponding codes in gimple.def. */ @@ -353,8 +352,6 @@ typedef unsigned char uchar; #include "input.h" #include "is-a.h" #include "memory-block.h" -#include "pass_manager.h" -#include "tree-pass.h" #endif /* GENERATOR_FILE && !USED_FOR_TARGET */ #endif /* coretypes.h */ diff --git a/gcc/function.h b/gcc/function.h index 7775c08..600c6a0 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -228,18 +228,15 @@ struct GTY(()) function { /* GIMPLE body for this function. */ gimple_seq gimple_body; - /* GIMPLEFE pass to start with */ - opt_pass *pass_startwith; - - /* Startwith flag */ - bool startwith; - /* SSA and dataflow information. */ struct gimple_df *gimple_df; /* The loops in this function. */ struct loops *x_current_loops; + /* Filled by the GIMPLE FE, pass to start compilation with. */ + char *pass_startwith; + /* The stack usage of this function. */ struct stack_usage *su; diff --git a/gcc/passes.c b/gcc/passes.c index ec1902a..61eea90 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1686,13 +1686,12 @@ remove_cgraph_node_from_order (cgraph_node *node, void *data) call CALLBACK on the current function. This function is global so that plugins can use it. */ void -do_per_function_toporder (void (*callback) (function *, void *data, void *flag), - void *data, void *flag) +do_per_function_toporder (void (*callback) (function *, void *data), void *data) { int i; if (current_function_decl) - callback (cfun, data, flag); + callback (cfun, data); else { cgraph_node_hook_list *hook; @@ -1727,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data, void *flag), { struct function *fn = DECL_STRUCT_FUNCTION (node->decl); push_cfun (fn); - callback (fn, data, flag); + callback (fn, data); pop_cfun (); } } @@ -2278,18 +2277,8 @@ override_gate_status (opt_pass *pass, tree func, bool gate_status) /* Execute PASS. */ bool -execute_one_pass (opt_pass *pass, bool startwith_p) +execute_one_pass (opt_pass *pass) { - /* For skipping passes until startwith pass */ - if (cfun && startwith_p && cfun->startwith) - { - if (!strcmp (pass->name, cfun->pass_startwith->name) - || !strcmp (pass->name, "*clean_state")) - cfun->startwith = false; - else - return true; - } - unsigned int todo_after = 0; bool gate_status; @@ -2324,6 +2313,35 @@ execute_one_pass (opt_pass *pass, bool startwith_p) 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)) + { + 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; + } + /* Pass execution event trigger: useful to identify passes being executed. */ invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass); @@ -2429,7 +2447,7 @@ execute_one_pass (opt_pass *pass, bool startwith_p) } static void -execute_pass_list_1 (opt_pass *pass, bool startwith_p) +execute_pass_list_1 (opt_pass *pass) { do { @@ -2438,23 +2456,18 @@ execute_pass_list_1 (opt_pass *pass, bool startwith_p) if (cfun == NULL) return; - if (execute_one_pass (pass, startwith_p) && pass->sub) - execute_pass_list_1 (pass->sub, startwith_p); + if (execute_one_pass (pass) && pass->sub) + execute_pass_list_1 (pass->sub); pass = pass->next; } while (pass); } void -execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p) +execute_pass_list (function *fn, opt_pass *pass) { gcc_assert (fn == cfun); - - if (startwith_p) - execute_pass_list_1 (pass, *startwith_p); - else - execute_pass_list_1 (pass, false); - + execute_pass_list_1 (pass); if (cfun && fn->cfg) { free_dominance_info (CDI_DOMINATORS); @@ -2784,22 +2797,19 @@ ipa_read_optimization_summaries (void) void execute_ipa_pass_list (opt_pass *pass) { - bool startwith_p = false; do { gcc_assert (!current_function_decl); gcc_assert (!cfun); gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); - if (!strcmp (pass->name, "opt_local_passes")) - startwith_p = true; - if (execute_one_pass (pass, startwith_p) && pass->sub) + if (execute_one_pass (pass) && pass->sub) { if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); - do_per_function_toporder ((void (*)(function *, void *, void *)) + do_per_function_toporder ((void (*)(function *, void *)) execute_pass_list, - pass->sub, &startwith_p); + pass->sub); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } else if (pass->sub->type == SIMPLE_IPA_PASS diff --git a/gcc/testsuite/gcc.dg/gimplefe-12.c b/gcc/testsuite/gcc.dg/gimplefe-12.c index cbaf8a6..2863228 100644 --- a/gcc/testsuite/gcc.dg/gimplefe-12.c +++ b/gcc/testsuite/gcc.dg/gimplefe-12.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ -/* { dg-options "-fgimple" } */ +/* { dg-options "-O -fgimple" } */ -void __GIMPLE (startwith ("tree-ccp1")) foo () +void __GIMPLE (startwith ("ccp1")) foo () { int a; int b; diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c b/gcc/testsuite/gcc.dg/gimplefe-13.c index c0da9fa..f0af761 100644 --- a/gcc/testsuite/gcc.dg/gimplefe-13.c +++ b/gcc/testsuite/gcc.dg/gimplefe-13.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ -/* { dg-options "-fgimple" } */ +/* { dg-options "-O -fgimple" } */ -void __GIMPLE (startwith ("tree-dse1")) foo () +void __GIMPLE (startwith ("dse2")) foo () { int a; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 93124b1..fce9839 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -622,9 +622,8 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt); /* Current optimization pass. */ extern opt_pass *current_pass; -extern bool execute_one_pass (opt_pass *, bool startwith_p = false); -extern void execute_pass_list (function *, opt_pass *, - bool *startwith_p = NULL); +extern bool execute_one_pass (opt_pass *); +extern void execute_pass_list (function *, opt_pass *); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); extern void execute_all_ipa_transforms (void); diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 51ec80a..bd5d10a 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -252,7 +252,8 @@ flush_ssaname_freelist (void) /* Return an SSA_NAME node for variable VAR defined in statement STMT in function FN. STMT may be an empty statement for artificial references (e.g., default definitions created when a variable is - used without a preceding definition). */ + used without a preceding definition). If VERISON is not zero then + allocate the SSA name with that version. */ tree make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, @@ -266,7 +267,7 @@ make_ssa_name_fn (struct function *fn, tree var, gimple *stmt, || TREE_CODE (var) == RESULT_DECL || (TYPE_P (var) && is_gimple_reg_type (var))); - /* parsing ssa names with versions. */ + /* Get the specified SSA name version. */ if (version != 0) { t = make_node (SSA_NAME);