IPA-CP cleanups and improvements

Jan Hubicka jh@suse.cz
Sat Aug 23 20:27:00 GMT 2008


Hi,
this patch cleans up ipcp.  Originally IPCP propagated simple constants as
IPA_CONST_VALUE, while addresses was IPA_CONST_VALUE_REF.  Only special cases
was handled.  Now all invariant expressions passing gimple_ip_invariant are
propagated as IPA_CONST_VALUE.  Also I've fixed number of bugs that prevented
parameters to be actually replaced by constant in the clones.

Bootstrapped/regtested with ipcp enabled by default on x86_64-linux;
will commit it if there are no complains and previous patch is accepted.

Now IPCP should do pretty as much clonning as possible with current
algorithm.  I will add some simple metric scheme and would like to
enable it by default at -O3 (and possibly -O2 for no code size expanding
transformations) so the whole infrastructure is excersised.
IPCP is also very cheap since analysis are used by inliner too. Sadly I
didn't benchmarked any improvmeent on real world code with the previous
implementation, perhaps this one will get better ;)

	* ipa-cp.c (ipcp_lat_is_const): Remove handling of IPA_CONST_VALUE_REF.
	(ipcp_lat_is_insertable): All constants are insertable.
	(ipcp_lattice_from_jfunc, ipcp_print_all_lattices): Remove handling of
	IPA_CONST_VALUE_REF.
	(ipcp_initialize_node_lattices): Propagate all types of operands.
	(build_const_val): Do not handle IPA_CONST_VALUE_REF.
	(ipcp_create_replace_map): Reformat.
	(ipcp_need_redirect_p): Simplify.
	(ipcp_insert_stage): Check that argument is used before clonning.
	* ipa-prop.c (ipa_print_node_jump_functions): Do not handle IPA_CONST_REF.
	(compute_scalar_jump_functions): Simplify using is_gimple_ip_invariat.
	(determine_cst_member_ptr): Keep wrapping ADDR_EXPR of members.
	(update_call_notes_after_inlining): Expect ADDR_EXPR in operand.
	* ipa-prop.h (jump_func_type): Remove IPA_CONST_REF.
	(jump_func_type): Remove IPA_CONST_VALUE_REF.
	* tree-inline.c (tree_function_versioning): Add variables referenced by
	replacing trees.
