Re: Fix ICE in initialize_node_lattices

2016-03-10 Thread Jan Hubicka
> On Thu, Mar 10, 2016 at 05:12:59PM +0100, Jan Hubicka wrote:
> > --- testsuite/g++.dg/lto/pr69589_0.C(revision 0)
> > +++ testsuite/g++.dg/lto/pr69589_0.C(working copy)
> > @@ -0,0 +1,26 @@
> > +// { dg-lto-do link }
> > +// { dg-lto-options "-O2 -rdynamic" } 
> 
> Shouldn't this have
> // { dg-require-visibility "hidden" }
> when it uses the visibility push(hidden) ?

You are right, I will add it to the testcase.

Honza
> 
> > +// { dg-extra-ld-options "-r -nostdlib" }
> > +#pragma GCC visibility push(hidden)
> > +struct A { int [] (long); };
> > +template  struct B;
> > +template  >
> > +using Z = int;
> > +template  struct C;
> > +struct S {
> > +  int e;
> > +  virtual ~S () {}
> > +};
> > +struct D : S {
> > +  A a;
> > +  long i;
> > +  D() { { e ? [i] : nullptr; } }
> > +};
> > +template <>
> > +struct C { Z m8 () const; };
> > +Z
> > +C::m8 () const
> > +{
> > +  D ();
> > +}
> 
>   Jakub


Re: Fix ICE in initialize_node_lattices

2016-03-10 Thread Jakub Jelinek
On Thu, Mar 10, 2016 at 05:12:59PM +0100, Jan Hubicka wrote:
> --- testsuite/g++.dg/lto/pr69589_0.C  (revision 0)
> +++ testsuite/g++.dg/lto/pr69589_0.C  (working copy)
> @@ -0,0 +1,26 @@
> +// { dg-lto-do link }
> +// { dg-lto-options "-O2 -rdynamic" } 

Shouldn't this have
// { dg-require-visibility "hidden" }
when it uses the visibility push(hidden) ?

> +// { dg-extra-ld-options "-r -nostdlib" }
> +#pragma GCC visibility push(hidden)
> +struct A { int [] (long); };
> +template  struct B;
> +template  >
> +using Z = int;
> +template  struct C;
> +struct S {
> +  int e;
> +  virtual ~S () {}
> +};
> +struct D : S {
> +  A a;
> +  long i;
> +  D() { { e ? [i] : nullptr; } }
> +};
> +template <>
> +struct C { Z m8 () const; };
> +Z
> +C::m8 () const
> +{
> +  D ();
> +}

Jakub


Fix ICE in initialize_node_lattices

2016-03-10 Thread Jan Hubicka
Hi,
this patch fixes ICE in ipa-cp that detects local function that is dead.
The issue is that virutal functions may have no address taken but still may
be virtual call targets.  This patch makes remove_unreachable_nodes to handle
this and not mark them local (since they are not)

Honza

* cgraph.c (cgraph_node::dump): Dump split_part and 
indirect_call_target.
* cgraph.h (cgraph_node): Add indirect_call_target flag.
* ipa.c (has_addr_references_p): Cleanup.
(is_indirect_call_target_p): New.
(walk_polymorphic_call_targets): Do not mark virtuals that may be
called indirectly as local.
(symbol_table::remove_unreachable_nodes): Compute indirect_call_target.

PR lto/69589
* g++.dg/lto/pr69589_0.C: New testcase
* g++.dg/lto/pr69589_1.C: New testcase
Index: cgraph.c
===
--- cgraph.c(revision 234108)
+++ cgraph.c(working copy)
@@ -2061,6 +2061,10 @@ cgraph_node::dump (FILE *f)
 fprintf (f, " icf_merged");
   if (merged_comdat)
 fprintf (f, " merged_comdat");
+  if (split_part)
+fprintf (f, " split_part");
+  if (indirect_call_target)
+fprintf (f, " indirect_call_target");
   if (nonfreeing_fn)
 fprintf (f, " nonfreeing_fn");
   if (DECL_STATIC_CONSTRUCTOR (decl))
Index: cgraph.h
===
--- cgraph.h(revision 234108)
+++ cgraph.h(working copy)
@@ -1366,6 +1366,8 @@ public:
   unsigned parallelized_function : 1;
   /* True if function is part split out by ipa-split.  */
   unsigned split_part : 1;
+  /* True if the function appears as possible target of indirect call.  */
+  unsigned indirect_call_target : 1;
 
 private:
   /* Worker for call_for_symbol_and_aliases.  */
Index: ipa.c
===
--- ipa.c   (revision 234108)
+++ ipa.c   (working copy)
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3.
 
 static bool
 has_addr_references_p (struct cgraph_node *node,
-  void *data ATTRIBUTE_UNUSED)
+  void *)
 {
   int i;
   struct ipa_ref *ref = NULL;
@@ -52,6 +52,14 @@ has_addr_references_p (struct cgraph_nod
   return false;
 }
 
+/* Return true when NODE can be target of an indirect call.  */
+
+static bool
+is_indirect_call_target_p (struct cgraph_node *node, void *)
+{
+  return node->indirect_call_target;
+}
+
 /* Look for all functions inlined to NODE and update their inlined_to pointers
to INLINED_TO.  */
 
@@ -172,23 +180,24 @@ walk_polymorphic_call_targets (hash_set<
(TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl
continue;
 
-  symtab_node *body = n->function_symbol ();
+ n->indirect_call_target = true;
+ symtab_node *body = n->function_symbol ();
 
  /* Prior inlining, keep alive bodies of possible targets for
 devirtualization.  */
-  if (n->definition
-  && (before_inlining_p
-  && opt_for_fn (body->decl, optimize)
-  && opt_for_fn (body->decl, flag_devirtualize)))
- {
-/* Be sure that we will not optimize out alias target
-   body.  */
-if (DECL_EXTERNAL (n->decl)
-&& n->alias
-&& before_inlining_p)
-  reachable->add (body);
-   reachable->add (n);
- }
+ if (n->definition
+ && (before_inlining_p
+ && opt_for_fn (body->decl, optimize)
+ && opt_for_fn (body->decl, flag_devirtualize)))
+{
+   /* Be sure that we will not optimize out alias target
+  body.  */
+   if (DECL_EXTERNAL (n->decl)
+   && n->alias
+   && before_inlining_p)
+ reachable->add (body);
+  reachable->add (n);
+}
  /* Even after inlining we want to keep the possible targets in the
 boundary, so late passes can still produce direct call even if
 the chance for inlining is lost.  */
@@ -323,6 +332,7 @@ symbol_table::remove_unreachable_nodes (
   FOR_EACH_FUNCTION (node)
 {
   node->used_as_abstract_origin = false;
+  node->indirect_call_target = false;
   if (node->definition
  && !node->global.inlined_to
  && !node->in_other_partition
@@ -659,7 +669,14 @@ symbol_table::remove_unreachable_nodes (
  fprintf (file, " %s", node->name ());
node->address_taken = false;
changed = true;
-   if (node->local_p ())
+   if (node->local_p ()
+   /* Virtual functions may be kept in cgraph just because
+  of possible later devirtualization.  Do not mark them as
+  local too early so we won't optimize them out