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]

Make ipcp to skip arguments known to be constant


Hi,
this updates ipa-cp to remove argument from function declarations, types and call expressions.

Bootstrapped/regtested x86_64-linux with clonning enabled, will commit it once ( if :)
previous patch is accepted.

Honza

	* cgraph.h (cgraph_function_versioning): Add argument to list
	args to skip.
	* ipa-cp.c (ipcp_node_not_modifiable_p): remove.
	(ipcp_node_modifiable_p): New function.
	(ipcp_create_replace_map): Improve debug output.
	(ipcp_need_redirect_p): When not clonning, nothing needs redirect.
	(ipcp_update_callgraph): Skip argument in callers.
	(ipcp_insert_stage): List arguments to skip.
	* cgraphunit.c (cgraph_function_versioning): Add new argument for
	args to skip.
	* tree-inline.c (copy_arguments_for_versioning): Likewise.
	(tree_function_versioning): Likewise.
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 139571)
--- cgraph.h	(working copy)
*************** void cgraph_reset_static_var_maps (void)
*** 351,357 ****
  void init_cgraph (void);
  struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
  						VEC(cgraph_edge_p,heap)*,
! 						varray_type);
  void cgraph_analyze_function (struct cgraph_node *);
  struct cgraph_node *save_inline_function_body (struct cgraph_node *);
  void record_references_in_initializer (tree);
--- 351,358 ----
  void init_cgraph (void);
  struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
  						VEC(cgraph_edge_p,heap)*,
! 						varray_type,
! 						bitmap);
  void cgraph_analyze_function (struct cgraph_node *);
  struct cgraph_node *save_inline_function_body (struct cgraph_node *);
  void record_references_in_initializer (tree);
Index: ipa-cp.c
===================================================================
*** ipa-cp.c	(revision 139571)
--- ipa-cp.c	(working copy)
*************** ipcp_iterate_stage (void)
*** 560,571 ****
  /* Check conditions to forbid constant insertion to function described by
     NODE.  */
  static inline bool
! ipcp_node_not_modifiable_p (struct cgraph_node *node)
  {
!   /* ??? Handle pending sizes case.  */
!   if (DECL_UNINLINABLE (node->decl))
!     return true;
!   return false;
  }
  
  /* Print count scale data structures.  */
--- 560,570 ----
  /* Check conditions to forbid constant insertion to function described by
     NODE.  */
  static inline bool
! ipcp_node_modifiable_p (struct cgraph_node *node)
  {
!   /* Once we will be able to do in-place replacement, we can be more
!      lax here.  */
!   return tree_versionable_function_p (node->decl);
  }
  
  /* Print count scale data structures.  */
