mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
3b695ba657
commit
6bbf39b789
|
|
@ -1,3 +1,14 @@
|
||||||
|
2016-05-08 Jan Hubicka <hubicka@ucw.cz>
|
||||||
|
|
||||||
|
* 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 <ubizjak@gmail.com>
|
2016-05-08 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
PR target/70998
|
PR target/70998
|
||||||
|
|
|
||||||
|
|
@ -2299,6 +2299,7 @@ void cgraphunit_c_finalize (void);
|
||||||
IN_SSA is true if the gimple is in SSA. */
|
IN_SSA is true if the gimple is in SSA. */
|
||||||
basic_block init_lowered_empty_function (tree, bool, gcov_type);
|
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 */
|
/* In cgraphclones.c */
|
||||||
|
|
||||||
tree clone_function_name_1 (const char *, const char *);
|
tree clone_function_name_1 (const char *, const char *);
|
||||||
|
|
|
||||||
|
|
@ -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->tm_clone = tm_clone;
|
||||||
new_node->icf_merged = icf_merged;
|
new_node->icf_merged = icf_merged;
|
||||||
new_node->merged_comdat = merged_comdat;
|
new_node->merged_comdat = merged_comdat;
|
||||||
|
new_node->thunk = thunk;
|
||||||
|
|
||||||
new_node->clone.tree_map = NULL;
|
new_node->clone.tree_map = NULL;
|
||||||
new_node->clone.args_to_skip = args_to_skip;
|
new_node->clone.args_to_skip = args_to_skip;
|
||||||
|
|
|
||||||
|
|
@ -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
|
non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
|
||||||
zero for a result adjusting thunk. */
|
zero for a result adjusting thunk. */
|
||||||
|
|
||||||
static tree
|
tree
|
||||||
thunk_adjust (gimple_stmt_iterator * bsi,
|
thunk_adjust (gimple_stmt_iterator * bsi,
|
||||||
tree ptr, bool this_adjusting,
|
tree ptr, bool this_adjusting,
|
||||||
HOST_WIDE_INT fixed_offset, tree virtual_offset)
|
HOST_WIDE_INT fixed_offset, tree virtual_offset)
|
||||||
|
|
@ -1907,6 +1907,7 @@ cgraph_node::assemble_thunks_and_aliases (void)
|
||||||
|
|
||||||
for (e = callers; e;)
|
for (e = callers; e;)
|
||||||
if (e->caller->thunk.thunk_p
|
if (e->caller->thunk.thunk_p
|
||||||
|
&& !e->caller->global.inlined_to
|
||||||
&& !e->caller->thunk.add_pointer_bounds_args)
|
&& !e->caller->thunk.add_pointer_bounds_args)
|
||||||
{
|
{
|
||||||
cgraph_node *thunk = e->caller;
|
cgraph_node *thunk = e->caller;
|
||||||
|
|
|
||||||
|
|
@ -2920,67 +2920,70 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
|
||||||
info = inline_summaries->get (node);
|
info = inline_summaries->get (node);
|
||||||
reset_inline_summary (node, info);
|
reset_inline_summary (node, info);
|
||||||
|
|
||||||
/* FIXME: Thunks are inlinable, but tree-inline don't know how to do that.
|
/* Estimate the stack size for the function if we're optimizing. */
|
||||||
Once this happen, we will need to more curefully predict call
|
self_stack_size = optimize && !node->thunk.thunk_p
|
||||||
statement size. */
|
? 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)
|
if (node->thunk.thunk_p)
|
||||||
{
|
{
|
||||||
struct inline_edge_summary *es = inline_edge_summary (node->callees);
|
struct inline_edge_summary *es = inline_edge_summary (node->callees);
|
||||||
struct predicate t = true_predicate ();
|
struct predicate t = true_predicate ();
|
||||||
|
|
||||||
info->inlinable = 0;
|
|
||||||
node->callees->inline_failed = CIF_THUNK;
|
node->callees->inline_failed = CIF_THUNK;
|
||||||
node->local.can_change_signature = false;
|
node->local.can_change_signature = false;
|
||||||
es->call_stmt_time = 1;
|
es->call_stmt_size = INLINE_SIZE_SCALE;
|
||||||
es->call_stmt_size = 1;
|
es->call_stmt_time = INLINE_TIME_SCALE;
|
||||||
account_size_time (info, 0, 0, &t);
|
account_size_time (info, INLINE_SIZE_SCALE * 2, INLINE_TIME_SCALE * 2, &t);
|
||||||
return;
|
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
|
else
|
||||||
{
|
{
|
||||||
/* Otherwise, inlinable functions always can change signature. */
|
/* Even is_gimple_min_invariant rely on current_function_decl. */
|
||||||
if (info->inlinable)
|
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
|
||||||
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);
|
|
||||||
|
|
||||||
|
/* 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)
|
for (e = node->callees; e; e = e->next_callee)
|
||||||
if (e->callee->comdat_local_p ())
|
if (e->callee->comdat_local_p ())
|
||||||
break;
|
break;
|
||||||
|
|
@ -2997,8 +3000,6 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
|
||||||
gcc_assert (info->time == info->self_time
|
gcc_assert (info->time == info->self_time
|
||||||
&& info->size == info->self_size);
|
&& info->size == info->self_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_cfun ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4450,6 +4450,43 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
|
||||||
}
|
}
|
||||||
goto egress;
|
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;
|
fn = cg_edge->callee->decl;
|
||||||
cg_edge->callee->get_untransformed_body ();
|
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. */
|
/* Record the function we are about to inline. */
|
||||||
id->src_fn = fn;
|
id->src_fn = fn;
|
||||||
id->src_node = cg_edge->callee;
|
|
||||||
id->src_cfun = DECL_STRUCT_FUNCTION (fn);
|
id->src_cfun = DECL_STRUCT_FUNCTION (fn);
|
||||||
id->call_stmt = stmt;
|
id->call_stmt = stmt;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue