Reorganize cgraph_node::clone_of_p
authorMartin Jambor <mjambor@suse.cz>
Mon, 15 Apr 2019 08:30:36 +0000 (10:30 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Mon, 15 Apr 2019 08:30:36 +0000 (10:30 +0200)
2019-04-15  Martin Jambor  <mjambor@suse.cz>

PR ipa/pr89693
* cgraph.c (clone_of_p): Loop over clone chain for each step in
the thunk chain.

testsuite/
* g++.dg/ipa/pr89693.C: New test.

From-SVN: r270364

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

index 2946beced27a138fb667e4e5b9a30576d4a189b2..e85c08c283b46b69edd692c546f4c84b95b66329 100644 (file)
@@ -1,3 +1,9 @@
+2019-04-15  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/pr89693
+       * cgraph.c (clone_of_p): Loop over clone chain for each step in
+       the thunk chain.
+
 2019-04-15  Monk Chiang  <sh.chiang04@gmail.com>
 
        * config.gcc (nds32*-*-linux*): Set gcc_cv_initfini_array to yes.
index 49d80ad1e286e40a50a00dd50cce20171a9f5ae0..b1b0b4c42d5c202916a25b54f554c891f1d6ab3e 100644 (file)
@@ -2977,17 +2977,25 @@ cgraph_node::collect_callers (void)
 static bool
 clone_of_p (cgraph_node *node, cgraph_node *node2)
 {
-  bool skipped_thunk = false;
   node = node->ultimate_alias_target ();
   node2 = node2->ultimate_alias_target ();
 
+  if (node2->clone_of == node
+      || node2->former_clone_of == node->decl)
+    return true;
+
+  if (!node->thunk.thunk_p && !node->former_thunk_p ())
+    {
+      while (node2 && node->decl != node2->decl)
+       node2 = node2->clone_of;
+      return node2 != NULL;
+    }
+
   /* There are no virtual clones of thunks so check former_clone_of or if we
      might have skipped thunks because this adjustments are no longer
      necessary.  */
   while (node->thunk.thunk_p || node->former_thunk_p ())
     {
-      if (node2->former_clone_of == node->decl)
-       return true;
       if (!node->thunk.this_adjusting)
        return false;
       /* In case of instrumented expanded thunks, which can have multiple calls
@@ -2996,23 +3004,21 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
       if (node->callees->next_callee)
        return true;
       node = node->callees->callee->ultimate_alias_target ();
-      skipped_thunk = true;
-    }
 
-  if (skipped_thunk)
-    {
       if (!node2->clone.args_to_skip
          || !bitmap_bit_p (node2->clone.args_to_skip, 0))
        return false;
       if (node2->former_clone_of == node->decl)
        return true;
-      else if (!node2->clone_of)
-       return false;
+
+      cgraph_node *n2 = node2;
+      while (n2 && node->decl != n2->decl)
+       n2 = n2->clone_of;
+      if (n2)
+       return true;
     }
 
-  while (node2 && node->decl != node2->decl)
-    node2 = node2->clone_of;
-  return node2 != NULL;
+  return false;
 }
 
 /* Verify edge count and frequency.  */
index 877ecc46502c01e93235798e189ded950a9b9c40..66dcfc4caf179f707a852d6636acc496a7f8ed4a 100644 (file)
@@ -1,3 +1,8 @@
+2019-04-15  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/pr89693
+       * g++.dg/ipa/pr89693.C: New test.
+
 2019-04-15  Dominique d'Humieres  <dominiq@gcc.gnu.org>
 
        PR tree-optimization/90020
diff --git a/gcc/testsuite/g++.dg/ipa/pr89693.C b/gcc/testsuite/g++.dg/ipa/pr89693.C
new file mode 100644 (file)
index 0000000..4ac83ee
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2005 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 4 Apr 2005 <nathan@codesourcery.com>
+// Re-purposed to check for re-rurgesnce of PR 89693 in 2019.
+
+// { dg-do compile }
+// { dg-options "-O3 -fno-ipa-icf-functions" }
+
+// Origin: yanliu@ca.ibm.com
+//         nathan@codesourcery.com
+
+struct A {
+  virtual void One ();
+};
+struct B  {
+  virtual B *Two ();
+  virtual B &Three ();
+};
+
+struct C : A, B
+{
+  virtual C *Two ();
+  virtual C &Three ();
+};
+void A::One () {}
+B *B::Two()    {return this;}
+B &B::Three()    {return *this;}
+C *C::Two ()   {return 0;}
+C &C::Three ()   {return *(C *)0;}
+
+B *Foo (B *b)
+{
+  return b->Two ();
+}
+
+B &Bar (B *b)
+{
+  return b->Three ();
+}
+
+int main ()
+{
+  C c;
+
+  /* We should not adjust a null pointer.  */
+  if (Foo (&c))
+    return 1;
+  /* But we should adjust a (bogus) null reference.  */
+  if (!&Bar (&c))
+    return 2;
+
+  return 0;
+}