Commit bc0ec027 by Jan Hubicka Committed by Jan Hubicka

cgraphunit.c (add_new_function): Fix logic when adding from late IPA pass.


	* cgraphunit.c (add_new_function): Fix logic when adding from
	late IPA pass.
	(assemble_thunk): Rename to ...
	(expand_thunk); .. this one; export; get it working with general functions;
	make produced gimple valid.
	* cgraph.h (expand_thunk): Declare.

From-SVN: r201463
parent 0e8853ee
2013-08-02 Jan Hubicka <jh@suse.cz> 2013-08-02 Jan Hubicka <jh@suse.cz>
* cgraphunit.c (add_new_function): Fix logic when adding from
late IPA pass.
(assemble_thunk): Rename to ...
(expand_thunk); .. this one; export; get it working with general functions;
make produced gimple valid.
* cgraph.h (expand_thunk): Declare.
2013-08-02 Jan Hubicka <jh@suse.cz>
* ipa-cp.c (gather_context_independent_values): Use ipa_get_param_move_cost. * ipa-cp.c (gather_context_independent_values): Use ipa_get_param_move_cost.
(get_replacement_map): Remove PARAM; move parameter folding into tree-inline.c (get_replacement_map): Remove PARAM; move parameter folding into tree-inline.c
(create_specialized_node): Update. (create_specialized_node): Update.
......
...@@ -716,6 +716,7 @@ void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree); ...@@ -716,6 +716,7 @@ void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree);
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); basic_block init_lowered_empty_function (tree, bool);
void cgraph_reset_node (struct cgraph_node *); void cgraph_reset_node (struct cgraph_node *);
void expand_thunk (struct cgraph_node *);
/* In cgraphclones.c */ /* In cgraphclones.c */
......
...@@ -323,13 +323,10 @@ cgraph_process_new_functions (void) ...@@ -323,13 +323,10 @@ cgraph_process_new_functions (void)
if (!node->symbol.analyzed) if (!node->symbol.analyzed)
analyze_function (node); analyze_function (node);
push_cfun (DECL_STRUCT_FUNCTION (fndecl)); push_cfun (DECL_STRUCT_FUNCTION (fndecl));
if ((cgraph_state == CGRAPH_STATE_IPA_SSA if (cgraph_state == CGRAPH_STATE_IPA_SSA
&& !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
/* When not optimizing, be sure we run early local passes anyway
to expand OMP. */
|| !optimize)
execute_pass_list (pass_early_local_passes.pass.sub); execute_pass_list (pass_early_local_passes.pass.sub);
else else if (inline_summary_vec != NULL)
compute_inline_parameters (node, true); compute_inline_parameters (node, true);
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
...@@ -1327,8 +1324,8 @@ thunk_adjust (gimple_stmt_iterator * bsi, ...@@ -1327,8 +1324,8 @@ thunk_adjust (gimple_stmt_iterator * bsi,
/* Produce assembler for thunk NODE. */ /* Produce assembler for thunk NODE. */
static void void
assemble_thunk (struct cgraph_node *node) expand_thunk (struct cgraph_node *node)
{ {
bool this_adjusting = node->thunk.this_adjusting; bool this_adjusting = node->thunk.this_adjusting;
HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset; HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
...@@ -1420,7 +1417,9 @@ assemble_thunk (struct cgraph_node *node) ...@@ -1420,7 +1417,9 @@ assemble_thunk (struct cgraph_node *node)
/* Build call to the function being thunked. */ /* Build call to the function being thunked. */
if (!VOID_TYPE_P (restype)) if (!VOID_TYPE_P (restype))
{ {
if (!is_gimple_reg_type (restype)) if (DECL_BY_REFERENCE (resdecl))
restmp = gimple_fold_indirect_ref (resdecl);
else if (!is_gimple_reg_type (restype))
{ {
restmp = resdecl; restmp = resdecl;
add_local_decl (cfun, restmp); add_local_decl (cfun, restmp);
...@@ -1436,74 +1435,91 @@ assemble_thunk (struct cgraph_node *node) ...@@ -1436,74 +1435,91 @@ assemble_thunk (struct cgraph_node *node)
if (this_adjusting) if (this_adjusting)
vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset, vargs.quick_push (thunk_adjust (&bsi, a, 1, fixed_offset,
virtual_offset)); virtual_offset));
else else if (nargs)
vargs.quick_push (a); vargs.quick_push (a);
for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
vargs.quick_push (arg); if (nargs)
for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
vargs.quick_push (arg);
call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs); call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
vargs.release (); vargs.release ();
gimple_call_set_from_thunk (call, true); gimple_call_set_from_thunk (call, true);
if (restmp) if (restmp)
gimple_call_set_lhs (call, restmp); {
gimple_call_set_lhs (call, restmp);
gcc_assert (useless_type_conversion_p (TREE_TYPE (restmp),
TREE_TYPE (TREE_TYPE (alias))));
}
gsi_insert_after (&bsi, call, GSI_NEW_STMT); gsi_insert_after (&bsi, call, GSI_NEW_STMT);
if (!(gimple_call_flags (call) & ECF_NORETURN))
{
if (restmp && !this_adjusting
&& (fixed_offset || virtual_offset))
{
tree true_label = NULL_TREE;
if (restmp && !this_adjusting) if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
{ {
tree true_label = NULL_TREE; gimple stmt;
/* If the return type is a pointer, we need to
protect against NULL. We know there will be an
adjustment, because that's why we're emitting a
thunk. */
then_bb = create_basic_block (NULL, (void *) 0, bb);
return_bb = create_basic_block (NULL, (void *) 0, then_bb);
else_bb = create_basic_block (NULL, (void *) 0, else_bb);
add_bb_to_loop (then_bb, bb->loop_father);
add_bb_to_loop (return_bb, bb->loop_father);
add_bb_to_loop (else_bb, bb->loop_father);
remove_edge (single_succ_edge (bb));
true_label = gimple_block_label (then_bb);
stmt = gimple_build_cond (NE_EXPR, restmp,
build_zero_cst (TREE_TYPE (restmp)),
NULL_TREE, NULL_TREE);
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
make_edge (bb, then_bb, EDGE_TRUE_VALUE);
make_edge (bb, else_bb, EDGE_FALSE_VALUE);
make_edge (return_bb, EXIT_BLOCK_PTR, 0);
make_edge (then_bb, return_bb, EDGE_FALLTHRU);
make_edge (else_bb, return_bb, EDGE_FALLTHRU);
bsi = gsi_last_bb (then_bb);
}
if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE) restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
{ fixed_offset, virtual_offset);
gimple stmt; if (true_label)
/* If the return type is a pointer, we need to {
protect against NULL. We know there will be an gimple stmt;
adjustment, because that's why we're emitting a bsi = gsi_last_bb (else_bb);
thunk. */ stmt = gimple_build_assign (restmp,
then_bb = create_basic_block (NULL, (void *) 0, bb); build_zero_cst (TREE_TYPE (restmp)));
return_bb = create_basic_block (NULL, (void *) 0, then_bb); gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
else_bb = create_basic_block (NULL, (void *) 0, else_bb); bsi = gsi_last_bb (return_bb);
add_bb_to_loop (then_bb, bb->loop_father); }
add_bb_to_loop (return_bb, bb->loop_father);
add_bb_to_loop (else_bb, bb->loop_father);
remove_edge (single_succ_edge (bb));
true_label = gimple_block_label (then_bb);
stmt = gimple_build_cond (NE_EXPR, restmp,
build_zero_cst (TREE_TYPE (restmp)),
NULL_TREE, NULL_TREE);
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
make_edge (bb, then_bb, EDGE_TRUE_VALUE);
make_edge (bb, else_bb, EDGE_FALSE_VALUE);
make_edge (return_bb, EXIT_BLOCK_PTR, 0);
make_edge (then_bb, return_bb, EDGE_FALLTHRU);
make_edge (else_bb, return_bb, EDGE_FALLTHRU);
bsi = gsi_last_bb (then_bb);
} }
else
gimple_call_set_tail (call, true);
restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0, /* Build return value. */
fixed_offset, virtual_offset); ret = gimple_build_return (restmp);
if (true_label) gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
{
gimple stmt;
bsi = gsi_last_bb (else_bb);
stmt = gimple_build_assign (restmp,
build_zero_cst (TREE_TYPE (restmp)));
gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
bsi = gsi_last_bb (return_bb);
}
} }
else else
gimple_call_set_tail (call, true); {
gimple_call_set_tail (call, true);
/* Build return value. */ remove_edge (single_succ_edge (bb));
ret = gimple_build_return (restmp); }
gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
delete_unreachable_blocks (); delete_unreachable_blocks ();
update_ssa (TODO_update_ssa); update_ssa (TODO_update_ssa);
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
/* Since we want to emit the thunk, we explicitly mark its name as /* Since we want to emit the thunk, we explicitly mark its name as
referenced. */ referenced. */
node->thunk.thunk_p = false; node->thunk.thunk_p = false;
cgraph_node_remove_callees (node); rebuild_cgraph_edges ();
cgraph_add_new_function (thunk_fndecl, true); cgraph_add_new_function (thunk_fndecl, true);
bitmap_obstack_release (NULL); bitmap_obstack_release (NULL);
} }
...@@ -1511,8 +1527,6 @@ assemble_thunk (struct cgraph_node *node) ...@@ -1511,8 +1527,6 @@ assemble_thunk (struct cgraph_node *node)
set_cfun (NULL); set_cfun (NULL);
} }
/* Assemble thunks and aliases associated to NODE. */ /* Assemble thunks and aliases associated to NODE. */
static void static void
...@@ -1529,7 +1543,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node) ...@@ -1529,7 +1543,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
e = e->next_caller; e = e->next_caller;
assemble_thunks_and_aliases (thunk); assemble_thunks_and_aliases (thunk);
assemble_thunk (thunk); expand_thunk (thunk);
} }
else else
e = e->next_caller; e = e->next_caller;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment