diff mbox

[PR,68851] Do not collect thunks in callect_callers

Message ID 20151214180811.GG3956@virgil.suse.cz
State New
Headers show

Commit Message

Martin Jambor Dec. 14, 2015, 6:08 p.m. UTC
Hi,

in PR 68851, IPA-CP decides to clone for all known contexts, even when
it is not local because the code is not supposed to grow anyway.  The
code doing that uses collect_callers method of cgraph_edge to find all
the edges which are to be redirected in such case.  However, there is
also an edge from a hunk to the cloned node and that gets collected
and redirected too.  Later on, this inconsistency (a thunk calling a
wrong node) leads to an assert in comdat handling, but it can lead to
all sorts of trouble.

The following patch fixes it by checking that thunks are not added
into the vector in that method (which is only used by IPA-CP at this
one spot and IPA-SRA so it should be fine).  Bootstrapped and tested
on x86_64-linux.  OK for trunk?  And perhaps for the gcc-5 branch too?

Thanks,

Martin


2015-12-14  Martin Jambor  <mjambor@suse.cz>

	PR ipa/68851
	* cgraph.c (collect_callers_of_node_1): Do not collect thunks.
	* cgraph.h (cgraph_node): Change comment of collect_callers.

testsuite/
	* g++.dg/ipa/pr68851.C: New test.
---
 gcc/cgraph.c                       |  3 ++-
 gcc/cgraph.h                       |  2 +-
 gcc/testsuite/g++.dg/ipa/pr68851.C | 29 +++++++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr68851.C

Comments

Jan Hubicka Dec. 14, 2015, 6:19 p.m. UTC | #1
> Hi,
> 
> in PR 68851, IPA-CP decides to clone for all known contexts, even when
> it is not local because the code is not supposed to grow anyway.  The
> code doing that uses collect_callers method of cgraph_edge to find all
> the edges which are to be redirected in such case.  However, there is
> also an edge from a hunk to the cloned node and that gets collected
> and redirected too.  Later on, this inconsistency (a thunk calling a
> wrong node) leads to an assert in comdat handling, but it can lead to
> all sorts of trouble.
> 
> The following patch fixes it by checking that thunks are not added
> into the vector in that method (which is only used by IPA-CP at this
> one spot and IPA-SRA so it should be fine).  Bootstrapped and tested
> on x86_64-linux.  OK for trunk?  And perhaps for the gcc-5 branch too?
> 
> Thanks,
> 
> Martin
> 
> 
> 2015-12-14  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/68851
> 	* cgraph.c (collect_callers_of_node_1): Do not collect thunks.
> 	* cgraph.h (cgraph_node): Change comment of collect_callers.
> 
> testsuite/
> 	* g++.dg/ipa/pr68851.C: New test.

This is OK (for branches too if it won't cause issues for a week)
thanks!
Honza
diff mbox

Patch

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index c8c3370..5a9c2a2 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2592,7 +2592,8 @@  collect_callers_of_node_1 (cgraph_node *node, void *data)
 
   if (avail > AVAIL_INTERPOSABLE)
     for (cs = node->callers; cs != NULL; cs = cs->next_caller)
-      if (!cs->indirect_inlining_edge)
+      if (!cs->indirect_inlining_edge
+	  && !cs->caller->thunk.thunk_p)
         redirect_callers->safe_push (cs);
   return false;
 }
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0a09391..ba14215 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1070,7 +1070,7 @@  public:
   cgraph_edge *get_edge (gimple *call_stmt);
 
   /* Collect all callers of cgraph_node and its aliases that are known to lead
-     to NODE (i.e. are not overwritable).  */
+     to NODE (i.e. are not overwritable) and that are not thunks.  */
   vec<cgraph_edge *> collect_callers (void);
 
   /* Remove all callers from the node.  */
diff --git a/gcc/testsuite/g++.dg/ipa/pr68851.C b/gcc/testsuite/g++.dg/ipa/pr68851.C
new file mode 100644
index 0000000..659e4cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr68851.C
@@ -0,0 +1,29 @@ 
+// { dg-do compile }
+// { dg-options "-O3" }
+
+class A;
+class B {
+public:
+  operator A *() const;
+};
+class A {
+public:
+  virtual bool isFormControlElement() const {}
+};
+class C {
+  struct D {
+    B element;
+  };
+  bool checkPseudoClass(const D &, int &) const;
+};
+class F {
+  virtual bool isFormControlElement() const;
+};
+class G : A, F {
+  bool isFormControlElement() const {}
+};
+bool C::checkPseudoClass(const D &p1, int &) const {
+  A &a = *p1.element;
+  a.isFormControlElement();
+  a.isFormControlElement() || a.isFormControlElement();
+}