[PATCH, PR 43812] Dissolve same_comdat_groups when localizing decls in function_and_variable_visibility
Martin Jambor
mjambor@suse.cz
Tue Apr 27 10:12:00 GMT 2010
Hi,
the patch below was approved by Honza on IRC and so I committed it as
revision 158777. I intend to commit it to the 4.5 branch early next
week - should I omit the additions to the verifier?
Thanks,
Martin
On Wed, Apr 21, 2010 at 06:17:56PM +0200, Martin Jambor wrote:
> 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)
More information about the Gcc-patches
mailing list