From eb20b7788fe0a9f43657668207677833e3881741 Mon Sep 17 00:00:00 2001
From: Martin Jambor <mjambor@suse.cz>
Date: Wed, 21 Nov 2012 18:13:48 +0100
Subject: [PATCH] ipa-prop.h (struct ipa_node_params): Rename
 clone_for_all_contexts to do_clone_for_all_contexts.

2012-11-21  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (struct ipa_node_params): Rename clone_for_all_contexts to
	do_clone_for_all_contexts.  Update all uses.  New flag
	is_all_contexts_clone.
	* ipa-cp.c (cgraph_edge_brings_value_p): Also consider the case when cs
	leads to the clone for all contexts.
	(perhaps_add_new_callers): Likewise.
	(decide_whether_version_node): Remove bogus !plats->aggs test.  Set
	is_all_contexts_clone when cloning for all contexts.

	* testsuite/gcc.dg/ipa/ipcp-agg-7.c: New test.
	* testsuite/gcc.dg/ipa/ipcp-agg-8.c: Likewise.

From-SVN: r193701
---
 gcc/ChangeLog                         | 11 ++++++
 gcc/ipa-cp.c                          | 26 +++++++------
 gcc/ipa-prop.h                        |  4 +-
 gcc/testsuite/ChangeLog               |  5 +++
 gcc/testsuite/gcc.dg/ipa/ipcp-agg-7.c | 54 +++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/ipa/ipcp-agg-8.c | 52 ++++++++++++++++++++++++++
 6 files changed, 140 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/ipcp-agg-7.c
 create mode 100644 gcc/testsuite/gcc.dg/ipa/ipcp-agg-8.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 58f69d1747cf..7853c37ff140 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2012-11-21  Martin Jambor  <mjambor@suse.cz>