*************** ipcp_create_replace_map (tree parm_tree,
*** 745,753 ****
    tree const_val;
  
    replace_map = XCNEW (struct ipa_replace_map);
-   if (dump_file)
-     fprintf (dump_file, "replacing param with const\n");
    const_val = build_const_val (lat, TREE_TYPE (parm_tree));
    replace_map->old_tree = parm_tree;
    replace_map->new_tree = const_val;
    replace_map->replace_p = true;
--- 744,758 ----
    tree const_val;
  
    replace_map = XCNEW (struct ipa_replace_map);
    const_val = build_const_val (lat, TREE_TYPE (parm_tree));
+   if (dump_file)
+     {
+       fprintf (dump_file, "  replacing param ");
+       print_generic_expr (dump_file, parm_tree, 0);
+       fprintf (dump_file, " with const ");
+       print_generic_expr (dump_file, const_val, 0);
+       fprintf (dump_file, "\n");
+     }
    replace_map->old_tree = parm_tree;
    replace_map->new_tree = const_val;
    replace_map->replace_p = true;
*************** ipcp_need_redirect_p (struct cgraph_edge
*** 766,771 ****
--- 771,779 ----
    struct ipa_jump_func *jump_func;
    struct cgraph_node *node = cs->callee, *orig;
  
+   if (!flag_ipa_cp_clone)
+     return false;
+ 
    if ((orig = ipcp_get_orig_node (node)) != NULL)
      node = orig;
    if (ipcp_get_orig_node (cs->caller))
*************** ipcp_need_redirect_p (struct cgraph_edge
*** 791,816 ****
  static void
  ipcp_update_callgraph (void)
  {
!   struct cgraph_node *node, *orig_callee;
!   struct cgraph_edge *cs;
  
    for (node = cgraph_nodes; node; node = node->next)
!     {
!       /* want to fix only original nodes  */
!       if (!node->analyzed || ipcp_node_is_clone (node))
! 	continue;
!       for (cs = node->callees; cs; cs = cs->next_callee)
! 	if (ipcp_node_is_clone (cs->callee))
  	  {
! 	    /* Callee is a cloned node  */
! 	    orig_callee = ipcp_get_orig_node (cs->callee);
! 	    if (ipcp_need_redirect_p (cs))
  	      {
! 		cgraph_redirect_edge_callee (cs, orig_callee);
! 		gimple_call_set_fndecl (cs->call_stmt, orig_callee->decl);
  	      }
  	  }
!     }
  }
  
  /* Update all cfg basic blocks in NODE according to SCALE.  */
--- 799,857 ----
  static void
  ipcp_update_callgraph (void)
  {
!   struct cgraph_node *node;
  
    for (node = cgraph_nodes; node; node = node->next)
!     if (node->analyzed && ipcp_node_is_clone (node))
!       {
! 	bitmap args_to_skip = BITMAP_ALLOC (NULL);
! 	struct cgraph_node *orig_node = ipcp_get_orig_node (node);
!         struct ipa_node_params *info = IPA_NODE_REF (orig_node);
!         int i, count = ipa_get_param_count (info);
!         struct cgraph_edge *cs, *next;
! 
! 	for (i = 0; i < count; i++)
  	  {
! 	    struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
! 	    tree parm_tree = ipa_get_ith_param (info, i);
! 
! 	    /* We can proactively remove obviously unused arguments.  */
! 	    if (is_gimple_reg (parm_tree)
! 		&& !gimple_default_def (DECL_STRUCT_FUNCTION (orig_node->decl),
! 					parm_tree))
  	      {
! 		bitmap_set_bit (args_to_skip, i);
! 		continue;
  	      }
+ 
+ 	    if (lat->type == IPA_CONST_VALUE)
+ 	      bitmap_set_bit (args_to_skip, i);
  	  }
! 	for (cs = node->callers; cs; cs = next)
! 	  {
! 	    next = cs->next_caller;
! 	    if (ipcp_node_is_clone (cs->caller) || !ipcp_need_redirect_p (cs))
! 	      {
! 		gimple new_stmt;
! 		gimple_stmt_iterator gsi;
! 
! 		current_function_decl = cs->caller->decl;
! 	        push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
! 		
! 		new_stmt = gimple_call_skip_args (cs->call_stmt, args_to_skip);
! 		gsi = gsi_for_stmt (cs->call_stmt);
! 		gsi_replace (&gsi, new_stmt, false);
! 		cgraph_set_call_stmt (cs, new_stmt);
! 	        pop_cfun ();
! 		current_function_decl = NULL;
! 	      }
! 	    else
! 	      {
! 		cgraph_redirect_edge_callee (cs, orig_node);
! 		gimple_call_set_fndecl (cs->call_stmt, orig_node->decl);
! 	      }
! 	  }
!       }
  }
  
  /* Update all cfg basic blocks in NODE according to SCALE.  */
*************** ipcp_insert_stage (void)
*** 989,995 ****
      {
        struct ipa_node_params *info;
        /* Propagation of the constant is forbidden in certain conditions.  */
!       if (!node->analyzed || ipcp_node_not_modifiable_p (node))
  	  continue;
        info = IPA_NODE_REF (node);
        if (ipa_is_called_with_var_arguments (info))
--- 1030,1036 ----
      {
        struct ipa_node_params *info;
        /* Propagation of the constant is forbidden in certain conditions.  */
!       if (!node->analyzed || !ipcp_node_modifiable_p (node))
  	  continue;
        info = IPA_NODE_REF (node);
        if (ipa_is_called_with_var_arguments (info))
*************** ipcp_insert_stage (void)
*** 1004,1009 ****
--- 1045,1051 ----
      {
        struct ipa_node_params *info;
        int growth = 0;
+       bitmap args_to_skip;
  
        node = (struct cgraph_node *)fibheap_extract_min (heap);
        node->aux = NULL;
*************** ipcp_insert_stage (void)
*** 1035,1054 ****
  
        VARRAY_GENERIC_PTR_INIT (replace_trees, ipcp_const_param_count (node),
  				"replace_trees");
        for (i = 0; i < count; i++)
  	{
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
  	  parm_tree = ipa_get_ith_param (info, i);
  
! 	  if (lat->type == IPA_CONST_VALUE
! 	      /* Do not count obviously unused arguments.  */
! 	      && (!is_gimple_reg (parm_tree)
! 		  || gimple_default_def (DECL_STRUCT_FUNCTION (node->decl),
! 					 parm_tree)))
  	    {
  	      replace_param =
  		ipcp_create_replace_map (parm_tree, lat);
  	      VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
  	    }
  	}
  
--- 1077,1103 ----
  
        VARRAY_GENERIC_PTR_INIT (replace_trees, ipcp_const_param_count (node),
  				"replace_trees");
+       args_to_skip = BITMAP_ALLOC (NULL);
        for (i = 0; i < count; i++)
  	{
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
  	  parm_tree = ipa_get_ith_param (info, i);
  
! 	  /* We can proactively remove obviously unused arguments.  */
! 	  if (is_gimple_reg (parm_tree)
! 	      && !gimple_default_def (DECL_STRUCT_FUNCTION (node->decl),
! 				      parm_tree))
! 	    {
! 	      bitmap_set_bit (args_to_skip, i);
! 	      continue;
! 	    }
! 
! 	  if (lat->type == IPA_CONST_VALUE)
  	    {
  	      replace_param =
  		ipcp_create_replace_map (parm_tree, lat);
  	      VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param);
+ 	      bitmap_set_bit (args_to_skip, i);
  	    }
  	}
  
*************** ipcp_insert_stage (void)
*** 1063,1069 ****
        /* Redirecting all the callers of the node to the
           new versioned node.  */
        node1 =
! 	cgraph_function_versioning (node, redirect_callers, replace_trees);
        VEC_free (cgraph_edge_p, heap, redirect_callers);
        VARRAY_CLEAR (replace_trees);
        if (node1 == NULL)
--- 1112,1120 ----
        /* Redirecting all the callers of the node to the
           new versioned node.  */
        node1 =
! 	cgraph_function_versioning (node, redirect_callers, replace_trees,
! 				    args_to_skip);
!       BITMAP_FREE (args_to_skip);
        VEC_free (cgraph_edge_p, heap, redirect_callers);
        VARRAY_CLEAR (replace_trees);
        if (node1 == NULL)
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 139571)
--- cgraphunit.c	(working copy)
*************** cgraph_copy_node_for_versioning (struct 
*** 1496,1507 ****
      TREE_MAP is a mapping of tree nodes we want to replace with
      new ones (according to results of prior analysis).
      OLD_VERSION_NODE is the node that is versioned.
!     It returns the new version's cgraph node.  */
  
  struct cgraph_node *
  cgraph_function_versioning (struct cgraph_node *old_version_node,
  			    VEC(cgraph_edge_p,heap) *redirect_callers,
! 			    varray_type tree_map)
  {
    tree old_decl = old_version_node->decl;
    struct cgraph_node *new_version_node = NULL;
--- 1496,1510 ----
      TREE_MAP is a mapping of tree nodes we want to replace with
      new ones (according to results of prior analysis).
      OLD_VERSION_NODE is the node that is versioned.
!     It returns the new version's cgraph node. 
!     ARGS_TO_SKIP lists arguments to be omitted from functions
!     */
  
  struct cgraph_node *
  cgraph_function_versioning (struct cgraph_node *old_version_node,
  			    VEC(cgraph_edge_p,heap) *redirect_callers,
! 			    varray_type tree_map,
! 			    bitmap args_to_skip)
  {
    tree old_decl = old_version_node->decl;
    struct cgraph_node *new_version_node = NULL;
*************** cgraph_function_versioning (struct cgrap
*** 1512,1518 ****
  
    /* Make a new FUNCTION_DECL tree node for the
       new version. */
!   new_decl = copy_node (old_decl);
  
    /* Create the new version's call-graph node.
       and update the edges of the new node. */
--- 1515,1524 ----
  
    /* Make a new FUNCTION_DECL tree node for the
       new version. */
!   if (!args_to_skip)
!     new_decl = copy_node (old_decl);
!   else
!     new_decl = build_function_decl_skip_argss (old_decl, args_to_skip);
  
    /* Create the new version's call-graph node.
       and update the edges of the new node. */
*************** cgraph_function_versioning (struct cgrap
*** 1521,1527 ****
  				     redirect_callers);
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (old_decl, new_decl, tree_map, false);
    /* Update the call_expr on the edges to call the new version node. */
    update_call_expr (new_version_node);
  
--- 1527,1533 ----
  				     redirect_callers);
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip);
    /* Update the call_expr on the edges to call the new version node. */
    update_call_expr (new_version_node);
  
*************** save_inline_function_body (struct cgraph
*** 1560,1566 ****
    gcc_assert (first_clone == cgraph_node (first_clone->decl));
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (node->decl, first_clone->decl, NULL, true);
  
    DECL_EXTERNAL (first_clone->decl) = 0;
    DECL_ONE_ONLY (first_clone->decl) = 0;
--- 1566,1572 ----
    gcc_assert (first_clone == cgraph_node (first_clone->decl));
  
    /* Copy the OLD_VERSION_NODE function tree to the new version.  */
!   tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL);
  
    DECL_EXTERNAL (first_clone->decl) = 0;
    DECL_ONE_ONLY (first_clone->decl) = 0;
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 139571)
--- tree-inline.c	(working copy)
*************** copy_decl_maybe_to_var (tree decl, copy_
*** 4082,4100 ****
  
  /* Return a copy of the function's argument tree.  */
  static tree
! copy_arguments_for_versioning (tree orig_parm, copy_body_data * id)
  {
!   tree *arg_copy, *parg;
  
!   arg_copy = &orig_parm;
!   for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
!     {
!       tree new_tree = remap_decl (*parg, id);
!       lang_hooks.dup_lang_specific_decl (new_tree);
!       TREE_CHAIN (new_tree) = TREE_CHAIN (*parg);
!       *parg = new_tree;
!     }
!   return orig_parm;
  }
  
  /* Return a copy of the function's static chain.  */
--- 4082,4105 ----
  
  /* Return a copy of the function's argument tree.  */
  static tree
! copy_arguments_for_versioning (tree orig_parm, copy_body_data * id,
! 			       bitmap args_to_skip)
  {
!   tree arg, *parg;
!   tree new_parm = NULL;
!   int i = 0;
  
!   parg = &new_parm;
! 
!   for (arg = orig_parm; arg; arg = TREE_CHAIN (arg), i++)
!     if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
!       {
!         tree new_tree = remap_decl (arg, id);
!         lang_hooks.dup_lang_specific_decl (new_tree);
!         *parg = new_tree;
! 	parg = &TREE_CHAIN (new_tree);
!       }
!   return new_parm;
  }
  
  /* Return a copy of the function's static chain.  */
*************** tree_versionable_function_p (tree fndecl
*** 4139,4145 ****
     of edges of clones of the function will be updated.  */
  void
  tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
! 			  bool update_clones)
  {
    struct cgraph_node *old_version_node;
    struct cgraph_node *new_version_node;
--- 4144,4150 ----
     of edges of clones of the function will be updated.  */
  void
  tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
! 			  bool update_clones, bitmap args_to_skip)
  {
    struct cgraph_node *old_version_node;
    struct cgraph_node *new_version_node;
*************** tree_function_versioning (tree old_decl,
*** 4207,4213 ****
    /* Copy the function's arguments.  */
    if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
      DECL_ARGUMENTS (new_decl) =
!       copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id);
    
    DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
    
--- 4212,4219 ----
    /* Copy the function's arguments.  */
    if (DECL_ARGUMENTS (old_decl) != NULL_TREE)
      DECL_ARGUMENTS (new_decl) =
!       copy_arguments_for_versioning (DECL_ARGUMENTS (old_decl), &id,
!       				     args_to_skip);
    
    DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
    


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