From 6bbf39b789101366bccacda4f912b05636f03887 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 8 May 2016 20:44:02 +0200 Subject: [PATCH] cgraph.c (thunk_adjust): Export. * cgraph.c (thunk_adjust): Export. * cgraphclones.c (cgraph_node::create_clone): Clone thunk info. * cgraphunit.c (thunk_adjust): Export. (cgraph_node::assemble_thunks_and_aliases): Do not assemble inlined thunks. * ipa-inline-analyssi.c (compute_inline_parameters): Thunks are inlinable. * tree-inline.c (expand_call_inline): Expand thunks inline. From-SVN: r236012 --- gcc/ChangeLog | 11 ++++ gcc/cgraph.h | 1 + gcc/cgraphclones.c | 1 + gcc/cgraphunit.c | 3 +- gcc/ipa-inline-analysis.c | 107 +++++++++++++++++++------------------- gcc/tree-inline.c | 38 +++++++++++++- 6 files changed, 106 insertions(+), 55 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c562800bee1..1f985ce00e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-05-08 Jan Hubicka + + * cgraph.c (thunk_adjust): Export. + * cgraphclones.c (cgraph_node::create_clone): Clone thunk info. + * cgraphunit.c (thunk_adjust): Export. + (cgraph_node::assemble_thunks_and_aliases): Do not assemble inlined + thunks. + * ipa-inline-analyssi.c (compute_inline_parameters): Thunks are + inlinable. + * tree-inline.c (expand_call_inline): Expand thunks inline. + 2016-05-08 Uros Bizjak PR target/70998 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index d714ad75189..8ad9f456a22 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -2299,6 +2299,7 @@ void cgraphunit_c_finalize (void); IN_SSA is true if the gimple is in SSA. */ basic_block init_lowered_empty_function (tree, bool, gcov_type); +tree thunk_adjust (gimple_stmt_iterator *, tree, bool, HOST_WIDE_INT, tree); /* In cgraphclones.c */ tree clone_function_name_1 (const char *, const char *); diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 10f2d3417f4..43ee7352e5b 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -436,6 +436,7 @@ cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq, new_node->tm_clone = tm_clone; new_node->icf_merged = icf_merged; new_node->merged_comdat = merged_comdat; + new_node->thunk = thunk; new_node->clone.tree_map = NULL; new_node->clone.args_to_skip = args_to_skip; diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 57618807c49..4bfcad78f59 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1471,7 +1471,7 @@ init_lowered_empty_function (tree decl, bool in_ssa, gcov_type count) non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and zero for a result adjusting thunk. */ -static tree +tree thunk_adjust (gimple_stmt_iterator * bsi, tree ptr, bool this_adjusting, HOST_WIDE_INT fixed_offset, tree virtual_offset) @@ -1907,6 +1907,7 @@ cgraph_node::assemble_thunks_and_aliases (void) for (e = callers; e;) if (e->caller->thunk.thunk_p + && !e->caller->global.inlined_to && !e->caller->thunk.add_pointer_bounds_args) { cgraph_node *thunk = e->caller; diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 47b5b96ace4..17b21d17c5f 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2920,67 +2920,70 @@ compute_inline_parameters (struct cgraph_node *node, bool early) info = inline_summaries->get (node); reset_inline_summary (node, info); - /* FIXME: Thunks are inlinable, but tree-inline don't know how to do that. - Once this happen, we will need to more curefully predict call - statement size. */ + /* Estimate the stack size for the function if we're optimizing. */ + self_stack_size = optimize && !node->thunk.thunk_p + ? estimated_stack_frame_size (node) : 0; + info->estimated_self_stack_size = self_stack_size; + info->estimated_stack_size = self_stack_size; + info->stack_frame_offset = 0; + if (node->thunk.thunk_p) { struct inline_edge_summary *es = inline_edge_summary (node->callees); struct predicate t = true_predicate (); - info->inlinable = 0; node->callees->inline_failed = CIF_THUNK; node->local.can_change_signature = false; - es->call_stmt_time = 1; - es->call_stmt_size = 1; - account_size_time (info, 0, 0, &t); - return; + es->call_stmt_size = INLINE_SIZE_SCALE; + es->call_stmt_time = INLINE_TIME_SCALE; + account_size_time (info, INLINE_SIZE_SCALE * 2, INLINE_TIME_SCALE * 2, &t); + inline_update_overall_summary (node); + info->self_size = info->size; + info->self_time = info->time; + /* We can not inline instrumetnation clones. */ + info->inlinable = !node->thunk.add_pointer_bounds_args; } - - /* Even is_gimple_min_invariant rely on current_function_decl. */ - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - - /* Estimate the stack size for the function if we're optimizing. */ - self_stack_size = optimize ? estimated_stack_frame_size (node) : 0; - info->estimated_self_stack_size = self_stack_size; - info->estimated_stack_size = self_stack_size; - info->stack_frame_offset = 0; - - /* Can this function be inlined at all? */ - if (!opt_for_fn (node->decl, optimize) - && !lookup_attribute ("always_inline", - DECL_ATTRIBUTES (node->decl))) - info->inlinable = false; - else - info->inlinable = tree_inlinable_function_p (node->decl); - - info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun); - - /* Type attributes can use parameter indices to describe them. */ - if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) - node->local.can_change_signature = false; else { - /* Otherwise, inlinable functions always can change signature. */ - if (info->inlinable) - node->local.can_change_signature = true; - else - { - /* Functions calling builtin_apply can not change signature. */ - for (e = node->callees; e; e = e->next_callee) - { - tree cdecl = e->callee->decl; - if (DECL_BUILT_IN (cdecl) - && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL - && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS - || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START)) - break; - } - node->local.can_change_signature = !e; - } - } - estimate_function_body_sizes (node, early); - + /* Even is_gimple_min_invariant rely on current_function_decl. */ + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + + /* Can this function be inlined at all? */ + if (!opt_for_fn (node->decl, optimize) + && !lookup_attribute ("always_inline", + DECL_ATTRIBUTES (node->decl))) + info->inlinable = false; + else + info->inlinable = tree_inlinable_function_p (node->decl); + + info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun); + + /* Type attributes can use parameter indices to describe them. */ + if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) + node->local.can_change_signature = false; + else + { + /* Otherwise, inlinable functions always can change signature. */ + if (info->inlinable) + node->local.can_change_signature = true; + else + { + /* Functions calling builtin_apply can not change signature. */ + for (e = node->callees; e; e = e->next_callee) + { + tree cdecl = e->callee->decl; + if (DECL_BUILT_IN (cdecl) + && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL + && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS + || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START)) + break; + } + node->local.can_change_signature = !e; + } + } + estimate_function_body_sizes (node, early); + pop_cfun (); + } for (e = node->callees; e; e = e->next_callee) if (e->callee->comdat_local_p ()) break; @@ -2997,8 +3000,6 @@ compute_inline_parameters (struct cgraph_node *node, bool early) gcc_assert (info->time == info->self_time && info->size == info->self_size); } - - pop_cfun (); } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index da233b29c4f..2ee3f630b14 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4450,6 +4450,43 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id) } goto egress; } + id->src_node = cg_edge->callee; + + /* If callee is thunk, all we need is to adjust the THIS pointer + and redirect to function being thunked. */ + if (id->src_node->thunk.thunk_p) + { + cgraph_edge *edge; + tree virtual_offset = NULL; + int freq = cg_edge->frequency; + gcov_type count = cg_edge->count; + tree op; + gimple_stmt_iterator iter = gsi_for_stmt (stmt); + + cg_edge->remove (); + edge = id->src_node->callees->clone (id->dst_node, call_stmt, + gimple_uid (stmt), + REG_BR_PROB_BASE, CGRAPH_FREQ_BASE, + true); + edge->frequency = freq; + edge->count = count; + if (id->src_node->thunk.virtual_offset_p) + virtual_offset = size_int (id->src_node->thunk.virtual_value); + op = create_tmp_reg_fn (cfun, TREE_TYPE (gimple_call_arg (stmt, 0)), + NULL); + gsi_insert_before (&iter, gimple_build_assign (op, + gimple_call_arg (stmt, 0)), + GSI_NEW_STMT); + gcc_assert (id->src_node->thunk.this_adjusting); + op = thunk_adjust (&iter, op, 1, id->src_node->thunk.fixed_offset, + virtual_offset); + + gimple_call_set_arg (stmt, 0, op); + gimple_call_set_fndecl (stmt, edge->callee->decl); + update_stmt (stmt); + id->src_node->remove (); + return true; + } fn = cg_edge->callee->decl; cg_edge->callee->get_untransformed_body (); @@ -4523,7 +4560,6 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id) /* Record the function we are about to inline. */ id->src_fn = fn; - id->src_node = cg_edge->callee; id->src_cfun = DECL_STRUCT_FUNCTION (fn); id->call_stmt = stmt; -- 2.30.2