From e3cc64dec20832769406aa38cde83c7dd4194bf4 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Tue, 22 Apr 2014 13:33:12 -0700 Subject: [4.9] GCC 4.9.0 official release refresh Change-Id: Ic99a7da8b44b789a48aeec93b33e93944d6e6767 --- gcc-4.9/gcc/cgraph.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'gcc-4.9/gcc/cgraph.c') diff --git a/gcc-4.9/gcc/cgraph.c b/gcc-4.9/gcc/cgraph.c index abfd63c..be3661a 100644 --- a/gcc-4.9/gcc/cgraph.c +++ b/gcc-4.9/gcc/cgraph.c @@ -61,6 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "ipa-inline.h" #include "cfgloop.h" #include "gimple-pretty-print.h" +#include "expr.h" +#include "tree-dfa.h" /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */ #include "tree-pass.h" @@ -1329,6 +1331,7 @@ gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) { tree decl = gimple_call_fndecl (e->call_stmt); + tree lhs = gimple_call_lhs (e->call_stmt); gimple new_stmt; gimple_stmt_iterator gsi; #ifdef ENABLE_CHECKING @@ -1471,6 +1474,31 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); } + /* If the call becomes noreturn, remove the lhs. */ + if (lhs && (gimple_call_flags (new_stmt) & ECF_NORETURN)) + { + if (TREE_CODE (lhs) == SSA_NAME) + { + tree var = create_tmp_reg_fn (DECL_STRUCT_FUNCTION (e->caller->decl), + TREE_TYPE (lhs), NULL); + var = get_or_create_ssa_default_def + (DECL_STRUCT_FUNCTION (e->caller->decl), var); + gimple set_stmt = gimple_build_assign (lhs, var); + gsi = gsi_for_stmt (new_stmt); + gsi_insert_before_without_update (&gsi, set_stmt, GSI_SAME_STMT); + update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), set_stmt); + } + gimple_call_set_lhs (new_stmt, NULL_TREE); + update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); + } + + /* If new callee has no static chain, remove it. */ + if (gimple_call_chain (new_stmt) && !DECL_STATIC_CHAIN (e->callee->decl)) + { + gimple_call_set_chain (new_stmt, NULL); + update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); + } + cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false); if (cgraph_dump_file) @@ -2516,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; @@ -2612,13 +2662,17 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl) || node->in_other_partition || e->callee->in_other_partition) return false; + + /* Optimizers can redirect unreachable calls or calls triggering undefined + behaviour to builtin_unreachable. */ + if (DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_UNREACHABLE) + return false; 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; -- cgit v1.1