Patchwork Let IPA-CP make direct callgraph edges it can

login
register
mail settings
Submitter Martin Jambor
Date Aug. 4, 2010, 7:14 p.m.
Message ID <20100804191440.GB6199@virgil.arch.suse.de>
Download mbox | patch
Permalink /patch/60885/
State New
Headers show

Comments

Martin Jambor - Aug. 4, 2010, 7:14 p.m.
Hi,

this patch replaces a TODO in IPA-CP saying that if after discovering
constants we should create (actually make direct) any call graph edges
that the inliner can then make use of.  This patch does exactly that
by traversing the indirect edges in a way that is quite similar to
(but a bit simpler than) ipa-prop.c.  

It then makes sure it does not redirect any of these newly direct
edges because they have not been there when analysis was performed and
so that we do not run into issues like PR 42231.  (This then raises a
question whether the flag indirect_inlining_edge should be renamed or
split into two distinct flags.  I have not made up my mind yet but one
of these things should be made solely for the sake of clarity, it
works just as intended now.)

I have bootstrapped and tested this patch on top of the ipa-cp
devirtualization one I have posted a while ago on x86-64-linux without
any problems.  OK for trunk eventually?

Thanks,

Martin


2010-08-03  Martin Jambor  <mjambor@suse.cz>

	* ipa-cp.c (ipcp_discover_new_direct_edges): New function.
	(ipcp_insert_stage): Redirect only edges not flagged with
	indirect_inlining_edge.  Call ipcp_discover_new_direct_edges for all
	discovered constants.

	* testsuite/gcc.dg/ipa/ipcp-ii-1.c: New test.
	* testsuite/g++.dg/ipa/ipcp-ivi-1.C: Likewise.
Jan Hubicka - Aug. 5, 2010, 8:29 a.m.
> Hi,
> 
> this patch replaces a TODO in IPA-CP saying that if after discovering
> constants we should create (actually make direct) any call graph edges
> that the inliner can then make use of.  This patch does exactly that
> by traversing the indirect edges in a way that is quite similar to
> (but a bit simpler than) ipa-prop.c.  
> 
> It then makes sure it does not redirect any of these newly direct
> edges because they have not been there when analysis was performed and
> so that we do not run into issues like PR 42231.  (This then raises a
> question whether the flag indirect_inlining_edge should be renamed or
> split into two distinct flags.  I have not made up my mind yet but one
> of these things should be made solely for the sake of clarity, it
> works just as intended now.)
> 
> I have bootstrapped and tested this patch on top of the ipa-cp
> devirtualization one I have posted a while ago on x86-64-linux without
> any problems.  OK for trunk eventually?
> 
> Thanks,
> 
> Martin
> 
> 
> 2010-08-03  Martin Jambor  <mjambor@suse.cz>
> 
> 	* ipa-cp.c (ipcp_discover_new_direct_edges): New function.
> 	(ipcp_insert_stage): Redirect only edges not flagged with
> 	indirect_inlining_edge.  Call ipcp_discover_new_direct_edges for all
> 	discovered constants.
OK,
thanks!

Honza
H.J. Lu - Oct. 30, 2010, 1:38 p.m.
On Wed, Aug 4, 2010 at 12:14 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> this patch replaces a TODO in IPA-CP saying that if after discovering
> constants we should create (actually make direct) any call graph edges
> that the inliner can then make use of.  This patch does exactly that
> by traversing the indirect edges in a way that is quite similar to
> (but a bit simpler than) ipa-prop.c.
>
> It then makes sure it does not redirect any of these newly direct
> edges because they have not been there when analysis was performed and
> so that we do not run into issues like PR 42231.  (This then raises a
> question whether the flag indirect_inlining_edge should be renamed or
> split into two distinct flags.  I have not made up my mind yet but one
> of these things should be made solely for the sake of clarity, it
> works just as intended now.)
>
> I have bootstrapped and tested this patch on top of the ipa-cp
> devirtualization one I have posted a while ago on x86-64-linux without
> any problems.  OK for trunk eventually?
>
> Thanks,
>
> Martin
>
>
> 2010-08-03  Martin Jambor  <mjambor@suse.cz>
>
>        * ipa-cp.c (ipcp_discover_new_direct_edges): New function.
>        (ipcp_insert_stage): Redirect only edges not flagged with
>        indirect_inlining_edge.  Call ipcp_discover_new_direct_edges for all
>        discovered constants.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46242

Patch

