On 8 July 2016 at 13:13, Richard Biener <richard.guent...@gmail.com> wrote: > On Thu, Jul 7, 2016 at 9:45 PM, Prasad Ghangal <prasad.ghan...@gmail.com> > wrote: >> On 6 July 2016 at 14:24, Richard Biener <richard.guent...@gmail.com> wrote: >>> On Wed, Jul 6, 2016 at 9:51 AM, Prasad Ghangal <prasad.ghan...@gmail.com> >>> wrote: >>>> On 30 June 2016 at 17:10, Richard Biener <richard.guent...@gmail.com> >>>> wrote: >>>>> On Wed, Jun 29, 2016 at 9:13 PM, Prasad Ghangal >>>>> <prasad.ghan...@gmail.com> wrote: >>>>>> On 29 June 2016 at 22:15, Richard Biener <richard.guent...@gmail.com> >>>>>> wrote: >>>>>>> On June 29, 2016 6:20:29 PM GMT+02:00, Prathamesh Kulkarni >>>>>>> <prathamesh.kulka...@linaro.org> wrote: >>>>>>>>On 18 June 2016 at 12:02, Prasad Ghangal <prasad.ghan...@gmail.com> >>>>>>>>wrote: >>>>>>>>> Hi, >>>>>>>>> >>>>>>>>> I tried hacking pass manager to execute only given passes. For this I >>>>>>>>> am adding new member as opt_pass *custom_pass_list to the function >>>>>>>>> structure to store passes need to execute and providing the >>>>>>>>> custom_pass_list to execute_pass_list() function instead of all >>>>>>>>passes >>>>>>>>> >>>>>>>>> for test case like- >>>>>>>>> >>>>>>>>> int a; >>>>>>>>> void __GIMPLE (execute ("tree-ccp1", "tree-fre1")) foo() >>>>>>>>> { >>>>>>>>> bb_1: >>>>>>>>> a = 1 + a; >>>>>>>>> } >>>>>>>>> >>>>>>>>> it will execute only given passes i.e. ccp1 and fre1 pass on the >>>>>>>>function >>>>>>>>> >>>>>>>>> and for test case like - >>>>>>>>> >>>>>>>>> int a; >>>>>>>>> void __GIMPLE (startwith ("tree-ccp1")) foo() >>>>>>>>> { >>>>>>>>> bb_1: >>>>>>>>> a = 1 + a; >>>>>>>>> } >>>>>>>>> >>>>>>>>> it will act as a entry point to the pipeline and will execute passes >>>>>>>>> starting from given pass. >>>>>>>>Bike-shedding: >>>>>>>>Would it make sense to have syntax for defining pass ranges to execute >>>>>>>>? >>>>>>>>for instance: >>>>>>>>void __GIMPLE(execute (pass_start : pass_end)) >>>>>>>>which would execute all the passes within range [pass_start, pass_end], >>>>>>>>which would be convenient if the range is large. >>>>>>> >>>>>>> But it would rely on a particular pass pipeline, f.e. pass-start >>>>>>> appearing before pass-end. >>>>>>> >>>>>>> Currently control doesn't work 100% as it only replaces >>>>>>> all_optimizations but not lowering passes or early opts, nor IPA opts. >>>>>>> >>>>>> >>>>>> Each pass needs GIMPLE in some specific form. So I am letting lowering >>>>>> and early opt passes to execute. I think we have to execute some >>>>>> passes (like cfg) anyway to represent GIMPLE into proper form >>>>> >>>>> Yes, that's true. Note that early opt passes only optimize but we need >>>>> pass_build_ssa_passes at least (for into-SSA). For proper unit-testing >>>>> of GIMPLE passes we do need to guard off early opts somehow >>>>> (I guess a simple if (flag_gimple && cfun->custom_pass_list) would do >>>>> that). >>>>> >>>>> Then there is of course the question about IPA passes which I think is >>>>> somewhat harder (one could always disable all IPA passes manually >>>>> via flags of course or finally have a global -fipa/no-ipa like most >>>>> other compilers). >>>>> >>>> Can we iterate through all ipa passes and do -fdisable-ipa-pass or >>>> -fenable-ipa-pass equivalent for each? >>> >>> We could do that, yes. But let's postpone this issue. I think that >>> startwith is going to be most useful and rather than constructing >>> a pass list for it "native" support for it in the pass manager is >>> likely to produce better results (add a 'startwith' member alongside >>> the pass list member and if it is set the pass manager skips all >>> passes that do not match 'startwith' and once it reaches it it clears >>> the field). >>> >>> In the future I hope we can get away from a static pass list and more >>> towards rule-driven pass execution (we have all those PROP_* stuff >>> already but it isn't really used for example). But well, that would be >>> a separate GSoC project ;) >>> >>> IMHO startwith will provide everything needed for unit-testing. We can >>> add a flag on whether further passes should be executed or not and >>> even a pass list like execute ("ccp1", "fre") can be implemented by >>> startwith ccp1 and then from there executing the rest of the passes in the >>> list and stopping at the end. >>> >>> As said, unit-testing should exercise a single pass if we can control >>> its input. >>> >> In this patch I am skipping execution of passes until pass_startwith >> is found. Unlike previous build, now pass manager executes all passes >> in pipeline starting from pass_startwith instead of just sub passes. > > That looks good. I wonder if > > + if (startwith_p && cfun->startwith) > + { > + if (pass->name == cfun->pass_startwith->name > + || pass->name == "*clean_state") > > need better be strcmp ()s though. Also the early optimization pipeline > should be executed with startwith support as well. >
This patch adds startwith support for early opt passes. But for starting from some passes (like asan0, optimized) in all_passes pipeline, it falils at verify_curr_properties in execute_one_pass (). I wonder if we need to update properties after skipping each pass Thanks, Prasad > Richard. > >>> Thanks, >>> Richard. >>> >>>> Thanks, >>>> Prasad >>>> >>>>> Richard. >>>>> >>>>>>> Richard. >>>>>>> >>>>>>>>Thanks, >>>>>>>>Prathamesh >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Prasad Ghangal >>>>>>> >>>>>>>
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index d7ffdce..1a55b9a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -18821,7 +18821,8 @@ c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, bool *startwith_p) if (!strcmp (op, "startwith")) { *pass = c_parser_gimple_pass_list_params (parser, pass); - (*pass)->next = NULL; + if (!(*pass)) + return; *startwith_p = true; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) return; @@ -18874,6 +18875,7 @@ c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass) if (!new_pass) { error_at (c_parser_peek_token (parser)->location, "invalid pass name"); + parser->error = true; c_parser_consume_token (parser); return NULL; } diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2bb112e..1df4950 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1942,6 +1942,7 @@ 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. */ @@ -1980,7 +1981,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, true); + execute_pass_list (cfun, g->get_passes ()->all_passes, &startwith_p); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); diff --git a/gcc/passes.c b/gcc/passes.c index c4588bb..c7c7191 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -114,8 +114,7 @@ pass_manager::execute_early_local_passes () execute_pass_list (cfun, pass_build_ssa_passes_1->sub); if (flag_check_pointer_bounds) execute_pass_list (cfun, pass_chkp_instrumentation_passes_1->sub); - if (!flag_gimple && !cfun->pass_startwith) - execute_pass_list (cfun, pass_local_optimization_passes_1->sub); + execute_pass_list (cfun, pass_local_optimization_passes_1->sub); } unsigned int @@ -1686,12 +1685,13 @@ 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 *data) +do_per_function_toporder (void (*callback) (function *, void *data, void *flag), + void *data, void *flag) { int i; if (current_function_decl) - callback (cfun, data); + callback (cfun, data, flag); else { cgraph_node_hook_list *hook; @@ -1726,7 +1726,7 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data) { struct function *fn = DECL_STRUCT_FUNCTION (node->decl); push_cfun (fn); - callback (fn, data); + callback (fn, data, flag); pop_cfun (); } } @@ -2284,10 +2284,10 @@ bool execute_one_pass (opt_pass *pass, bool startwith_p) { /* For skipping passes until startwith pass */ - if (startwith_p && cfun->startwith) + if (cfun && startwith_p && cfun->startwith) { - if (pass->name == cfun->pass_startwith->name - || pass->name == "*clean_state") + if (!strcmp (pass->name, cfun->pass_startwith->name) + || !strcmp (pass->name, "*clean_state")) cfun->startwith = false; else return true; @@ -2446,10 +2446,15 @@ execute_pass_list_1 (opt_pass *pass, bool startwith_p) } void -execute_pass_list (function *fn, opt_pass *pass, bool startwith_p) +execute_pass_list (function *fn, opt_pass *pass, bool *startwith_p) { gcc_assert (fn == cfun); - execute_pass_list_1 (pass, startwith_p); + + if (startwith_p) + execute_pass_list_1 (pass, *startwith_p); + else + execute_pass_list_1 (pass, false); + if (cfun && fn->cfg) { free_dominance_info (CDI_DOMINATORS); @@ -2779,19 +2784,22 @@ 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 (execute_one_pass (pass) && pass->sub) + if (!strcmp (pass->name, "opt_local_passes")) + startwith_p = true; + if (execute_one_pass (pass, startwith_p) && pass->sub) { if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); - do_per_function_toporder ((void (*)(function *, void *)) + do_per_function_toporder ((void (*)(function *, void *, void *)) execute_pass_list, - pass->sub); + pass->sub, &startwith_p); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } else if (pass->sub->type == SIMPLE_IPA_PASS diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 1c68485..df97f45 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -616,7 +616,7 @@ extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt); 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 = false); +extern void execute_pass_list (function *, opt_pass *, bool *startwith_p = NULL); 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);