[PATCH, PR 61986] Produce aggregate replacement nodes in ascending order of offsets

Martin Jambor mjambor@suse.cz
Wed Sep 3 08:47:00 GMT 2014


Hi,

intersecting known aggregate values coming along a given set of call
graph edges requires that all lists are in ascending order of offsets
in order to perform it in only one sweep through each of them.
However, aggregate replacement nodes are produced in exactly the
opposite order.  This makes us miss an item in the intersection and
assert later.  The ordering is fixed by the following patch.

Bootstrapped and tested on x86_64-linux.  OK for the trunk and all
problematic branches (4.9 for sure, I am not sure about 4.8 at this
moment).

Thanks,

Martin


2014-09-02  Martin Jambor  <mjambor@suse.cz>

	PR ipa/61986
	* ipa-cp.c (find_aggregate_values_for_callers_subset): Chain
	created replacements in ascending order of offsets.
	(known_aggs_to_agg_replacement_list): Likewise.

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

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 44d4c9a..58121d4 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -3146,7 +3146,8 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
 					  vec<cgraph_edge *> callers)
 {
   struct ipa_node_params *dest_info = IPA_NODE_REF (node);
-  struct ipa_agg_replacement_value *res = NULL;
+  struct ipa_agg_replacement_value *res;
+  struct ipa_agg_replacement_value **tail = &res;
   struct cgraph_edge *cs;
   int i, j, count = ipa_get_param_count (dest_info);
 
@@ -3190,14 +3191,15 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
 	  v->offset = item->offset;
 	  v->value = item->value;
 	  v->by_ref = plats->aggs_by_ref;
-	  v->next = res;
-	  res = v;
+	  *tail = v;
+	  tail = &v->next;
 	}
 
     next_param:
       if (inter.exists ())
 	inter.release ();
     }
+  *tail = NULL;
   return res;
 }
 
@@ -3206,7 +3208,8 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
 static struct ipa_agg_replacement_value *
 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
 {
-  struct ipa_agg_replacement_value *res = NULL;
+  struct ipa_agg_replacement_value *res;
+  struct ipa_agg_replacement_value **tail = &res;
   struct ipa_agg_jump_function *aggjf;
   struct ipa_agg_jf_item *item;
   int i, j;
@@ -3220,9 +3223,10 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
 	v->offset = item->offset;
 	v->value = item->value;
 	v->by_ref = aggjf->by_ref;
-	v->next = res;
-	res = v;
+	*tail = v;
+	tail = &v->next;
       }
+  *tail = NULL;
   return res;
 }
 
diff --git a/gcc/testsuite/gcc.dg/ipa/pr61986.c b/gcc/testsuite/gcc.dg/ipa/pr61986.c
new file mode 100644
index 0000000..8d2f658
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr61986.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+int a, b, c;
+
+struct S
+{
+  int f0;
+  int f1;
+} d;
+
+static int fn2 (struct S);
+void fn3 (struct S);
+
+void
+fn1 (struct S p)
+{
+  struct S h = { 0, 0 };
+  fn3 (p);
+  fn2 (h);
+}
+
+int
+fn2 (struct S p)
+{
+  struct S j = { 0, 0 };
+  fn3 (p);
+  fn2 (j);
+  return 0;
+}
+
+void
+fn3 (struct S p)
+{
+  for (; b; a++)
+    c = p.f0;
+  fn1 (d);
+}
+
+void
+fn4 ()
+{
+  for (;;)
+    {
+      struct S f = { 0, 0 };
+      fn1 (f);
+    }
+}



More information about the Gcc-patches mailing list