Relax cgraph_node::clone_of_p to also look through former clones
authorMartin Jambor <mjambor@suse.cz>
Thu, 7 Mar 2019 16:03:34 +0000 (17:03 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Thu, 7 Mar 2019 16:03:34 +0000 (17:03 +0100)
2019-03-07  Martin Jambor  <mjambor@suse.cz>

PR ipa/88235
* cgraph.h (cgraph_node): New inline method former_thunk_p.
* cgraph.c (cgraph_node::dump): Dump a note if node is a former thunk.
(clone_of_p): Treat expanded thunks like thunks, be optimistic if they
have multiple callees.  At the end check if declarations match as
opposed to cgraph_nodes.

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

From-SVN: r269462

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

index e62b5e58fab0792ae0394ab366c5cfa23737e092..b8774f253919c3653161d2f943ffbdd2f0119bcc 100644 (file)
@@ -1,3 +1,12 @@
+2019-03-07  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/88235
+       * cgraph.h (cgraph_node): New inline method former_thunk_p.
+       * cgraph.c (cgraph_node::dump): Dump a note if node is a former thunk.
+       (clone_of_p): Treat expanded thunks like thunks, be optimistic if they
+       have multiple callees.  At the end check if declarations match as
+       opposed to cgraph_nodes.
+
 2019-03-07  Martin Liska  <mliska@suse.cz>
 
        * cgraph.c (cgraph_node::verify_node): Verify with a neighbour
index dfe1833ed1dd29962462f9edfc3799d52f7d85df..9f0d603a1cf3bbfeb18e7802b27601e4691cec89 100644 (file)
@@ -2109,6 +2109,8 @@ cgraph_node::dump (FILE *f)
               (int)thunk.indirect_offset,
               (int)thunk.virtual_offset_p);
     }
+  else if (former_thunk_p ())
+    fprintf (f, "  Former thunk");
   if (alias && thunk.alias
       && DECL_P (thunk.alias))
     {
@@ -2963,7 +2965,9 @@ cgraph_node::collect_callers (void)
   return redirect_callers;
 }
 
-/* Return TRUE if NODE2 a clone of NODE or is equivalent to it.  */
+
+/* Return TRUE if NODE2 a clone of NODE or is equivalent to it.  Return
+   optimistically true if this cannot be determined.  */
 
 static bool
 clone_of_p (cgraph_node *node, cgraph_node *node2)
@@ -2975,12 +2979,17 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
   /* 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)
+  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
+        in them, we do not know how to continue and just have to be
+        optimistic.  */
+      if (node->callees->next_callee)
+       return true;
       node = node->callees->callee->ultimate_alias_target ();
       skipped_thunk = true;
     }
@@ -2996,7 +3005,7 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
        return false;
     }
 
-  while (node != node2 && node2)
+  while (node2 && node->decl != node2->decl)
     node2 = node2->clone_of;
   return node2 != NULL;
 }
index c294602d7624b4f6aa9f1bec2eb44b736a667d2c..9a19d83fffb294479bbec5f7383dd7a07085eaf3 100644 (file)
@@ -1283,6 +1283,9 @@ public:
      Note that at WPA stage, the function body may not be present in memory.  */
   inline bool has_gimple_body_p (void);
 
+  /* Return true if this node represents a former, i.e. an expanded, thunk.  */
+  inline bool former_thunk_p (void);
+
   /* Return true if function should be optimized for size.  */
   bool optimize_for_size_p (void);
 
@@ -2921,6 +2924,17 @@ cgraph_node::has_gimple_body_p (void)
   return definition && !thunk.thunk_p && !alias;
 }
 
+/* Return true if this node represents a former, i.e. an expanded, thunk.  */
+
+inline bool
+cgraph_node::former_thunk_p (void)
+{
+  return (!thunk.thunk_p
+         && (thunk.fixed_offset
+             || thunk.virtual_offset_p
+             || thunk.indirect_offset));
+}
+
 /* Walk all functions with body defined.  */
 #define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \
    for ((node) = symtab->first_function_with_gimple_body (); (node); \
index d13a7db0bb81e1beb2d3365702d891c6f71b13c2..d0bd73432e0d60fa30e1596bc0124aa6adbd2f70 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-07  Martin Jambor  <mjambor@suse.cz>
+
+       PR ipa/88235
+       * g++.dg/ipa/pr88235.C: New test.
+
 2019-04-07  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/89618
diff --git a/gcc/testsuite/g++.dg/ipa/pr88235.C b/gcc/testsuite/g++.dg/ipa/pr88235.C
new file mode 100644 (file)
index 0000000..29f3252
--- /dev/null
@@ -0,0 +1,55 @@
+// { dg-do compile }
+// { dg-options "-O1 -fdevirtualize -finline-small-functions -fipa-cp -fipa-cp-clone --param ipa-cp-eval-threshold=125 --param max-inline-insns-single=4" }
+
+extern "C" int printf (const char *, ...);
+enum E { vf_request, vf_event } want;
+
+int errs = 0;
+
+class ivResource {
+public:
+  virtual ~ivResource () { }
+};
+
+class ivHandler   : public ivResource   {
+public:
+  virtual void event() { }
+};
+
+class ivGlyph   : public ivResource   {
+public:
+  virtual ~ivGlyph  () { }
+  virtual void request () {
+    if (want!=vf_request)
+      ++errs;
+  }
+};
+
+class ItemView : public ivGlyph, public ivHandler {
+public:
+  virtual void event () {
+    if (want!=vf_event)
+      ++errs;
+  }
+} a;
+
+ivGlyph *bar() {
+  return &a;
+}
+
+ivHandler *bar2() {
+  return &a;
+}
+
+int main() {
+  want=vf_request;
+  bar()->request();
+  want=vf_event;
+  bar2()->event();
+  if (errs) {
+    printf("FAIL\n");
+    return 1;
+  }
+  printf("PASS\n");
+  return 0;
+}