aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-transform.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2019-07-26 10:44:51 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2019-07-26 10:44:51 +0200
commit4517b378af6b412e053e8927972434d8580162d0 (patch)
tree8ba242b52d8258623593e284cd0ffb7d7618141e /gcc/ipa-inline-transform.c
parentac2dca4daf516c6972df1f5ef66e64b3c8f12bc2 (diff)
downloadgcc-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.c42
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