This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, PR 43812] Dissolve same_comdat_groups when localizing decls in function_and_variable_visibility


Hi,

PR 43812 is caused by the fact that ipa-cp asserts that there is no
function which has no incoming edges and yet cannot be called
indirectly or from outside the current compilation unit.  That is
normally true because we remove all unreachable functions before
IPA-CP.  However, at -fwhole-program we keep one such function because
it is in a same_comdat_group list even though
function_and_variable_visibility has made all of the functions in the
list local.  The fix is to make the function dissolve the list in the
process as well.

This patch also adds stuff to the call graph verifier that checks the
list is indeed circular, it has more than one member and that all of
the members have their fndecl in a DECL_COMDAT_GROUP (this last
property would have caught the problem).

Bootstrapped and tested on x86-64-linux without any problems.  OK fro
trunk and the 4.5 branch (without the verifier changes)?

Thanks,

Martin

2010-04-21  Martin Jambor  <mjambor@suse.cz>

	PR middle-end/43812
	* ipa.c (dissolve_same_comdat_group_list): New function.
	(function_and_variable_visibility): Call
	dissolve_same_comdat_group_list when comdat group contains external or
	newly local nodes.
	* cgraphunit.c (verify_cgraph_node): Verify that same_comdat_group
	lists are circular and that they contain only DECL_ONE_ONLY nodes.

	* testsuite/g++.dg/ipa/pr43812.C: New test.


Index: icln/gcc/ipa.c
===================================================================
--- icln.orig/gcc/ipa.c
+++ icln/gcc/ipa.c
@@ -353,6 +353,21 @@ cgraph_externally_visible_p (struct cgra
   return false;
 }
 
+/* Dissolve the same_comdat_group list in which NODE resides.  */
+
+static void
+dissolve_same_comdat_group_list (struct cgraph_node *node)
+{
+  struct cgraph_node *n = node, *next;
+  do
+    {
+      next = n->same_comdat_group;
+      n->same_comdat_group = NULL;
+      n = next;
+    }
+  while (n != node);
+}
+
 /* Mark visibility of all functions.
 
    A local function is one whose calls can occur only in the current
@@ -383,17 +398,17 @@ function_and_variable_visibility (bool w
 	 and simplifies later passes.  */
       if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
 	{
-	  struct cgraph_node *n = node, *next;
-	  do
-	    {
+#ifdef ENABLE_CHECKING
+	  struct cgraph_node *n;
+
+	  for (n = node->same_comdat_group;
+	       n != node;
+	       n = n->same_comdat_group)
 	      /* If at least one of same comdat group functions is external,
 		 all of them have to be, otherwise it is a front-end bug.  */
 	      gcc_assert (DECL_EXTERNAL (n->decl));
-	      next = n->same_comdat_group;
-	      n->same_comdat_group = NULL;
-	      n = next;
-	    }
-	  while (n != node);
+#endif
+	  dissolve_same_comdat_group_list (node);
 	}
       gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
       	          || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
@@ -409,6 +424,12 @@ function_and_variable_visibility (bool w
 	{
 	  gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
 	  cgraph_make_decl_local (node->decl);
+	  if (node->same_comdat_group)
+	    /* cgraph_externally_visible_p has already checked all other nodes
+	       in the group and they will all be made local.  We need to
+	       dissolve the group at once so that the predicate does not
+	       segfault though. */
+	    dissolve_same_comdat_group_list (node);
 	}
       node->local.local = (cgraph_only_called_directly_p (node)
 			   && node->analyzed
Index: icln/gcc/testsuite/g++.dg/ipa/pr43812.C
===================================================================
--- /dev/null
+++ icln/gcc/testsuite/g++.dg/ipa/pr43812.C
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fwhole-program -fipa-cp" } */
+
+typedef float scoord_t;
+typedef scoord_t sdist_t;
+typedef sdist_t dist_t;
+template<typename T> class TRay { };
+typedef TRay<dist_t> Ray;
+class BBox { };
+class RenderContext { };
+class RefCounted {
+public:
+    void deref () const {
+        if (--ref_count <= 0) {
+            delete this;
+        }
+    }
+    mutable int ref_count;
+};
+template<class T> class Ref {
+public:
+    ~Ref () {
+        if (obj) obj->deref ();
+    }
+    T *obj;
+};
+class Material : public RefCounted { };
+class Surface {
+public:
+    virtual ~Surface () { }
+    class IsecInfo   { };
+    virtual const IsecInfo *intersect (Ray &ray, RenderContext &context) const;
+    Ref<const Material> material;
+};
+class LocalSurface : public Surface {
+    virtual BBox bbox () const;
+};
+BBox LocalSurface::bbox () const { }
Index: icln/gcc/cgraphunit.c
===================================================================
--- icln.orig/gcc/cgraphunit.c
+++ icln/gcc/cgraphunit.c
@@ -714,6 +714,32 @@ verify_cgraph_node (struct cgraph_node *
       error ("double linked list of clones corrupted");
       error_found = true;
     }
+  if (node->same_comdat_group)
+    {
+      struct cgraph_node *n = node->same_comdat_group;
+
+      if (!DECL_ONE_ONLY (node->decl))
+	{
+	  error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
+	  error_found = true;
+	}
+      if (n == node)
+	{
+	  error ("node is alone in a comdat group");
+	  error_found = true;
+	}
+      do
+	{
+	  if (!n->same_comdat_group)
+	    {
+	      error ("same_comdat_group is not a circular list");
+	      error_found = true;
+	      break;
+	    }
+	  n = n->same_comdat_group;
+	}
+      while (n != node);
+    }
 
   if (node->analyzed && gimple_has_body_p (node->decl)
       && !TREE_ASM_WRITTEN (node->decl)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]