Index: ipa-cp.c
===================================================================
*** ipa-cp.c	(revision 139391)
--- ipa-cp.c	(working copy)
*************** ipcp_set_node_scale (struct cgraph_node 
*** 207,213 ****
  static inline bool
  ipcp_lat_is_const (struct ipcp_lattice *lat)
  {
!   if (lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
      return true;
    else
      return false;
--- 207,213 ----
  static inline bool
  ipcp_lat_is_const (struct ipcp_lattice *lat)
  {
!   if (lat->type == IPA_CONST_VALUE)
      return true;
    else
      return false;
*************** ipcp_lat_is_const (struct ipcp_lattice *
*** 218,228 ****
  static inline bool
  ipcp_lat_is_insertable (struct ipcp_lattice *lat)
  {
!   if ((lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
!       && !POINTER_TYPE_P (TREE_TYPE (lat->constant)))
!     return true;
!   else
!     return false;
  }
  
  /* Return true if LAT1 and LAT2 are equal.  */
--- 218,224 ----
  static inline bool
  ipcp_lat_is_insertable (struct ipcp_lattice *lat)
  {
!   return lat->type == IPA_CONST_VALUE;
  }
  
  /* Return true if LAT1 and LAT2 are equal.  */
*************** ipcp_lattice_from_jfunc (struct ipa_node
*** 294,304 ****
        lat->type = IPA_CONST_VALUE;
        lat->constant = jfunc->value.constant;
      }
-   else if (jfunc->type == IPA_CONST_REF)
-     {
-       lat->type = IPA_CONST_VALUE_REF;
-       lat->constant = jfunc->value.constant;
-     }
    else if (jfunc->type == IPA_PASS_THROUGH)
      {
        struct ipcp_lattice *caller_lat;
--- 290,295 ----
*************** ipcp_print_all_lattices (FILE * f)
*** 349,355 ****
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
  
  	  fprintf (f, " param [%d]: ", i);
! 	  if (lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
  	    {
  	      fprintf (f, "type is CONST ");
  	      print_generic_expr (f, lat->constant, 0);
--- 340,346 ----
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
  
  	  fprintf (f, " param [%d]: ", i);
! 	  if (lat->type == IPA_CONST_VALUE)
  	    {
  	      fprintf (f, "type is CONST ");
  	      print_generic_expr (f, lat->constant, 0);
*************** ipcp_initialize_node_lattices (struct cg
*** 375,391 ****
    info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
  				  ipa_get_param_count (info));
    for (i = 0; i < ipa_get_param_count (info) ; i++)
!     {
!       tree parm_tree = ipa_get_ith_param (info, i);
!       struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
! 
!       if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
! 	  || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
! 	  || POINTER_TYPE_P (TREE_TYPE (parm_tree)))
! 	lat->type = IPA_TOP;
!       else
! 	lat->type = IPA_BOTTOM;
!     }
  }
  
  /* Create a new assignment statement and make it the first statement in the
--- 366,372 ----
    info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
  				  ipa_get_param_count (info));
    for (i = 0; i < ipa_get_param_count (info) ; i++)
!     ipcp_get_ith_lattice (info, i)->type = IPA_TOP;
  }
  
  /* Create a new assignment statement and make it the first statement in the
*************** build_const_val (struct ipcp_lattice *la
*** 412,425 ****
    gcc_assert (ipcp_lat_is_const (lat));
    val = lat->constant;
  
-   /* compute_jump_functions inserts FUNCTION_DECL as value of parameter
-      when address of function is taken.  It would make more sense to pass
-      whole ADDR_EXPR, but for now compensate here.  */
-   if ((lat->type == IPA_CONST_VALUE
-         && TREE_CODE (val) == FUNCTION_DECL)
-       || lat->type == IPA_CONST_VALUE_REF)
-     return build_fold_addr_expr_with_type (val, tree_type);
- 
    if (!useless_type_conversion_p (tree_type, TREE_TYPE (val)))
      {
        if (fold_convertible_p (tree_type, val))
--- 393,398 ----
*************** ipcp_create_replace_map (struct function
*** 789,795 ****
    tree const_val;
  
    replace_map = XCNEW (struct ipa_replace_map);
!   if (is_gimple_reg (parm_tree) && gimple_default_def (func, parm_tree)
        && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_default_def (func,
  								 parm_tree)))
      {
--- 762,769 ----
    tree const_val;
  
    replace_map = XCNEW (struct ipa_replace_map);
!   if (is_gimple_reg (parm_tree)
!       && gimple_default_def (func, parm_tree)
        && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_default_def (func,
  								 parm_tree)))
      {
*************** ipcp_need_redirect_p (struct cgraph_edge
*** 829,836 ****
        if (ipcp_lat_is_const (lat))
  	{
  	  jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
! 	  if (jump_func->type != IPA_CONST && jump_func->type != IPA_CONST_REF
! 	      && jump_func->type != IPA_CONST_MEMBER_PTR)
  	    return true;
  	}
      }
--- 803,809 ----
        if (ipcp_lat_is_const (lat))
  	{
  	  jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
! 	  if (jump_func->type != IPA_CONST)
  	    return true;
  	}
      }
*************** ipcp_insert_stage (void)
*** 949,955 ****
        for (i = 0; i < count; i++)
  	{
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
! 	  if (ipcp_lat_is_insertable (lat))
  	    const_param++;
  	}
        if (const_param == 0)
--- 922,932 ----
        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);
! 	  if (ipcp_lat_is_insertable (lat)
! 	      /* Do not count obviously unused arguments.  */
! 	      && (!is_gimple_reg (parm_tree)
! 		  || gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm_tree)))
  	    const_param++;
  	}
        if (const_param == 0)
*************** ipcp_insert_stage (void)
*** 958,965 ****
        for (i = 0; i < count; i++)
  	{
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
! 	  if (lat->type == IPA_CONST_VALUE
! 	      && !POINTER_TYPE_P (TREE_TYPE (lat->constant)))
  	    {
  	      parm_tree = ipa_get_ith_param (info, i);
  	      replace_param =
--- 935,941 ----
        for (i = 0; i < count; i++)
  	{
  	  struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
! 	  if (lat->type == IPA_CONST_VALUE)
  	    {
  	      parm_tree = ipa_get_ith_param (info, i);
  	      replace_param =
*************** ipcp_insert_stage (void)
*** 999,1006 ****
  	      if (ipcp_lat_is_insertable (lat))
  		{
  		  parm_tree = ipa_get_ith_param (info, i);
! 		  if (lat->type != IPA_CONST_VALUE_REF
! 		      && !is_gimple_reg (parm_tree))
  		    ipcp_propagate_one_const (node1, i, lat);
  		}
  	    }
--- 975,981 ----
  	      if (ipcp_lat_is_insertable (lat))
  		{
  		  parm_tree = ipa_get_ith_param (info, i);
! 		  if (!is_gimple_reg (parm_tree))
  		    ipcp_propagate_one_const (node1, i, lat);
  		}
  	    }
Index: ipa-prop.c
===================================================================
*** ipa-prop.c	(revision 139391)
--- ipa-prop.c	(working copy)
*************** ipa_print_node_jump_functions (FILE *f, 
*** 273,279 ****
  	  fprintf (f, "  param %d: ", i);
  	  if (type == IPA_UNKNOWN)
  	    fprintf (f, "UNKNOWN\n");
! 	  else if (type == IPA_CONST || type == IPA_CONST_REF)
   	    {
  	      tree val = jump_func->value.constant;
  	      fprintf (f, "CONST: ");
--- 273,279 ----
  	  fprintf (f, "  param %d: ", i);
  	  if (type == IPA_UNKNOWN)
  	    fprintf (f, "UNKNOWN\n");
! 	  else if (type == IPA_CONST)
   	    {
  	      tree val = jump_func->value.constant;
  	      fprintf (f, "CONST: ");
*************** compute_scalar_jump_functions (struct ip
*** 327,359 ****
      {
        arg = gimple_call_arg (call, num);
  
!       if (TREE_CODE (arg) == INTEGER_CST
! 	  || TREE_CODE (arg) == REAL_CST
! 	  || TREE_CODE (arg) == FIXED_CST)
  	{
  	  functions[num].type = IPA_CONST;
  	  functions[num].value.constant = arg;
  	}
-       else if (TREE_CODE (arg) == ADDR_EXPR)
- 	{
- 	  if (TREE_CODE (TREE_OPERAND (arg, 0)) == FUNCTION_DECL)
- 	    {
- 	      functions[num].type = IPA_CONST;
- 	      functions[num].value.constant = TREE_OPERAND (arg, 0);
- 	    }
- 	  else if (TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL)
- 	    {
- 	      tree cst_decl = TREE_OPERAND (arg, 0);
- 
- 	      if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
- 		  || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST
- 		  || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
- 		{
- 		  functions[num].type = IPA_CONST_REF;
- 		  functions[num].value.constant = cst_decl;
- 		}
- 	    }
-  	}
        else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg))
  	{
  	  int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
--- 327,337 ----
      {
        arg = gimple_call_arg (call, num);
  
!       if (is_gimple_ip_invariant (arg))
  	{
  	  functions[num].type = IPA_CONST;
  	  functions[num].value.constant = arg;
  	}
        else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg))
  	{
  	  int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
*************** determine_cst_member_ptr (gimple call, t
*** 496,502 ****
  	      method = TREE_OPERAND (rhs, 0);
  	      if (delta)
  		{
! 		  fill_member_ptr_cst_jump_function (jfunc, method, delta);
  		  return;
  		}
  	    }
--- 474,480 ----
  	      method = TREE_OPERAND (rhs, 0);
  	      if (delta)
  		{
! 		  fill_member_ptr_cst_jump_function (jfunc, rhs, delta);
  		  return;
  		}
  	    }
*************** determine_cst_member_ptr (gimple call, t
*** 511,517 ****
  	      delta = rhs;
  	      if (method)
  		{
! 		  fill_member_ptr_cst_jump_function (jfunc, method, delta);
  		  return;
  		}
  	    }
--- 489,495 ----
  	      delta = rhs;
  	      if (method)
  		{
! 		  fill_member_ptr_cst_jump_function (jfunc, rhs, delta);
  		  return;
  		}
  	    }
*************** update_call_notes_after_inlining (struct
*** 952,957 ****
--- 930,939 ----
  	  else
  	    decl = jfunc->value.constant;
  
+ 	  if (TREE_CODE (decl) != ADDR_EXPR)
+ 	    continue;
+ 	  decl = TREE_OPERAND (decl, 0);
+ 
  	  if (TREE_CODE (decl) != FUNCTION_DECL)
  	    continue;
  	  callee = cgraph_node (decl);
Index: ipa-prop.h
===================================================================
*** ipa-prop.h	(revision 139391)
--- ipa-prop.h	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 32,45 ****
     Formal - the caller's formal parameter is passed as an actual argument.
     Constant - a constant is passed as an actual argument.
     Unknown - neither of the above.
!    Integer and real constants are represented as IPA_CONST and Fortran
!    constants are represented as IPA_CONST_REF.  Finally, IPA_CONST_MEMBER_PTR
!    stands for C++ member pointers constants.  */
  enum jump_func_type
  {
    IPA_UNKNOWN = 0,     /* newly allocated and zeroed jump functions default */
    IPA_CONST,
-   IPA_CONST_REF,
    IPA_CONST_MEMBER_PTR,
    IPA_PASS_THROUGH
  };
--- 32,43 ----
     Formal - the caller's formal parameter is passed as an actual argument.
     Constant - a constant is passed as an actual argument.
     Unknown - neither of the above.
!    Integer and real constants are represented as IPA_CONST.
!    Finally, IPA_CONST_MEMBER_PTR stands for C++ member pointers constants.  */
  enum jump_func_type
  {
    IPA_UNKNOWN = 0,     /* newly allocated and zeroed jump functions default */
    IPA_CONST,
    IPA_CONST_MEMBER_PTR,
    IPA_PASS_THROUGH
  };
*************** enum jump_func_type
*** 52,64 ****
     IPA_CONST_VALUE - simple scalar constant,
     Cval of formal f will have a constant value if all callsites to this
     function have the same constant value passed to f.
!    Integer and real constants are represented as IPA_CONST and Fortran
!    constants are represented as IPA_CONST_REF.  */
  enum ipa_lattice_type
  {
    IPA_BOTTOM,
    IPA_CONST_VALUE,
-   IPA_CONST_VALUE_REF,
    IPA_TOP
  };
  
--- 50,60 ----
     IPA_CONST_VALUE - simple scalar constant,
     Cval of formal f will have a constant value if all callsites to this
     function have the same constant value passed to f.
!    Integer and real constants are represented as IPA_CONST.  */
  enum ipa_lattice_type
  {
    IPA_BOTTOM,
    IPA_CONST_VALUE,
    IPA_TOP
  };
  
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 139391)
--- tree-inline.c	(working copy)
*************** tree_function_versioning (tree old_decl,
*** 4214,4221 ****
  	replace_info
  	  = (struct ipa_replace_map *) VARRAY_GENERIC_PTR (tree_map, i);
  	if (replace_info->replace_p)
! 	  insert_decl_map (&id, replace_info->old_tree,
! 			   replace_info->new_tree);
        }
    
    DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
--- 4214,4231 ----
  	replace_info
  	  = (struct ipa_replace_map *) VARRAY_GENERIC_PTR (tree_map, i);
  	if (replace_info->replace_p)
! 	  {
! 	    if (TREE_CODE (replace_info->new_tree) == ADDR_EXPR)
! 	      {
! 		tree op = TREE_OPERAND (replace_info->new_tree, 0);
! 		while (handled_component_p (op))
! 		  op = TREE_OPERAND (op, 0);
! 		if (TREE_CODE (op) == VAR_DECL)
! 		  add_referenced_var (op);
! 	      }
! 	    insert_decl_map (&id, replace_info->old_tree,
! 			     replace_info->new_tree);
! 	  }
        }
    
    DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);



More information about the Gcc-patches mailing list