summaryrefslogtreecommitdiff
path: root/gcc/cgraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r--gcc/cgraph.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 281ad6326b5..be3661af6d3 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2544,12 +2544,34 @@ collect_callers_of_node (struct cgraph_node *node)
return redirect_callers;
}
-/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
+/* Return TRUE if NODE2 a clone of NODE or is equivalent to it. */
+
static bool
clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
{
+ bool skipped_thunk = false;
node = cgraph_function_or_thunk_node (node, NULL);
node2 = cgraph_function_or_thunk_node (node2, NULL);
+
+ /* 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)
+ {
+ if (node2->former_clone_of == node->decl)
+ return true;
+ if (!node->thunk.this_adjusting)
+ return false;
+ node = cgraph_function_or_thunk_node (node->callees->callee, NULL);
+ skipped_thunk = true;
+ }
+
+ if (skipped_thunk
+ && (!node2->clone_of
+ || !node2->clone.args_to_skip
+ || !bitmap_bit_p (node2->clone.args_to_skip, 0)))
+ return false;
+
while (node != node2 && node2)
node2 = node2->clone_of;
return node2 != NULL;
@@ -2649,10 +2671,8 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
node = cgraph_function_or_thunk_node (node, NULL);
if (e->callee->former_clone_of != node->decl
- /* IPA-CP sometimes redirect edge to clone and then back to the former
- function. This ping-pong has to go, eventually. */
&& (node != cgraph_function_or_thunk_node (e->callee, NULL))
- && !clone_of_p (cgraph_function_or_thunk_node (node, NULL), e->callee))
+ && !clone_of_p (node, e->callee))
return true;
else
return false;