Patchwork Tweaks to the interface between ipa-inline-analysis and ipa-cp/ipa-prop

login
register
mail settings
Submitter Martin Jambor
Date May 12, 2011, 3:40 p.m.
Message ID <20110512154047.GA6788@virgil.arch.suse.de>
Download mbox | patch
Permalink /patch/95332/
State New
Headers show

Comments

Martin Jambor - May 12, 2011, 3:40 p.m.
Hi,

the original intention of this patch was not only to make the
interface a bit nicer and internals of the lattice isolated but also
so that we do not use struct ipcp_lattice in ipa-inline-analysis.c and
thus my large modifications of theat structure do not have to be
reflected in the file.

Perhaps more importantly however, in my current work on allowing
ipa-cp to have more than one value in a lattice, the new function
estimate_ipcp_clone_size_and_time cannot pick the parameter values by
itself, ipa-cp has to supply the opportunities in a vector and pick
among them according to the returned results.  Therefore I have also
changed the interface of that function too.

By the way, in the future we may want ipa-cp to merge clones that are
equivalent (let's say one of the predicate says that a parameter is
greater than 10 and we have a bunch of callers supplying values 1, 2
and 8, we will want to create just one clone for all three values
because the effect is the same).  This means that eventually ipa-cp
will be interested in the clause_t for various values, merge
opportunities which have the same one, create a single clone for them
and somehow have the materialization modify the function body
accordingly.  The infrastructure required is not trivial but it is
probably something to think about.

I have bootstrapped and tested this patch on x86_64-linux without any
issues.  OK for trunk?

Thanks,

Martin




2011-05-10  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.c (ipa_cst_from_jfunc): New function.
	* ipa-prop.h (ipa_cst_from_jfunc): Declare.
	* ipa-inline-analysis.c (evaluate_conditions_for_edge): Use it.
	(evaluate_conditions_for_ipcp_clone): Removed.
	(estimate_ipcp_clone_size_and_time): Accept vector of known constants.
	* ipa-cp.c (ipcp_estimate_growth): Build vector of known constants.
	* ipa-inline.h (estimate_ipcp_clone_size_and_time): Update.
Jan Hubicka - May 12, 2011, 3:45 p.m.
> By the way, in the future we may want ipa-cp to merge clones that are
> equivalent (let's say one of the predicate says that a parameter is
> greater than 10 and we have a bunch of callers supplying values 1, 2
> and 8, we will want to create just one clone for all three values
> because the effect is the same).  This means that eventually ipa-cp
> will be interested in the clause_t for various values, merge
> opportunities which have the same one, create a single clone for them
> and somehow have the materialization modify the function body
> accordingly.  The infrastructure required is not trivial but it is
> probably something to think about.

Yep, I also wondered about this.  It will however need some way to promote down the
set of known truths to local optimizers...
> 2011-05-10  Martin Jambor  <mjambor@suse.cz>
> 
> 	* ipa-prop.c (ipa_cst_from_jfunc): New function.
> 	* ipa-prop.h (ipa_cst_from_jfunc): Declare.
> 	* ipa-inline-analysis.c (evaluate_conditions_for_edge): Use it.
> 	(evaluate_conditions_for_ipcp_clone): Removed.
> 	(estimate_ipcp_clone_size_and_time): Accept vector of known constants.
> 	* ipa-cp.c (ipcp_estimate_growth): Build vector of known constants.
> 	* ipa-inline.h (estimate_ipcp_clone_size_and_time): Update.

OK
Honza

Patch

Index: src/gcc/ipa-inline-analysis.c
===================================================================
--- src.orig/gcc/ipa-inline-analysis.c
+++ src/gcc/ipa-inline-analysis.c
@@ -592,7 +592,6 @@  evaluate_conditions_for_edge (struct cgr
       struct ipa_node_params *parms_info;
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
       int i, count = ipa_get_cs_argument_count (args);
-      struct ipcp_lattice lat;
       VEC (tree, heap) *known_vals = NULL;
 
       if (e->caller->global.inlined_to)
@@ -603,9 +602,10 @@  evaluate_conditions_for_edge (struct cgr
       VEC_safe_grow_cleared (tree, heap, known_vals, count);
       for (i = 0; i < count; i++)
 	{
-	  ipa_lattice_from_jfunc (parms_info, &lat, ipa_get_ith_jump_func (args, i));
-	  if (lat.type == IPA_CONST_VALUE)
-	    VEC_replace (tree, known_vals, i, lat.constant);
+	  tree cst = ipa_cst_from_jfunc (parms_info,
+					 ipa_get_ith_jump_func (args, i));
+	  if (cst)
+	    VEC_replace (tree, known_vals, i, cst);
 	}
       clause = evaluate_conditions_for_known_args (e->callee,
 						   inline_p, known_vals);
@@ -619,31 +619,6 @@  evaluate_conditions_for_edge (struct cgr
 }
 
 
-/* Work out what conditions might be true at invocation of NODE
-   that is (future) ipa-cp clone.  */
-
-static clause_t
-evaluate_conditions_for_ipcp_clone (struct cgraph_node *node)
-{
-  struct ipa_node_params *parms_info = IPA_NODE_REF (node);
-  int i, count = ipa_get_param_count (parms_info);
-  struct ipcp_lattice *lat;
-  VEC (tree, heap) *known_vals = NULL;
-  clause_t clause;
-
-  VEC_safe_grow_cleared (tree, heap, known_vals, count);
-  for (i = 0; i < count; i++)
-    {
-      lat = ipa_get_lattice (parms_info, i);
-      if (lat->type == IPA_CONST_VALUE)
-	VEC_replace (tree, known_vals, i, lat->constant);
-    }
-  clause = evaluate_conditions_for_known_args (node, false, known_vals);
-  VEC_free (tree, heap, known_vals);
-  return clause;
-}
-
-
 /* Allocate the inline summary vector or resize it to cover all cgraph nodes. */
 
 static void
@@ -1823,18 +1798,19 @@  estimate_node_size_and_time (struct cgra
 }
 
 
-/* Estimate size and time needed to execute callee of EDGE assuming
-   that parameters known to be constant at caller of EDGE are
-   propagated.  If INLINE_P is true, it is assumed that call will
-   be inlined.  */
+/* Estimate size and time needed to execute callee of EDGE assuming that
+   parameters known to be constant at caller of EDGE are propagated.
+   KNOWN_VALs is a vector of assumed known constant values for parameters.  */
 
 void
 estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
+				   VEC (tree, heap) *known_vals,
 		                   int *ret_size, int *ret_time)
 {
-  estimate_node_size_and_time (node,
-			       evaluate_conditions_for_ipcp_clone (node),
-			       ret_size, ret_time);
+  clause_t clause;
+
+  clause = evaluate_conditions_for_known_args (node, false, known_vals);
+  estimate_node_size_and_time (node, clause, ret_size, ret_time);
 }
 
 
Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -3002,6 +3002,7 @@  ipa_update_after_lto_read (void)
 /* Given the jump function JFUNC, compute the lattice LAT that describes the
    value coming down the callsite. INFO describes the caller node so that
    pass-through jump functions can be evaluated.  */
+
 void
 ipa_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
 			 struct ipa_jump_func *jfunc)
