public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Teach IPA-CP to make calls direct based on contents of aggregates
@ 2013-03-24  0:15 Martin Jambor
  2013-03-24 11:09 ` Jan Hubicka
  0 siblings, 1 reply; 2+ messages in thread
From: Martin Jambor @ 2013-03-24  0:15 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jan Hubicka

Hi,

this is a bit of aggregate IPA-CP that I missed to submit in last
stage1 and that makes indirect call graph edges from IPA-CP clones
direct if they call a known address loaded from an aggregate
parameter.

The reason why ipa_get_indirect_edge_target is split into two is that
unlike in the inlining case, this one has to understand the
description of known aggregate values in clones which are different
from aggregate jump functions (they are quite simpler).  Otherwise the
patch is hopefully quite straightforward.

Bootstrapped and tested on x86_64-linux, OK for trunk?

Thanks,

Martin
 

2013-03-19  Martin Jambor  <mjambor@suse.cz>

	* ipa-cp.c (ipa_get_indirect_edge_target): Renamed to
	ipa_get_indirect_edge_target_1, added parameter agg_reps and ability to
	process it.
	(ipa_get_indirect_edge_target): New function.
	(devirtualization_time_bonus): New parameter known_aggs, pass it to
	ipa_get_indirect_edge_target.  Update all callers.
	(ipcp_discover_new_direct_edges): New parameter aggvals.  Pass it to
	ipa_get_indirect_edge_target_1 instead of calling
	ipa_get_indirect_edge_target.
	(create_specialized_node): Pass aggvlas to
	ipcp_discover_new_direct_edges.

testsuite/
	* gcc.dg/ipa/ipcp-agg-9.c: New test.

Index: src/gcc/ipa-cp.c
===================================================================
--- src.orig/gcc/ipa-cp.c
+++ src/gcc/ipa-cp.c
@@ -1477,14 +1477,16 @@ propagate_constants_accross_call (struct
 }
 
 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
-   (which can contain both constants and binfos) or KNOWN_BINFOS (which can be
-   NULL) return the destination.  */
+   (which can contain both constants and binfos), KNOWN_BINFOS, KNOWN_AGGS or
+   AGG_REPS return the destination.  The latter three can be NULL.  If AGG_REPS
+   is not NULL, KNOWN_AGGS is ignored.  */
 
-tree
-ipa_get_indirect_edge_target (struct cgraph_edge *ie,
-			      vec<tree> known_vals,
-			      vec<tree> known_binfos,
-			      vec<ipa_agg_jump_function_p> known_aggs)
+static tree
+ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
+				vec<tree> known_vals,
+				vec<tree> known_binfos,
+				vec<ipa_agg_jump_function_p> known_aggs,
+				struct ipa_agg_replacement_value *agg_reps)
 {
   int param_index = ie->indirect_info->param_index;
   HOST_WIDE_INT token, anc_offset;
@@ -1500,8 +1502,21 @@ ipa_get_indirect_edge_target (struct cgr
 
       if (ie->indirect_info->agg_contents)
 	{
-	  if (known_aggs.length ()
-	      > (unsigned int) param_index)
+	  if (agg_reps)
+	    {
+	      t = NULL;
+	      while (agg_reps)
+		{
+		  if (agg_reps->index == param_index
+		      && agg_reps->offset == ie->indirect_info->offset)
+		    {
+		      t = agg_reps->value;
+		      break;
+		    }
+		  agg_reps = agg_reps->next;
+		}
+	    }
+	  else if (known_aggs.length () > (unsigned int) param_index)
 	    {
 	      struct ipa_agg_jump_function *agg;
 	      agg = known_aggs[param_index];
@@ -1556,13 +1571,29 @@ ipa_get_indirect_edge_target (struct cgr
     }
 }
 
+
+/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
+   (which can contain both constants and binfos), KNOWN_BINFOS (which can be
+   NULL) or KNOWN_AGGS (which also can be NULL) return the destination.  */
+
+tree
+ipa_get_indirect_edge_target (struct cgraph_edge *ie,
+			      vec<tree> known_vals,
+			      vec<tree> known_binfos,
+			      vec<ipa_agg_jump_function_p> known_aggs)
+{
+  return ipa_get_indirect_edge_target_1 (ie, known_vals, known_binfos,
+					 known_aggs, NULL);
+}
+
 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS
    and KNOWN_BINFOS.  */
 
 static int
 devirtualization_time_bonus (struct cgraph_node *node,
 			     vec<tree> known_csts,
-			     vec<tree> known_binfos)
+			     vec<tree> known_binfos,
+			     vec<ipa_agg_jump_function_p> known_aggs)
 {
   struct cgraph_edge *ie;
   int res = 0;
@@ -1574,7 +1605,7 @@ devirtualization_time_bonus (struct cgra
       tree target;
 
       target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos,
-					vNULL);
+					     known_aggs);
       if (!target)
 	continue;
 
@@ -1818,7 +1849,8 @@ estimate_local_effects (struct cgraph_no
       cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false);
       estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
 					 known_aggs_ptrs, &size, &time, &hints);
-      time -= devirtualization_time_bonus (node, known_csts, known_binfos);
+      time -= devirtualization_time_bonus (node, known_csts, known_binfos,
+					   known_aggs_ptrs);
       time -= hint_time_bonus (hints);
       time -= removable_params_cost;
       size -= stats.n_calls * removable_params_cost;
@@ -1895,7 +1927,8 @@ estimate_local_effects (struct cgraph_no
 					     known_aggs_ptrs, &size, &time,
 					     &hints);
 	  time_benefit = base_time - time
-	    + devirtualization_time_bonus (node, known_csts, known_binfos)
+	    + devirtualization_time_bonus (node, known_csts, known_binfos,
+					   known_aggs_ptrs)
 	    + hint_time_bonus (hints)
 	    + removable_params_cost + emc;
 
@@ -1957,7 +1990,8 @@ estimate_local_effects (struct cgraph_no
 						 known_aggs_ptrs, &size, &time,
 						 &hints);
 	      time_benefit = base_time - time
-		+ devirtualization_time_bonus (node, known_csts, known_binfos)
+		+ devirtualization_time_bonus (node, known_csts, known_binfos,
+					       known_aggs_ptrs)
 		+ hint_time_bonus (hints);
 	      gcc_checking_assert (size >=0);
 	      if (size == 0)
@@ -2240,7 +2274,8 @@ ipcp_propagate_stage (struct topo_info *
 
 static void
 ipcp_discover_new_direct_edges (struct cgraph_node *node,
-				vec<tree> known_vals)
+				vec<tree> known_vals,
+				struct ipa_agg_replacement_value *aggvals)
 {
   struct cgraph_edge *ie, *next_ie;
   bool found = false;
@@ -2250,7 +2285,8 @@ ipcp_discover_new_direct_edges (struct c
       tree target;
 
       next_ie = ie->next_callee;
-      target = ipa_get_indirect_edge_target (ie, known_vals, vNULL, vNULL);
+      target = ipa_get_indirect_edge_target_1 (ie, known_vals, vNULL, vNULL,
+					       aggvals);
       if (target)
 	{
 	  ipa_make_edge_direct_to_target (ie, target);
@@ -2660,7 +2696,7 @@ create_specialized_node (struct cgraph_n
   new_info->ipcp_orig_node = node;
   new_info->known_vals = known_vals;
 
-  ipcp_discover_new_direct_edges (new_node, known_vals);
+  ipcp_discover_new_direct_edges (new_node, known_vals, aggvals);
 
   callers.release ();
   return new_node;
Index: src/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c
===================================================================
--- /dev/null
+++ src/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c
@@ -0,0 +1,45 @@
+/* Verify that IPA-CP can make edges direct based on aggregate contents.  */
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp -fdump-ipa-inline"  } */
+
+struct S
+{
+  int i;
+  void (*f)(struct S *);
+  unsigned u;
+};
+
+struct U
+{
+  struct U *next;
+  struct S s;
+  short a[8];
+};
+
+extern void non_existent(struct S *p, int);
+
+static void hooray1 (struct S *p)
+{
+  non_existent (p, 1);
+}
+
+static __attribute__ ((noinline))
+void hiphip1 (struct S *p)
+{
+  p->f (p);
+}
+
+int test1 (void)
+{
+  struct S s;
+  s.i = 1234;
+  s.f = hooray1;
+  s.u = 1001;
+  hiphip1 (&s);
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "ipa-prop: Discovered an indirect call to a known target"  "cp"  } } */
+/* { dg-final { scan-ipa-dump "hooray1\[^\\n\]*inline copy in hiphip1"  "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Teach IPA-CP to make calls direct based on contents of aggregates
  2013-03-24  0:15 [PATCH] Teach IPA-CP to make calls direct based on contents of aggregates Martin Jambor
@ 2013-03-24 11:09 ` Jan Hubicka
  0 siblings, 0 replies; 2+ messages in thread
