This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

IPA merge 3: passmanager tweeks


Hi,
this patch makes pass manager to deal with per function properties.  
Currently we have only one global variable for current properties and when
pass manager is switching from IPA to per-function mode we just do nothing.
This sort of work, since we reset flags on beggining of each pass queue with
TODO_set_props.

This scheme however breaks on IPA branch, where the SSA properties 
on the beggining of late optimization passes depends on whether optimizations
are performed or not, so we can't just set them to static value with
TODO_set_props.

On IPA branch I just added code to push/pop properties each time the pass
manager is going from IPA to local mode and vice versa, but this breaks in
variaous side cases, such as when new functions are introduced into compilation
queue late and those late comming functions don't have yet all the properties
introduced by earlier IPA passes.

The alternative of truly managing properties for each function separately
seems cleaner thus and hopefully the extra two integer in function structure
are not going to kill us.

This patch also makes working stuff like TODO_dump_function at the end of IPA
pass and hopefully brings us closer to plan of using pass manager instead of
all the current funny interaction in between cgraphunit, passes and
tree-optimize.

Bootstrapped/regtested i686-linux, OK?

	* omp-low.c (expand_omp_parallel): Set function properties.
	* function.h (struct function): Add curr_properties and last_verified.
	* passes.c (register_dump_files): Do not set TODO_set_props for the
	first pass
	(init_optimization_passes): Set it here; reorder initialization so the
	dump files appear in more logic order.
	(last_verified, curr_properties): Kill.
	(do_per_function): New function.
	(execute_function_todo): Break out from ...
	(execute_todo): ... here; handle per-function flags.
	(clear_last_verified, verify_curr_properties,
	update_properties_after_pass): New functions.
	(execute_one_pass): Handle per-function properties.
	(execute_ipa_pass_list): Use do_per_function; sanity check that cfun
	and current_function_decls are cleared out.
	* ipa-cp.c (constant_val_insert): Clear cfun/current_function_decl
	after use.
Index: omp-low.c
===================================================================
*** omp-low.c	(revision 119377)
--- omp-low.c	(working copy)
*************** expand_omp_parallel (struct omp_region *
*** 2526,2531 ****
--- 2526,2533 ----
        new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
        if (exit_bb)
  	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+       DECL_STRUCT_FUNCTION (child_fn)->curr_properties
+ 	= cfun->curr_properties;
        cgraph_add_new_function (child_fn);
  
        /* Convert OMP_RETURN into a RETURN_EXPR.  */
Index: function.h
===================================================================
*** function.h	(revision 119377)
--- function.h	(working copy)
*************** struct function GTY(())
*** 370,375 ****
--- 370,379 ----
       Used for detecting stack clobbers.  */
    tree stack_protect_guard;
  
+   /* Properties used by the passmanager.  */
+   unsigned int curr_properties;
+   unsigned int last_verified;
+ 
    /* Collected bit flags.  */
  
    /* Nonzero if function being compiled needs to be given an address
Index: passes.c
===================================================================
*** passes.c	(revision 119377)
--- passes.c	(working copy)
*************** static void 
*** 371,377 ****
  register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties)
  {
    pass->properties_required |= properties;
-   pass->todo_flags_start |= TODO_set_props;
    register_dump_files_1 (pass, ipa, properties);
  }
  
--- 371,376 ----
*************** init_optimization_passes (void)
*** 695,726 ****
  #undef NEXT_PASS
  
    /* Register the passes with the tree dump code.  */
    register_dump_files (all_ipa_passes, true,
  		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
  		       | PROP_cfg);
-   register_dump_files (all_lowering_passes, false, PROP_gimple_any);
    register_dump_files (all_passes, false,
  		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
  		       | PROP_cfg);
  }
  
! static unsigned int last_verified;
! static unsigned int curr_properties;
! 
  static void
! execute_todo (unsigned int flags)
  {
! #if defined ENABLE_CHECKING
!   if (need_ssa_update_p ())
!     gcc_assert (flags & TODO_update_ssa_any);
! #endif
  
!   if (curr_properties & PROP_ssa)
      flags |= TODO_verify_ssa;
!   flags &= ~last_verified;
    if (!flags)
      return;
!   
    /* Always recalculate SMT usage before doing anything else.  */
    if (flags & TODO_update_smt_usage)
      recalculate_used_alone ();
--- 694,745 ----
  #undef NEXT_PASS
  
    /* Register the passes with the tree dump code.  */
+   register_dump_files (all_lowering_passes, false, PROP_gimple_any);
+   all_lowering_passes->todo_flags_start |= TODO_set_props;
    register_dump_files (all_ipa_passes, true,
  		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
  		       | PROP_cfg);
    register_dump_files (all_passes, false,
  		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
  		       | PROP_cfg);
  }
  
! /* Call CALLBACK for every function if current function is not set
!    (ie we do IPA) and for current function otehrwise.  */
  static void