+
+	* ipa-prop.h (struct ipa_node_params): Rename clone_for_all_contexts to
+	do_clone_for_all_contexts.  Update all uses.  New flag
+	is_all_contexts_clone.
+	* ipa-cp.c (cgraph_edge_brings_value_p): Also consider the case when cs
+	leads to the clone for all contexts.
+	(perhaps_add_new_callers): Likewise.
+	(decide_whether_version_node): Remove bogus !plats->aggs test.  Set
+	is_all_contexts_clone when cloning for all contexts.
+
 2012-11-21  Martin Jambor  <mjambor@suse.cz>
 
 	PR tree-optimization/55260
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 16cf990dc671..12e199d2a533 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1828,7 +1828,7 @@ estimate_local_effects (struct cgraph_node *node)
       if (size <= 0
 	  || cgraph_will_be_removed_from_program_if_no_direct_calls (node))
 	{
-	  info->clone_for_all_contexts = true;
+	  info->do_clone_for_all_contexts = true;
 	  base_time = time;
 
 	  if (dump_file)
@@ -1841,7 +1841,7 @@ estimate_local_effects (struct cgraph_node *node)
 	{
 	  if (size + overall_size <= max_new_size)
 	    {
-	      info->clone_for_all_contexts = true;
+	      info->do_clone_for_all_contexts = true;
 	      base_time = time;
 	      overall_size += size;
 
@@ -2312,8 +2312,9 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs,
 			    struct ipcp_value_source *src)
 {
   struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+  struct ipa_node_params *dst_info = IPA_NODE_REF (cs->callee);
 
-  if (IPA_NODE_REF (cs->callee)->ipcp_orig_node
+  if ((dst_info->ipcp_orig_node && !dst_info->is_all_contexts_clone)
       || caller_info->node_dead)
     return false;
   if (!src->val)
@@ -3175,8 +3176,9 @@ perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val)
       while (cs)
 	{
 	  enum availability availability;
-
-	  if (cgraph_function_node (cs->callee, &availability) == node
+	  struct cgraph_node *dst = cgraph_function_node (cs->callee,
+							  &availability);
+	  if ((dst == node || IPA_NODE_REF (dst)->is_all_contexts_clone)
 	      && availability > AVAIL_OVERWRITABLE
 	      && cgraph_edge_brings_value_p (cs, src))
 	    {
@@ -3335,8 +3337,8 @@ decide_whether_version_node (struct cgraph_node *node)
 	     cgraph_node_name (node), node->uid);
 
   gather_context_independent_values (info, &known_csts, &known_binfos,
-				     info->clone_for_all_contexts ? &known_aggs
-				     : NULL, NULL);
+				  info->do_clone_for_all_contexts ? &known_aggs
+				  : NULL, NULL);
 
   for (i = 0; i < count ;i++)
     {
@@ -3351,7 +3353,7 @@ decide_whether_version_node (struct cgraph_node *node)
 	  ret |= decide_about_value (node, i, -1, val, known_csts,
 				     known_binfos);
 
-      if (!plats->aggs_bottom || !plats->aggs)
+      if (!plats->aggs_bottom)
 	{
 	  struct ipcp_agg_lattice *aglat;
 	  struct ipcp_value *val;
@@ -3368,8 +3370,9 @@ decide_whether_version_node (struct cgraph_node *node)
         info = IPA_NODE_REF (node);
     }
 
-  if (info->clone_for_all_contexts)
+  if (info->do_clone_for_all_contexts)
     {
+      struct cgraph_node *clone;
       vec<cgraph_edge_p> callers;
 
       if (dump_file)
@@ -3379,11 +3382,12 @@ decide_whether_version_node (struct cgraph_node *node)
 
       callers = collect_callers_of_node (node);
       move_binfos_to_values (known_csts, known_binfos);
-      create_specialized_node (node, known_csts,
+      clone = create_specialized_node (node, known_csts,
 			       known_aggs_to_agg_replacement_list (known_aggs),
 			       callers);
       info = IPA_NODE_REF (node);
-      info->clone_for_all_contexts = false;
+      info->do_clone_for_all_contexts = false;
+      IPA_NODE_REF (clone)->is_all_contexts_clone = true;
       ret = true;
     }
   else
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 1d0a9927fd03..95442dc5582c 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -328,7 +328,9 @@ struct ipa_node_params
   unsigned node_enqueued : 1;
   /* Whether we should create a specialized version based on values that are
      known to be constant in all contexts.  */
-  unsigned clone_for_all_contexts : 1;
+  unsigned do_clone_for_all_contexts : 1;
+  /* Set if this is an IPA-CP clone for all contexts.  */
+  unsigned is_all_contexts_clone : 1;
   /* Node has been completely replaced by clones and will be removed after
      ipa-cp is finished.  */
   unsigned node_dead : 1;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5def603e5353..3a12c817764c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-11-21  Martin Jambor  <mjambor@suse.cz>
+
+	* gcc.dg/ipa/ipcp-agg-7.c: New test.
+	* gcc.dg/ipa/ipcp-agg-8.c: Likewise.
+
 2012-11-21  Martin Jambor  <mjambor@suse.cz>
 
 	PR tree-optimization/55260
diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-7.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-7.c
new file mode 100644
index 000000000000..e85ca1a9d092
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-7.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim"  } */
+/* { dg-add-options bind_pic_locally } */
+
+struct S
+{
+  int a, b, c;
+};
+
+void *blah(int, void *);
+
+static void __attribute__ ((noinline)) foo (int x, int z, struct S *p);
+
+static void __attribute__ ((noinline))
+bar (int x, int z, struct S *p)
+{
+  foo (z, x, p);
+}
+
+static void __attribute__ ((noinline))
+foo (int x, int z, struct S *p)
+{
+  int i, c = p->c;
+  int b = p->b - z;
+  void *v = (void *) p;
+
+  if (z)
+    {
+      z--;
+      bar (z, x, p);
+    }
+  for (i = 0; i< c; i++)
+    v = blah(b + x + i, v);
+}
+
+void
+entry (int c)
+{
+  struct S s;
+  int i;
+
+  for (i = 0; i<c; i++)
+    {
+      s.a = c;
+      s.b = 64;
+      s.c = 32;
+      foo (4, i, &s);
+    }
+}
+/* { dg-final { scan-ipa-dump-times "Clone of bar" 1 "cp" } } */
+/* { dg-final { scan-ipa-dump-times "Clone of foo" 1 "cp" } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-8.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-8.c
new file mode 100644
index 000000000000..5014ffd3b761
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-8.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-ipa-sra -fdump-tree-optimized-slim"  } */
+/* { dg-add-options bind_pic_locally } */
+
+struct S
+{
+  int a, b, c;
+};
+
+void *blah(int, void *);
+
+static void __attribute__ ((noinline)) foo (int x, int z, struct S *p);
+
+static void __attribute__ ((noinline))
+bar (int x, int z, struct S *p)
+{
+  p->b = 0;
+  foo (z, x, p);
+}
+
+static void __attribute__ ((noinline))
+foo (int x, int z, struct S *p)
+{
+  int i, c = p->c;
+  int b = p->b - z;
+  void *v = (void *) p;
+
+  if (z)
+    {
+      z--;
+      bar (z, x, p);
+    }
+  for (i = 0; i< c; i++)
+    v = blah(b + x + i, v);
+}
+
+void
+entry (int c)
+{
+  struct S s;
+  int i;
+
+  for (i = 0; i<c; i++)
+    {
+      s.a = c;
+      s.b = 64;
+      s.c = 32;
+      foo (4, i, &s);
+    }
+}
+/* { dg-final { scan-tree-dump "->b;" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
-- 
GitLab