Fix PR ipa/65263.
authormarxin <marxin@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Mar 2015 09:26:20 +0000 (09:26 +0000)
committermarxin <marxin@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Mar 2015 09:26:20 +0000 (09:26 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@221134 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-icf.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/pr65263.C [new file with mode: 0644]

index 7d8cf78..5e11a0f 100644 (file)
@@ -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
index 5555439..9bae35e 100644 (file)
@@ -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"
index ff437cf..82519fa 100644 (file)
@@ -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
index 9cdd73e..4832618 100644 (file)
@@ -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.  */
index 4555c13..2b3cf0e 100644 (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>
 
        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 (file)
index 0000000..34459a2
--- /dev/null
@@ -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);
+}