diff options
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 28 |
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; |