aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-transform.c
diff options
context:
space:
mode:
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