Commit 4f4ada6a by Jan Hubicka Committed by Jan Hubicka

re PR ipa/69589 (ICE in initialize_node_lattices, at ipa-cp.c:971)


	PR lto/69589
	* 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.

	* g++.dg/lto/pr69589_0.C: New testcase
	* g++.dg/lto/pr69589_1.C: New testcase

From-SVN: r234115
parent 079cd854
2016-03-10 Jan Hubicka <hubicka@ucw.cz> 2016-03-10 Jan Hubicka <hubicka@ucw.cz>
PR lto/69589
* 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.
2016-03-10 Jan Hubicka <hubicka@ucw.cz>
PR ipa/69630 PR ipa/69630
* ipa-devirt.c (possible_polymorphic_call_targets): Do not ICE * ipa-devirt.c (possible_polymorphic_call_targets): Do not ICE
on cxa_pure_virtual. on cxa_pure_virtual.
......
...@@ -2061,6 +2061,10 @@ cgraph_node::dump (FILE *f) ...@@ -2061,6 +2061,10 @@ cgraph_node::dump (FILE *f)
fprintf (f, " icf_merged"); fprintf (f, " icf_merged");
if (merged_comdat) if (merged_comdat)
fprintf (f, " 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) if (nonfreeing_fn)
fprintf (f, " nonfreeing_fn"); fprintf (f, " nonfreeing_fn");
if (DECL_STATIC_CONSTRUCTOR (decl)) if (DECL_STATIC_CONSTRUCTOR (decl))
......
...@@ -1366,6 +1366,8 @@ public: ...@@ -1366,6 +1366,8 @@ public:
unsigned parallelized_function : 1; unsigned parallelized_function : 1;
/* True if function is part split out by ipa-split. */ /* True if function is part split out by ipa-split. */
unsigned split_part : 1; unsigned split_part : 1;
/* True if the function appears as possible target of indirect call. */
unsigned indirect_call_target : 1;
private: private:
/* Worker for call_for_symbol_and_aliases. */ /* Worker for call_for_symbol_and_aliases. */
......
...@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
static bool static bool
has_addr_references_p (struct cgraph_node *node, has_addr_references_p (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED) void *)
{ {
int i; int i;
struct ipa_ref *ref = NULL; struct ipa_ref *ref = NULL;
...@@ -52,6 +52,14 @@ has_addr_references_p (struct cgraph_node *node, ...@@ -52,6 +52,14 @@ has_addr_references_p (struct cgraph_node *node,
return false; 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 /* Look for all functions inlined to NODE and update their inlined_to pointers
to INLINED_TO. */ to INLINED_TO. */
...@@ -172,23 +180,24 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, ...@@ -172,23 +180,24 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
(TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)))) (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl))))
continue; 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 /* Prior inlining, keep alive bodies of possible targets for
devirtualization. */ devirtualization. */
if (n->definition if (n->definition
&& (before_inlining_p && (before_inlining_p
&& opt_for_fn (body->decl, optimize) && opt_for_fn (body->decl, optimize)
&& opt_for_fn (body->decl, flag_devirtualize))) && opt_for_fn (body->decl, flag_devirtualize)))
{ {
/* Be sure that we will not optimize out alias target /* Be sure that we will not optimize out alias target
body. */ body. */
if (DECL_EXTERNAL (n->decl) if (DECL_EXTERNAL (n->decl)
&& n->alias && n->alias
&& before_inlining_p) && before_inlining_p)
reachable->add (body); reachable->add (body);
reachable->add (n); reachable->add (n);
} }
/* Even after inlining we want to keep the possible targets in the /* Even after inlining we want to keep the possible targets in the
boundary, so late passes can still produce direct call even if boundary, so late passes can still produce direct call even if
the chance for inlining is lost. */ the chance for inlining is lost. */
...@@ -323,6 +332,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -323,6 +332,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
FOR_EACH_FUNCTION (node) FOR_EACH_FUNCTION (node)
{ {
node->used_as_abstract_origin = false; node->used_as_abstract_origin = false;
node->indirect_call_target = false;
if (node->definition if (node->definition
&& !node->global.inlined_to && !node->global.inlined_to
&& !node->in_other_partition && !node->in_other_partition
...@@ -659,7 +669,14 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -659,7 +669,14 @@ symbol_table::remove_unreachable_nodes (FILE *file)
fprintf (file, " %s", node->name ()); fprintf (file, " %s", node->name ());
node->address_taken = false; node->address_taken = false;
changed = true; 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 before
we are done with polymorphic call analysis. */
&& (!before_inlining_p
|| !node->call_for_symbol_and_aliases
(is_indirect_call_target_p, NULL, true)))
{ {
node->local.local = true; node->local.local = true;
if (file) if (file)
......
2016-03-10 Jan Hubicka <hubicka@ucw.cz>
PR lto/69589
* g++.dg/lto/pr69589_0.C: New testcase
* g++.dg/lto/pr69589_1.C: New testcase
2016-03-10 Marek Polacek <polacek@redhat.com> 2016-03-10 Marek Polacek <polacek@redhat.com>
PR c++/70153 PR c++/70153
......
// { dg-lto-do link }
// { dg-lto-options "-O2 -rdynamic" }
// { dg-extra-ld-options "-r -nostdlib" }
#pragma GCC visibility push(hidden)
struct A { int &operator[] (long); };
template <typename> struct B;
template <typename T, typename = B<T> >
using Z = int;
template <typename> struct C;
struct S {
int e;
virtual ~S () {}
};
struct D : S {
A a;
long i;
D() { { e ? &a[i] : nullptr; } }
};
template <>
struct C<int> { Z<S> m8 () const; };
Z<S>
C<int>::m8 () const
{
D ();
}
struct A;
template <class T>
struct Q { Q (T); };
template<typename T, class D>
struct U {
~U () { m1 (nullptr); }
D m2 ();
T *u;
void m1 (T *) { m2 () (u); }
};
struct F { F (int *); };
template <class, class T = F>
using W = Q<T>;
int a, b;
void fn1 (void *);
template <class T>
void
fn2 (T *x)
{
if (x)
x->~T();
fn1 (x);
}
template <typename T>
struct C {
void operator() (T *x) { fn2 (x); }
};
struct D;
template <typename T, typename D = C<T> >
using V = U<T, D>;
struct A {
A (int *);
};
struct S;
struct G {
V<S> m3 ();
};
struct S {
int e;
virtual ~S () {}
};
template<typename T>
struct H {
H (int, T x, int) : h(x) {}
G g;
void m4 () { g.m3 (); }
T h;
};
struct I {
I(A, W<D>);
};
void
test ()
{
A c (&b);
W<D> d (&b);
I e (c, d);
H<I> f (0, e, a);
f.m4 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment