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
+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>
}
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"
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
{
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);)
{
{
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 ();
}
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)
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. */
+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
--- /dev/null
+/* { 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);
+}