diff options
author | Martin Jambor <mjambor@suse.cz> | 2019-07-26 10:44:51 +0200 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2019-07-26 10:44:51 +0200 |
commit | 4517b378af6b412e053e8927972434d8580162d0 (patch) | |
tree | 8ba242b52d8258623593e284cd0ffb7d7618141e /gcc/ipa-inline-transform.c | |
parent | ac2dca4daf516c6972df1f5ef66e64b3c8f12bc2 (diff) | |
download | gcc-4517b378af6b412e053e8927972434d8580162d0.zip gcc-4517b378af6b412e053e8927972434d8580162d0.tar.gz gcc-4517b378af6b412e053e8927972434d8580162d0.tar.bz2 |
[PR 89330] Remove non-useful speculations from new_edges
2019-07-26 Martin Jambor <mjambor@suse.cz>
PR ipa/89330
* ipa-inline-transform.c (check_speculations_1): New function.
(push_all_edges_in_set_to_vec): Likewise.
(check_speculations): Use check_speculations_1, new parameter
new_edges.
(inline_call): Pass new_edges to check_speculations.
* ipa-inline.c (add_new_edges_to_heap): Assert edge_callee is not
NULL.
(speculation_useful_p): Early return true if edge is inlined, remove
later checks for inline_failed.
testsuite/
* g++.dg/lto/pr89330_[01].C: New test.
* g++.dg/tree-prof/devirt.C: Added -fno-profile-values to dg-options.
From-SVN: r273825
Diffstat (limited to 'gcc/ipa-inline-transform.c')
-rw-r--r-- | gcc/ipa-inline-transform.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 4a3a193..897c563 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -237,10 +237,13 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, } } -/* Check all speculations in N and resolve them if they seems useless. */ +/* Check all speculations in N and if any seem useless, resolve them. When a + first edge is resolved, pop all edges from NEW_EDGES and insert them to + EDGE_SET. Then remove each resolved edge from EDGE_SET, if it is there. */ static bool -check_speculations (cgraph_node *n) +check_speculations_1 (cgraph_node *n, vec<cgraph_edge *> *new_edges, + hash_set <cgraph_edge *> *edge_set) { bool speculation_removed = false; cgraph_edge *next; @@ -250,15 +253,46 @@ check_speculations (cgraph_node *n) next = e->next_callee; if (e->speculative && !speculation_useful_p (e, true)) { + while (new_edges && !new_edges->is_empty ()) + edge_set->add (new_edges->pop ()); + edge_set->remove (e); + e->resolve_speculation (NULL); speculation_removed = true; } else if (!e->inline_failed) - speculation_removed |= check_speculations (e->callee); + speculation_removed |= check_speculations_1 (e->callee, new_edges, + edge_set); } return speculation_removed; } +/* Push E to NEW_EDGES. Called from hash_set traverse method, which + unfortunately means this function has to have external linkage, otherwise + the code will not compile with gcc 4.8. */ + +bool +push_all_edges_in_set_to_vec (cgraph_edge * const &e, + vec<cgraph_edge *> *new_edges) +{ + new_edges->safe_push (e); + return true; +} + +/* Check all speculations in N and if any seem useless, resolve them and remove + them from NEW_EDGES. */ + +static bool +check_speculations (cgraph_node *n, vec<cgraph_edge *> *new_edges) +{ + hash_set <cgraph_edge *> edge_set; + bool res = check_speculations_1 (n, new_edges, &edge_set); + if (!edge_set.is_empty ()) + edge_set.traverse <vec<cgraph_edge *> *, + push_all_edges_in_set_to_vec> (new_edges); + return res; +} + /* Mark all call graph edges coming out of NODE and all nodes that have been inlined to it as in_polymorphic_cdtor. */ @@ -450,7 +484,7 @@ inline_call (struct cgraph_edge *e, bool update_original, mark_all_inlined_calls_cdtor (e->callee); if (opt_for_fn (e->caller->decl, optimize)) new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges); - check_speculations (e->callee); + check_speculations (e->callee, new_edges); if (update_overall_summary) ipa_update_overall_fn_summary (to); else |