Index: icln/gcc/ipa-cp.c
===================================================================
--- icln.orig/gcc/ipa-cp.c
+++ icln/gcc/ipa-cp.c
@@ -1269,6 +1269,49 @@  ipcp_const_param_count (struct cgraph_no
   return const_param;
 }
 
+/* Given that a formal parameter of NODE given by INDEX is known to be constant
+   CST, try to find any indirect edges that can be made direct and make them
+   so.  Note that INDEX is the number the parameter at the time of analyzing
+   parameter uses and parameter removals should not be considered for it.  (In
+   fact, the parameter itself has just been removed.)  */
+
+static void
+ipcp_discover_new_direct_edges (struct cgraph_node *node, int index, tree cst)
+{
+  struct cgraph_edge *ie, *next_ie;
+
+  for (ie = node->indirect_calls; ie; ie = next_ie)
+    {
+      struct cgraph_indirect_call_info *ici = ie->indirect_info;
+
+      next_ie = ie->next_callee;
+      if (ici->param_index != index)
+	continue;
+
+      if (ici->polymorphic)
+	{
+	  tree binfo;
+	  HOST_WIDE_INT token;
+
+	  if (TREE_CODE (cst) != ADDR_EXPR)
+	    continue;
+
+	  binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0),
+						 NULL_TREE);
+	  if (!binfo)
+	    continue;
+	  gcc_assert (ie->indirect_info->anc_offset == 0);
+	  token = ie->indirect_info->otr_token;
+	  cst = gimple_fold_obj_type_ref_known_binfo (token, binfo);
+	  if (!cst)
+	    continue;
+	}
+
+      ipa_make_edge_direct_to_target (ie, cst);
+    }
+}
+
+
 /* Propagate the constant parameters found by ipcp_iterate_stage()
    to the function's code.  */
 static void
@@ -1390,7 +1433,8 @@  ipcp_insert_stage (void)
 	node_callers++;
       redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers);
       for (cs = node->callers; cs != NULL; cs = cs->next_caller)
-	VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
+	if (!cs->indirect_inlining_edge)
+	  VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
 
       /* Redirecting all the callers of the node to the
          new versioned node.  */
@@ -1410,7 +1454,13 @@  ipcp_insert_stage (void)
 		 cgraph_node_name (node), (int)growth, (int)new_size);
       ipcp_init_cloned_node (node, node1);
 
-      /* TODO: We can use indirect inlning info to produce new calls.  */
+      info = IPA_NODE_REF (node);
+      for (i = 0; i < count; i++)
+	{
+	  struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
+	  if (lat->type == IPA_CONST_VALUE)
+	    ipcp_discover_new_direct_edges (node1, i, lat->constant);
+        }
 
       if (dump_file)
 	dump_function_to_file (node1->decl, dump_file, dump_flags);
Index: icln/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C
===================================================================
--- /dev/null
+++ icln/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C
@@ -0,0 +1,65 @@ 
+/* Verify that simple virtual calls are inlined even without early
+   inlining.  */
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining"  } */
+
+extern "C" void abort (void);
+
+class A
+{
+public:
+  int data;
+  virtual int foo (int i);
+};
+
+class B : public A
+{
+public:
+  virtual int foo (int i);
+};
+
+class C : public A
+{
+public:
+  virtual int foo (int i);
+};
+
+int A::foo (int i)
+{
+  return i + 1;
+}
+
+int B::foo (int i)
+{
+  return i + 2;
+}
+
+int C::foo (int i)
+{
+  return i + 3;
+}
+
+int __attribute__ ((noinline)) middleman (class A *obj, int i)
+{
+  return obj->foo (i);
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+class B b;
+
+int main (int argc, char *argv[])
+{
+  int i;
+
+  for (i = 0; i < get_input (); i++)
+    if (middleman (&b, get_input ()) != 3)
+      abort ();
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int.*middleman"  "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: icln/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c
===================================================================
--- /dev/null
+++ icln/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c
@@ -0,0 +1,34 @@ 
+/* Verify that simple indirect calls are inlined even without early
+   inlining..  */
+/* { dg-do compile } */
+/* { dg-options "-O3 -c -fdump-ipa-inline -fno-early-inlining"  } */
+
+extern void non_existent(int);
+extern void non_existent(int);
+
+static void hooray ()
+{
+  non_existent (1);
+}
+
+static void  __attribute__ ((noinline)) hiphip (void (*f)())
+{
+  f ();
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+int main (int argc, int *argv[])
+{
+  int i;
+
+  for (i = 0; i < get_input (); i++)
+    hiphip (hooray);
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in hiphip.constprop"  "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */