From 1738b52201b1ce28c9f869646f5412b8937ccfe6 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 7 Mar 2019 17:03:34 +0100 Subject: [PATCH] Relax cgraph_node::clone_of_p to also look through former clones 2019-03-07 Martin Jambor 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 | 9 +++++++ gcc/cgraph.c | 15 ++++++++--- gcc/cgraph.h | 14 ++++++++++ gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/ipa/pr88235.C | 55 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/pr88235.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e62b5e5..b8774f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-03-07 Martin Jambor + + 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 * cgraph.c (cgraph_node::verify_node): Verify with a neighbour diff --git a/gcc/cgraph.c b/gcc/cgraph.c index dfe1833..9f0d603 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -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; } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index c294602..9a19d83 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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); \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d13a7db..d0bd734 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-03-07 Martin Jambor + + PR ipa/88235 + * g++.dg/ipa/pr88235.C: New test. + 2019-04-07 Richard Biener 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 index 0000000..29f3252 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr88235.C @@ -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; +} -- 2.7.4