aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2016-05-08 20:44:02 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2016-05-08 18:44:02 +0000
commit6bbf39b789101366bccacda4f912b05636f03887 (patch)
tree6fd631ddca25c1c6908f1589de9b99b80f6a38b4 /gcc
parent3b695ba657799e3723a892a5fec1a1fb2061c63c (diff)
downloadgcc-6bbf39b789101366bccacda4f912b05636f03887.zip
gcc-6bbf39b789101366bccacda4f912b05636f03887.tar.gz
gcc-6bbf39b789101366bccacda4f912b05636f03887.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/cgraph.h1
-rw-r--r--gcc/cgraphclones.c1
-rw-r--r--gcc/cgraphunit.c3
-rw-r--r--gcc/ipa-inline-analysis.c107
-rw-r--r--gcc/tree-inline.c38
6 files changed, 106 insertions, 55 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c562800..1f985ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
PR target/70998
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index d714ad7..8ad9f45 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 10f2d34..43ee735 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 5761880..4bfcad7 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 47b5b96..17b21d1 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 da233b2..2ee3f63 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;