[PATCH, PR 58106] Make ipa_edge_duplication_hook cope with recursive inlining

Martin Jambor mjambor@suse.cz
Wed Aug 28 15:08:00 GMT 2013


Hi,

PR 58106 happens because the reference description duplication code
cannot deal with existence of master_nodes of recursive inlining.  It
did not put rdescs pertaining to edges going out of these nodes to the
lookup linked list (because they do not seem to be inlined into
anything) but the remapping of "not-this-edge" rdesc pointers looked
for them there - and also need to consider that the rdesc edge caller
is not inlined into anything to find them.

So this patch puts all rdesc clones to the lookup linked list and
updates the search criteria and fixes the issue.  I have looked at how
often we duplicate rdescs and we do it very rarely, 26 times in whole
SPEC 2006 at -Ofast for example.  This is expected because we create
them only constant jump functions with addresses of functions.  In
order to build a long lookup list which could potentially be a compile
time hog, such an edge would need to be inlined and we'd have to
inline its caller massively, the length grows linearly with the number
of inline clones and the number of searches as well.

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

Thanks,

Martin


2013-08-27  Martin Jambor  <mjambor@suse.cz>

	PR ipa/58106
	* ipa-prop.c (ipa_edge_duplication_hook): Always put new rdesc to the
	linked list.  When finding the correct duplicate, also consider also
	the caller in additon to its inlined_to node.

testsuite/
	* gcc.dg/ipa/pr58106.c: New test.

Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -2964,11 +2964,8 @@ ipa_edge_duplication_hook (struct cgraph
 		= (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool);
 	      dst_rdesc->cs = dst;
 	      dst_rdesc->refcount = src_rdesc->refcount;
-	      if (dst->caller->global.inlined_to)
-		{
-		  dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
-		  src_rdesc->next_duplicate = dst_rdesc;
-		}
+	      dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
+	      src_rdesc->next_duplicate = dst_rdesc;
 	      dst_jf->value.constant.rdesc = dst_rdesc;
 	    }
 	  else
@@ -2983,9 +2980,14 @@ ipa_edge_duplication_hook (struct cgraph
 	      for (dst_rdesc = src_rdesc->next_duplicate;
 		   dst_rdesc;
 		   dst_rdesc = dst_rdesc->next_duplicate)
-		if (dst_rdesc->cs->caller->global.inlined_to
-		    == dst->caller->global.inlined_to)
-		  break;
+		{
+		  struct cgraph_node *top;
+		  top = dst_rdesc->cs->caller->global.inlined_to
+		    ? dst_rdesc->cs->caller->global.inlined_to
+		    : dst_rdesc->cs->caller;
+		  if (dst->caller->global.inlined_to == top)
+		    break;
+		}
 	      gcc_assert (dst_rdesc);
 	      dst_jf->value.constant.rdesc = dst_rdesc;
 	    }
Index: src/gcc/testsuite/gcc.dg/ipa/pr58106.c
===================================================================
--- /dev/null
+++ src/gcc/testsuite/gcc.dg/ipa/pr58106.c
@@ -0,0 +1,50 @@
+/* PR 58106 testcase.  Verify that redsc chain creating and lookup works with
+   recursive inlining and master clone creation.  */
+/* { dg-do compile } */
+/* { dg-options "-O3"  } */
+
+typedef struct rtx_def *rtx;
+enum rtx_code {
+  LAST_AND_UNUSED_RTX_CODE};
+extern const char * const rtx_format[((int) LAST_AND_UNUSED_RTX_CODE)];
+struct rtx_def {
+  enum rtx_code code;
+};
+typedef int (*rtx_function) (rtx *, void *);
+extern int for_each_rtx (rtx *, rtx_function, void *);
+int
+replace_label (rtx *x, void *data)
+{
+  rtx l = *x;
+  if (l == (rtx) 0)
+    {
+ {
+   rtx new_c, new_l;
+   for_each_rtx (&new_c, replace_label, data);
+ }
+    }
+}
+static int
+for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data)
+{
+  int result, i, j;
+  const char *format = (rtx_format[(int) (((enum rtx_code) (exp)->code))]);
+  rtx *x;
+  for (; format[n] != '\0'; n++)
+    {
+      switch (format[n])
+ {
+ case 'e':
+   result = (*f) (x, data);
+     {
+       result = for_each_rtx_1 (*x, i, f, data);
+     }
+ }
+    }
+}
+int
+for_each_rtx (rtx *x, rtx_function f, void *data)
+{
+  int i;
+  return for_each_rtx_1 (*x, i, f, data);
+}





More information about the Gcc-patches mailing list