! do_per_function (void (*callback) (void *data), void *data)
  {
!   if (current_function_decl)
!     callback (data);
!   else
!     {
!       struct cgraph_node *node;
!       for (node = cgraph_nodes; node; node = node->next)
! 	if (node->analyzed)
! 	  {
! 	    push_cfun (DECL_STRUCT_FUNCTION (node->decl));
! 	    current_function_decl = node->decl;
! 	    callback (data);
! 	    free_dominance_info (CDI_DOMINATORS);
! 	    free_dominance_info (CDI_POST_DOMINATORS);
! 	    current_function_decl = NULL;
! 	    pop_cfun ();
! 	    ggc_collect ();
! 	  }
!     }
! }
  
! /* Perform all TODO actions that ought to be done at function basis.  */
! static void
! execute_function_todo (void *data)
! {
!   unsigned int flags = (size_t)data;
!   if (cfun->curr_properties & PROP_ssa)
      flags |= TODO_verify_ssa;
!   flags &= ~cfun->last_verified;
    if (!flags)
      return;
! 
    /* Always recalculate SMT usage before doing anything else.  */
    if (flags & TODO_update_smt_usage)
      recalculate_used_alone ();
*************** execute_todo (unsigned int flags)
*** 753,759 ****
      {
        unsigned update_flags = flags & TODO_update_ssa_any;
        update_ssa (update_flags);
!       last_verified &= ~TODO_verify_ssa;
      }
  
    if (flags & TODO_remove_unused_locals)
--- 772,778 ----
      {
        unsigned update_flags = flags & TODO_update_ssa_any;
        update_ssa (update_flags);
!       cfun->last_verified &= ~TODO_verify_ssa;
      }
  
    if (flags & TODO_remove_unused_locals)
*************** execute_todo (unsigned int flags)
*** 762,780 ****
    if ((flags & TODO_dump_func)
        && dump_file && current_function_decl)
      {
!       if (curr_properties & PROP_trees)
          dump_function_to_file (current_function_decl,
                                 dump_file, dump_flags);
        else
  	{
  	  if (dump_flags & TDF_SLIM)
  	    print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
! 	  else if ((curr_properties & PROP_cfg) && (dump_flags & TDF_BLOCKS))
  	    print_rtl_with_bb (dump_file, get_insns ());
            else
  	    print_rtl (dump_file, get_insns ());
  
! 	  if (curr_properties & PROP_cfg
  	      && graph_dump_format != no_graph
  	      && (dump_flags & TDF_GRAPH))
  	    print_rtl_graph_with_bb (dump_file_name, get_insns ());
--- 781,800 ----
    if ((flags & TODO_dump_func)
        && dump_file && current_function_decl)
      {
!       if (cfun->curr_properties & PROP_trees)
          dump_function_to_file (current_function_decl,
                                 dump_file, dump_flags);
        else
  	{
  	  if (dump_flags & TDF_SLIM)
  	    print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
! 	  else if ((cfun->curr_properties & PROP_cfg)
! 		   && (dump_flags & TDF_BLOCKS))
  	    print_rtl_with_bb (dump_file, get_insns ());
            else
  	    print_rtl (dump_file, get_insns ());
  
! 	  if (cfun->curr_properties & PROP_cfg
  	      && graph_dump_format != no_graph
  	      && (dump_flags & TDF_GRAPH))
  	    print_rtl_graph_with_bb (dump_file_name, get_insns ());
*************** execute_todo (unsigned int flags)
*** 784,789 ****
--- 804,835 ----
  	 close the file before aborting.  */
        fflush (dump_file);
      }
+ 
+ #if defined ENABLE_CHECKING
+   if (flags & TODO_verify_ssa)
+     verify_ssa (true);
+   if (flags & TODO_verify_flow)
+     verify_flow_info ();
+   if (flags & TODO_verify_stmts)
+     verify_stmts ();
+   if (flags & TODO_verify_loops)
+     verify_loop_closed_ssa ();
+ #endif
+ 
+   cfun->last_verified = flags & TODO_verify_all;
+ }
+ 
+ /* Perform all TODO actions.  */
+ static void
+ execute_todo (unsigned int flags)
+ {
+ #if defined ENABLE_CHECKING
+   if (need_ssa_update_p ())
+     gcc_assert (flags & TODO_update_ssa_any);
+ #endif
+ 
+   do_per_function (execute_function_todo, (void *)(size_t) flags);
+ 
    if ((flags & TODO_dump_cgraph)
        && dump_file && !current_function_decl)
      {
*************** execute_todo (unsigned int flags)
*** 797,815 ****
      {
        ggc_collect ();
      }
  
! #if defined ENABLE_CHECKING
!   if (flags & TODO_verify_ssa)
!     verify_ssa (true);
!   if (flags & TODO_verify_flow)
!     verify_flow_info ();
!   if (flags & TODO_verify_stmts)
!     verify_stmts ();
!   if (flags & TODO_verify_loops)
!     verify_loop_closed_ssa ();
! #endif
  
!   last_verified = flags & TODO_verify_all;
  }
  
  static bool
--- 843,874 ----
      {
        ggc_collect ();
      }
+ }
  
! /* Clear the last verified flag.  */
! static void
! clear_last_verified (void *data ATTRIBUTE_UNUSED)
! {
!   cfun->last_verified = 0;
! }
  
! /* Helper function. Verify that the properties has been turn into the
!    properties expected by the pass.  */
! static void
! verify_curr_properties (void *data)
! {
!   unsigned int props = (size_t)data;
!   gcc_assert ((cfun->curr_properties & props) == props);
! }
! 
! /* After executing the pass, apply expected changes to the function properties.
!    */
! static void
! update_properties_after_pass (void *data)
! {
!   struct tree_opt_pass *pass = data;
!   cfun->curr_properties = (cfun->curr_properties | pass->properties_provided)
! 		           & ~pass->properties_destroyed;
  }
  
  static bool
*************** execute_one_pass (struct tree_opt_pass *
*** 823,839 ****
      return false;
  
    if (pass->todo_flags_start & TODO_set_props)
!     curr_properties = pass->properties_required;
  
    /* Note that the folders should only create gimple expressions.
       This is a hack until the new folder is ready.  */
!   in_gimple_form = (curr_properties & PROP_trees) != 0;
  
    /* Run pre-pass verification.  */
    execute_todo (pass->todo_flags_start);
  
!   gcc_assert ((curr_properties & pass->properties_required)
! 	      == pass->properties_required);
  
    if (pass->properties_destroyed & PROP_smt_usage)
      updating_used_alone = true;
--- 882,900 ----
      return false;
  
    if (pass->todo_flags_start & TODO_set_props)
!     cfun->curr_properties = pass->properties_required;
  
    /* Note that the folders should only create gimple expressions.
       This is a hack until the new folder is ready.  */
!   in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
  
    /* Run pre-pass verification.  */
    execute_todo (pass->todo_flags_start);
  
! #ifdef ENABLE_CHECKING
!   do_per_function (verify_curr_properties,
! 		   (void *)(size_t)pass->properties_required);
! #endif
  
    if (pass->properties_destroyed & PROP_smt_usage)
      updating_used_alone = true;
*************** execute_one_pass (struct tree_opt_pass *
*** 869,888 ****
    if (pass->execute)
      {
        todo_after = pass->execute ();
!       last_verified = 0;
      }
  
    /* Stop timevar.  */
    if (pass->tv_id)
      timevar_pop (pass->tv_id);
  
!   curr_properties = (curr_properties | pass->properties_provided)
! 		    & ~pass->properties_destroyed;
  
    if (initializing_dump
        && dump_file
        && graph_dump_format != no_graph
!       && (curr_properties & (PROP_cfg | PROP_rtl)) == (PROP_cfg | PROP_rtl))
      {
        get_dump_file_info (pass->static_pass_number)->flags |= TDF_GRAPH;
        dump_flags |= TDF_GRAPH;
--- 930,949 ----
    if (pass->execute)
      {
        todo_after = pass->execute ();
!       do_per_function (clear_last_verified, NULL);
      }
  
    /* Stop timevar.  */
    if (pass->tv_id)
      timevar_pop (pass->tv_id);
  
!   do_per_function (update_properties_after_pass, pass);
  
    if (initializing_dump
        && dump_file
        && graph_dump_format != no_graph
!       && (cfun->curr_properties & (PROP_cfg | PROP_rtl))
! 	  == (PROP_cfg | PROP_rtl))
      {
        get_dump_file_info (pass->static_pass_number)->flags |= TDF_GRAPH;
        dump_flags |= TDF_GRAPH;
*************** execute_ipa_pass_list (struct tree_opt_p
*** 929,950 ****
  {
    do
      {
        if (execute_one_pass (pass) && pass->sub)
! 	{
! 	  struct cgraph_node *node;
! 	  for (node = cgraph_nodes; node; node = node->next)
! 	    if (node->analyzed)
! 	      {
! 		push_cfun (DECL_STRUCT_FUNCTION (node->decl));
! 		current_function_decl = node->decl;
! 		execute_pass_list (pass->sub);
! 		free_dominance_info (CDI_DOMINATORS);
! 		free_dominance_info (CDI_POST_DOMINATORS);
! 		current_function_decl = NULL;
! 		pop_cfun ();
! 		ggc_collect ();
! 	      }
! 	}
        pass = pass->next;
      }
    while (pass);
--- 990,999 ----
  {
    do
      {
+       gcc_assert (!current_function_decl);
+       gcc_assert (!cfun);
        if (execute_one_pass (pass) && pass->sub)
! 	do_per_function ((void (*)(void *))execute_pass_list, pass->sub);
        pass = pass->next;
      }
    while (pass);
Index: ipa-cp.c
===================================================================
--- ipa-cp.c	(revision 119444)
+++ ipa-cp.c	(working copy)
@@ -453,6 +453,8 @@ constant_val_insert (tree fn, tree parm1
   if (ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
     FOR_EACH_EDGE (e_step, ei, ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs)
       bsi_insert_on_edge_immediate (e_step, init_stmt);
+  current_function_decl = NULL;
+  cfun = NULL;
 }
 
 /* build INTEGER_CST tree with type TREE_TYPE and 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]