@@ -3061,3 +3062,19 @@  ipa_lattice_from_jfunc (struct ipa_node_
   else
     lat->type = IPA_BOTTOM;
 }
+
+/* Determine whether JFUNC evaluates to a constant and if so, return it.
+   Otherwise return NULL. INFO describes the caller node so that pass-through
+   jump functions can be evaluated.  */
+
+tree
+ipa_cst_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
+{
+  struct ipcp_lattice lat;
+
+  ipa_lattice_from_jfunc (info, &lat, jfunc);
+  if (lat.type == IPA_CONST_VALUE)
+    return lat.constant;
+  else
+    return NULL_TREE;
+}
Index: src/gcc/ipa-prop.h
===================================================================
--- src.orig/gcc/ipa-prop.h
+++ src/gcc/ipa-prop.h
@@ -521,8 +521,12 @@  void ipa_prop_write_jump_functions (cgra
 void ipa_prop_read_jump_functions (void);
 void ipa_update_after_lto_read (void);
 int ipa_get_param_decl_index (struct ipa_node_params *, tree);
-void ipa_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
+void ipa_lattice_from_jfunc (struct ipa_node_params *info,
+			     struct ipcp_lattice *lat,
 			     struct ipa_jump_func *jfunc);
+tree ipa_cst_from_jfunc (struct ipa_node_params *info,
+			 struct ipa_jump_func *jfunc);
+
 
 /* From tree-sra.c:  */
 tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree,
Index: src/gcc/ipa-cp.c
===================================================================
--- src.orig/gcc/ipa-cp.c
+++ src/gcc/ipa-cp.c
@@ -1068,6 +1068,7 @@  ipcp_estimate_growth (struct cgraph_node
   int removable_args = 0;
   bool need_original
      = !cgraph_will_be_removed_from_program_if_no_direct_calls (node);
+  VEC (tree, heap) *known_vals = NULL;
   struct ipa_node_params *info;
   int i, count;
   int growth;
@@ -1085,6 +1086,7 @@  ipcp_estimate_growth (struct cgraph_node
 
   info = IPA_NODE_REF (node);
   count = ipa_get_param_count (info);
+  VEC_safe_grow_cleared (tree, heap, known_vals, count);
   if (node->local.can_change_signature)
     for (i = 0; i < count; i++)
       {
@@ -1095,14 +1097,18 @@  ipcp_estimate_growth (struct cgraph_node
 	  removable_args++;
 
 	if (lat->type == IPA_CONST_VALUE)
-	  removable_args++;
+	  {
+	    removable_args++;
+	    VEC_replace (tree, known_vals, i, lat->constant);
+	  }
       }
 
   /* We make just very simple estimate of savings for removal of operand from
      call site.  Precise cost is difficult to get, as our size metric counts
      constants and moves as free.  Generally we are looking for cases that
      small function is called very many times.  */
-  estimate_ipcp_clone_size_and_time (node, &growth, NULL);
+  estimate_ipcp_clone_size_and_time (node, known_vals, &growth, NULL);
+  VEC_free (tree, heap, known_vals);
   growth = growth
   	   - removable_args * redirectable_node_callers;
   if (growth < 0)
Index: src/gcc/ipa-inline.h
===================================================================
--- src.orig/gcc/ipa-inline.h
+++ src/gcc/ipa-inline.h
@@ -149,7 +149,9 @@  void inline_free_summary (void);
 void initialize_inline_failed (struct cgraph_edge *);
 int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
 int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
-void estimate_ipcp_clone_size_and_time (struct cgraph_node *, int *, int *);
+void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
+					VEC (tree, heap) *known_vals,
+					int *, int *);
 int do_estimate_growth (struct cgraph_node *);
 void inline_merge_summary (struct cgraph_edge *edge);
 int do_estimate_edge_growth (struct cgraph_edge *edge);