re PR target/65263 (ICE (error: unrecognizable insn / in insn_min_length, at config/rs6000/rs6000.md) on powerpc64le-linux-gnu)

Fix PR ipa/65263.

	PR ipa/65263
	* cgraph.c (cgraph_node::has_thunk_p): New function.
	* cgraph.h (cgraph_node::has_thunk_p: Likewise.
	* ipa-icf.c (redirect_all_callers): Do not redirect thunks.
	(sem_function::merge): Assert is changed.
	* g++.dg/ipa/pr65263.C: New test.


Co-Authored-By: Jan Hubicka <hubicka@ucw.cz>

From-SVN: r221134
This commit is contained in:
Martin Liska 2015-03-03 10:26:20 +01:00 committed by Martin Liska
parent bd31fe14d2
commit 17d1bf760f
6 changed files with 100 additions and 5 deletions

View File

@ -1,3 +1,12 @@
2015-03-03 Martin Liska <mliska@suse.cz>
Jan Hubicka <hubicka@ucw.cz>
PR ipa/65263
* cgraph.c (cgraph_node::has_thunk_p): New function.
* cgraph.h (cgraph_node::has_thunk_p: Likewise.
* ipa-icf.c (redirect_all_callers): Do not redirect thunks.
(sem_function::merge): Assert is changed.
2015-03-03 Martin Liska <mliska@suse.cz> 2015-03-03 Martin Liska <mliska@suse.cz>
Martin Jambor <mjambor@suse.cz> Martin Jambor <mjambor@suse.cz>

View File

@ -3325,4 +3325,16 @@ cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
} }
return false; return false;
} }
/* Return true if NODE has thunk. */
bool
cgraph_node::has_thunk_p (cgraph_node *node, void *)
{
for (cgraph_edge *e = node->callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p)
return true;
return false;
}
#include "gt-cgraph.h" #include "gt-cgraph.h"

View File

@ -1204,6 +1204,9 @@ public:
with (not necessarily cgraph_node (DECL). */ with (not necessarily cgraph_node (DECL). */
static cgraph_node *create_alias (tree alias, tree target); static cgraph_node *create_alias (tree alias, tree target);
/* Return true if NODE has thunk. */
static bool has_thunk_p (cgraph_node *node, void *);
cgraph_edge *callees; cgraph_edge *callees;
cgraph_edge *callers; cgraph_edge *callers;
/* List of edges representing indirect calls with a yet undetermined /* List of edges representing indirect calls with a yet undetermined

View File

@ -697,12 +697,22 @@ redirect_all_callers (cgraph_node *n, cgraph_node *to)
{ {
int nredirected = 0; int nredirected = 0;
ipa_ref *ref; ipa_ref *ref;
cgraph_edge *e = n->callers;
while (n->callers) while (e)
{ {
cgraph_edge *e = n->callers; /* Redirecting thunks to interposable symbols or symbols in other sections
e->redirect_callee (to); may not be supported by target output code. Play safe for now and
nredirected++; punt on redirection. */
if (!e->caller->thunk.thunk_p)
{
struct cgraph_edge *nexte = e->next_caller;
e->redirect_callee (to);
e = nexte;
nredirected++;
}
else
e = e->next_callee;
} }
for (unsigned i = 0; n->iterate_direct_aliases (i, ref);) for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
{ {
@ -717,6 +727,8 @@ redirect_all_callers (cgraph_node *n, cgraph_node *to)
{ {
nredirected += redirect_all_callers (n_alias, to); nredirected += redirect_all_callers (n_alias, to);
if (n_alias->can_remove_if_no_direct_calls_p () if (n_alias->can_remove_if_no_direct_calls_p ()
&& !n_alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
NULL, true)
&& !n_alias->has_aliases_p ()) && !n_alias->has_aliases_p ())
n_alias->remove (); n_alias->remove ();
} }
@ -907,6 +919,8 @@ sem_function::merge (sem_item *alias_item)
return false; return false;
} }
if (!create_wrapper if (!create_wrapper
&& !alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
NULL, true)
&& !alias->can_remove_if_no_direct_calls_p ()) && !alias->can_remove_if_no_direct_calls_p ())
{ {
if (dump_file) if (dump_file)
@ -975,7 +989,10 @@ sem_function::merge (sem_item *alias_item)
if (dump_file) if (dump_file)
fprintf (dump_file, "Unified; Wrapper has been created.\n\n"); fprintf (dump_file, "Unified; Wrapper has been created.\n\n");
} }
gcc_assert (alias->icf_merged || remove);
/* It's possible that redirection can hit thunks that block
redirection opportunities. */
gcc_assert (alias->icf_merged || remove || redirect_callers);
original->icf_merged = true; original->icf_merged = true;
/* Inform the inliner about cross-module merging. */ /* Inform the inliner about cross-module merging. */

View File

@ -1,3 +1,8 @@
2015-03-03 Martin Liska <mliska@suse.cz>
Jan Hubicka <hubicka@ucw.cz>
* g++.dg/ipa/pr65263.C: New test.
2015-03-02 Jan Hubicka <hubicka@ucw.cz> 2015-03-02 Jan Hubicka <hubicka@ucw.cz>
PR ipa/65130 PR ipa/65130

View File

@ -0,0 +1,49 @@
/* { dg-do compile } */
/* { dg-options "-O3 -c -w" } */
template <class> class A;
template <class R> struct VirtualMatrice {
virtual bool m_fn1(int) const { return true; }
struct B {
A<R> x;
B(VirtualMatrice *p1, A<R> p2) : x(p2) { p1->m_fn1(0) ?: throw; }
};
void operator*(A<R> p1) { B(this, p1); }
~VirtualMatrice();
}
;
template <class> class A {
public:
operator int *();
A(int *, long);
};
class G : public A<int> {
public:
G(long);
};
int typedef Complex;
template <class> class H : VirtualMatrice<int> {};
template <class> class C;
template <> class C<int> : H<Complex>, VirtualMatrice<Complex> {
bool m_fn1(int) const { return true; }
};
template <class K, class Mat>
void DoIdoAction(int, int, A<K> p3, A<K>, A<K>, A<K>, Mat, Mat &p8) {
p8 *p3;
}
class D {
typedef int K;
class F {
int operator()() const;
};
};
int D::F::operator()() const {
VirtualMatrice<K> *a;
VirtualMatrice<K> b, &B = *a;
G c(0), g(1);
int d, e, f;
A<K> h(&g[f], 0), i(&g[e], 0), j(&g[d], 0);
DoIdoAction(0, 3, h, i, j, c, b, B);
}