On Thu, 20 Mar 2014, Martin Jambor wrote:

> Hi,
> 
> On Thu, Mar 20, 2014 at 07:40:56PM +0100, Jakub Jelinek wrote:
> > On Thu, Mar 20, 2014 at 05:07:32PM +0100, Martin Jambor wrote:
> > > in the PR, verifier claims an edge is pointing to a wrong declaration
> > > even though it has successfully verified the edge multiple times
> > > before.  The reason is that symtab_remove_unreachable_nodes decides to
> > > "remove the body" of a node and also clear any information that it is
> > > an alias of another in the process (more detailed analysis in comment
> > > #9 of the bug).
> > > 
> > > In bugzilla Honza wrote that "silencing the verifier" is the way to
> > > go.  Either we can dedicate a new flag in each cgraph_node or
> > > symtab_node just for the purpose of verification or do something more
> > > hackish like the patch below which re-uses the former_clone_of field
> > > for this purpose.  Since clones are always private nodes, they should
> > > always either survive removal of unreachable nodes or be completely
> > > killed by it and should never enter the in_border zombie state.
> > > Therefore their former_clone_of must always be NULL.  So I added a new
> > > special value, error_mark_node, to mark this zombie state and taught
> > > the verifier to be happy with such nodes.
> > > 
> > > Bootstrapped and tested on x86_64-linux.  What do you think?
> > 
> > Don't we have like 22 spare bits in cgraph_node and 20 spare bits in
> > symtab_node?  I'd find it clearer if you just used a new flag to mark the
> > zombie nodes.  Though, I'll let Richard or Honza to decide, don't feel
> > strongly about it.
> > 
> 
> I guess you are right, here is the proper version which is currently
> undergoing bootstrap and testing.

I agree with Jakub, the following variant is ok.

Thanks,
Richard.

> Thanks,
> 
> Martin
> 
> 2014-03-20  Martin Jambor  <mjam...@suse.cz>
> 
>       PR ipa/59176
>       * cgraph.h (symtab_node): New flag body_removed.
>       * ipa.c (symtab_remove_unreachable_nodes): Set body_removed flag
>       when removing bodies.
>       * symtab.c (dump_symtab_base): Dump body_removed flag.
>       * cgraph.c (verify_edge_corresponds_to_fndecl): Skip nodes which
>       had their bodies removed.
> 
> testsuite/
>         * g++.dg/torture/pr59176.C: New test.
> 
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index a15b6bc..fb6880c 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -2601,8 +2601,13 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge 
> *e, tree decl)
>    node = cgraph_get_node (decl);
>  
>    /* We do not know if a node from a different partition is an alias or what 
> it
> -     aliases and therefore cannot do the former_clone_of check reliably.  */
> -  if (!node || node->in_other_partition || e->callee->in_other_partition)
> +     aliases and therefore cannot do the former_clone_of check reliably.  
> When
> +     body_removed is set, we have lost all information about what was alias 
> or
> +     thunk of and also cannot proceed.  */
> +  if (!node
> +      || node->body_removed
> +      || node->in_other_partition
> +      || e->callee->in_other_partition)
>      return false;
>    node = cgraph_function_or_thunk_node (node, NULL);
>  
> diff --git a/gcc/cgraph.h b/gcc/cgraph.h
> index 32b1ee1..59d9ce6 100644
> --- a/gcc/cgraph.h
> +++ b/gcc/cgraph.h
> @@ -91,7 +91,9 @@ public:
>    unsigned forced_by_abi : 1;
>    /* True when the name is known to be unique and thus it does not need 
> mangling.  */
>    unsigned unique_name : 1;
> -
> +  /* True when body and other characteristics have been removed by
> +     symtab_remove_unreachable_nodes. */
> +  unsigned body_removed : 1;
>  
>    /*** WHOPR Partitioning flags.
>         These flags are used at ltrans stage when only part of the callgraph 
> is
> diff --git a/gcc/ipa.c b/gcc/ipa.c
> index 572dba1..4a8c6b7 100644
> --- a/gcc/ipa.c
> +++ b/gcc/ipa.c
> @@ -484,6 +484,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, 
> FILE *file)
>           {
>             if (file)
>               fprintf (file, " %s", node->name ());
> +           node->body_removed = true;
>             node->analyzed = false;
>             node->definition = false;
>             node->cpp_implicit_alias = false;
> @@ -542,6 +543,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, 
> FILE *file)
>               fprintf (file, " %s", vnode->name ());
>             changed = true;
>           }
> +       vnode->body_removed = true;
>         vnode->definition = false;
>         vnode->analyzed = false;
>         vnode->aux = NULL;
> diff --git a/gcc/symtab.c b/gcc/symtab.c
> index 5d69803..0ce8e8e 100644
> --- a/gcc/symtab.c
> +++ b/gcc/symtab.c
> @@ -601,6 +601,8 @@ dump_symtab_base (FILE *f, symtab_node *node)
>            ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
>                                    (node->alias_target))
>            : IDENTIFIER_POINTER (node->alias_target));
> +  if (node->body_removed)
> +    fprintf (f, "\n  Body removed by symtab_remove_unreachable_nodes");
>    fprintf (f, "\n  Visibility:");
>    if (node->in_other_partition)
>      fprintf (f, " in_other_partition");
> diff --git a/gcc/testsuite/g++.dg/ipa/pr59176.C 
> b/gcc/testsuite/g++.dg/ipa/pr59176.C
> new file mode 100644
> index 0000000..d576bc3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr59176.C
> @@ -0,0 +1,41 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3" } */
> +
> +template <class> class A {
> +protected:
> +  void m_fn2();
> +  ~A() { m_fn2(); }
> +  virtual void m_fn1();
> +};
> +
> +class D : A<int> {};
> +template <class Key> void A<Key>::m_fn2() {
> +  m_fn1();
> +  m_fn1();
> +  m_fn1();
> +}
> +
> +#pragma interface
> +class B {
> +  D m_cellsAlreadyProcessed;
> +  D m_cellsNotToProcess;
> +
> +public:
> +  virtual ~B() {}
> +  void m_fn1();
> +};
> +
> +class C {
> +  unsigned long m_fn1();
> +  B m_fn2();
> +  unsigned long m_fn3();
> +};
> +unsigned long C::m_fn1() {
> +CellHierarchy:
> +  m_fn2().m_fn1();
> +}
> +
> +unsigned long C::m_fn3() {
> +CellHierarchy:
> +  m_fn2().m_fn1();
> +}
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer

Reply via email to