aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2015-03-03 10:26:20 +0100
committerMartin Liska <marxin@gcc.gnu.org>2015-03-03 09:26:20 +0000
commit17d1bf760f8fda0023d5074de0a2b2929e27c480 (patch)
tree95f961e1350a2d19eb23ce29ab324e11f8dee391 /gcc
parentbd31fe14d2dfb4b12a82d9a223853ff2228a6523 (diff)
downloadgcc-17d1bf760f8fda0023d5074de0a2b2929e27c480.zip
gcc-17d1bf760f8fda0023d5074de0a2b2929e27c480.tar.gz
gcc-17d1bf760f8fda0023d5074de0a2b2929e27c480.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/cgraph.c12
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/ipa-icf.c27
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr65263.C49
6 files changed, 100 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d8cf78..5e11a0f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,13 @@
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>
Martin Jambor <mjambor@suse.cz>
PR ipa/65087
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 5555439..9bae35e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -3325,4 +3325,16 @@ cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
}
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"
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index ff437cf..82519fa 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1204,6 +1204,9 @@ public:
with (not necessarily cgraph_node (DECL). */
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 *callers;
/* List of edges representing indirect calls with a yet undetermined
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 9cdd73e..4832618 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -697,12 +697,22 @@ redirect_all_callers (cgraph_node *n, cgraph_node *to)
{
int nredirected = 0;
ipa_ref *ref;
+ cgraph_edge *e = n->callers;
- while (n->callers)
+ while (e)
{
- cgraph_edge *e = n->callers;
- e->redirect_callee (to);
- nredirected++;
+ /* Redirecting thunks to interposable symbols or symbols in other sections
+ may not be supported by target output code. Play safe for now and
+ 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);)
{
@@ -717,6 +727,8 @@ redirect_all_callers (cgraph_node *n, cgraph_node *to)
{
nredirected += redirect_all_callers (n_alias, to);
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->remove ();
}
@@ -907,6 +919,8 @@ sem_function::merge (sem_item *alias_item)
return false;
}
if (!create_wrapper
+ && !alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
+ NULL, true)
&& !alias->can_remove_if_no_direct_calls_p ())
{
if (dump_file)
@@ -975,7 +989,10 @@ sem_function::merge (sem_item *alias_item)
if (dump_file)
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;
/* Inform the inliner about cross-module merging. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4555c13..2b3cf0e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
PR ipa/65130
diff --git a/gcc/testsuite/g++.dg/ipa/pr65263.C b/gcc/testsuite/g++.dg/ipa/pr65263.C
new file mode 100644
index 0000000..34459a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr65263.C
@@ -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);
+}