From: Jan Hubicka @ 2013-03-24 11:09 UTC (permalink / raw)
  To: GCC Patches, Jan Hubicka

> 
> The reason why ipa_get_indirect_edge_target is split into two is that
> unlike in the inlining case, this one has to understand the
> description of known aggregate values in clones which are different
> from aggregate jump functions (they are quite simpler).  Otherwise the
> patch is hopefully quite straightforward.

Hmm, perhaps we can commonize it a bit more?
> 
> Bootstrapped and tested on x86_64-linux, OK for trunk?

I would also suggest adding code translating calls to known constant (NULL or integer_cst) into
__builtin_trap / __bulitin_unreachable (based on Richi's preferences).  It should help code quality
(since relatively few calls are like that on Mozilla) and also it will make us to notice where
we propagate complette garbage - I still do not know of those obviously bogus calls come from
impossible type conversions (so we read past vtable) or because of some bug.
> 
> 2013-03-19  Martin Jambor  <mjambor@suse.cz>
> 
> 	* ipa-cp.c (ipa_get_indirect_edge_target): Renamed to
> 	ipa_get_indirect_edge_target_1, added parameter agg_reps and ability to
> 	process it.
> 	(ipa_get_indirect_edge_target): New function.
> 	(devirtualization_time_bonus): New parameter known_aggs, pass it to
> 	ipa_get_indirect_edge_target.  Update all callers.
> 	(ipcp_discover_new_direct_edges): New parameter aggvals.  Pass it to
> 	ipa_get_indirect_edge_target_1 instead of calling
> 	ipa_get_indirect_edge_target.
> 	(create_specialized_node): Pass aggvlas to
> 	ipcp_discover_new_direct_edges.
> 
> testsuite/
> 	* gcc.dg/ipa/ipcp-agg-9.c: New test.
> 
OK,
thanks

Honza

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-03-24 11:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-24  0:15 [PATCH] Teach IPA-CP to make calls direct based on contents of aggregates Martin Jambor
2013-03-24 11:09 ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).