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);

Reply via email to