Commit 61e03ffc by Jan Hubicka

re PR tree-optimization/47237 (builtin_apply_args broken WRT local ABI changes.)

	PR target/47237
	* cgraph.h (cgraph_local_info): New field can_change_signature.
	* ipa-cp.c (ipcp_update_callgraph): Only compute args_to_skip if callee
	signature can change.
	(ipcp_estimate_growth): Call sequence simplify only if calle signature
	can change.
	(ipcp_insert_stage): Only compute args_to_skip if signature can change.
	(cgraph_function_versioning): We can not change signature of functions
	that don't allow that.
	* lto-cgraph.c (lto_output_node): Stream local.can_change_signature.
	(lto_input_node): Likewise.
	* ipa-inline.c (compute_inline_parameters): Compute local.can_change_signature.
	* ipa-split.c (visit_bb): Never split away APPLY_ARGS.
	* tree-sra.c (ipa_sra_preliminary_function_checks): Give up on functions
	that can not change signature.
	* i386.c (ix86_function_regparm, ix86_function_sseregparm,
	init_cumulative_args): Do not use local calling conventions for functions
	that can not change signature.

From-SVN: r169290
parent 980ca891
......@@ -2300,6 +2300,8 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
if (!flag_wpa)
gcc_checking_assert (tree_versionable_function_p (old_decl));
gcc_assert (old_node->local.can_change_signature || !args_to_skip);
/* Make a new FUNCTION_DECL tree node */
if (!args_to_skip)
new_decl = copy_node (old_decl);
......
......@@ -114,6 +114,10 @@ struct GTY(()) cgraph_local_info {
Currently computed and used only by ipa-cp. */
unsigned versionable : 1;
/* False when function calling convention and signature can not be changed.
This is the case when __builtin_apply_args is used. */
unsigned can_change_signature : 1;
/* True when function should be inlined independently on its size. */
unsigned disregard_inline_limits : 1;
......
......@@ -2014,6 +2014,8 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
if (!tree_versionable_function_p (old_decl))
return NULL;
gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
/* Make a new FUNCTION_DECL tree node for the
new version. */
if (!args_to_skip)
......
......@@ -5493,7 +5493,7 @@ ix86_function_regparm (const_tree type, const_tree decl)
{
/* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */
struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE (decl));
if (i && i->local)
if (i && i->local && i->can_change_signature)
{
int local_regparm, globals = 0, regno;
......@@ -5570,7 +5570,7 @@ ix86_function_sseregparm (const_tree type, const_tree decl, bool warn)
{
/* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */
struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE(decl));
if (i && i->local)
if (i && i->local && i->can_change_signature)
return TARGET_SSE2 ? 2 : 1;
}
......@@ -5954,7 +5954,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
va_start so for local functions maybe_vaarg can be made aggressive
helping K&R code.
FIXME: once typesytem is fixed, we won't need this code anymore. */
if (i && i->local)
if (i && i->local && i->can_change_signature)
fntype = TREE_TYPE (fndecl);
cum->maybe_vaarg = (fntype
? (!prototype_p (fntype) || stdarg_p (fntype))
......@@ -1040,25 +1040,29 @@ ipcp_update_callgraph (void)
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed && ipcp_node_is_clone (node))
{
bitmap args_to_skip = BITMAP_ALLOC (NULL);
bitmap args_to_skip = NULL;
struct cgraph_node *orig_node = ipcp_get_orig_node (node);
struct ipa_node_params *info = IPA_NODE_REF (orig_node);
int i, count = ipa_get_param_count (info);
struct cgraph_edge *cs, *next;
for (i = 0; i < count; i++)
if (node->local.can_change_signature)
{
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
/* We can proactively remove obviously unused arguments. */
if (!ipa_is_param_used (info, i))
args_to_skip = BITMAP_ALLOC (NULL);
for (i = 0; i < count; i++)
{
bitmap_set_bit (args_to_skip, i);
continue;
}
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
/* We can proactively remove obviously unused arguments. */
if (!ipa_is_param_used (info, i))
{
bitmap_set_bit (args_to_skip, i);
continue;
}
if (lat->type == IPA_CONST_VALUE)
bitmap_set_bit (args_to_skip, i);
if (lat->type == IPA_CONST_VALUE)
bitmap_set_bit (args_to_skip, i);
}
}
for (cs = node->callers; cs; cs = next)
{
......@@ -1130,17 +1134,18 @@ ipcp_estimate_growth (struct cgraph_node *node)
info = IPA_NODE_REF (node);
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
if (node->local.can_change_signature)
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
/* We can proactively remove obviously unused arguments. */
if (!ipa_is_param_used (info, i))
removable_args++;
/* We can proactively remove obviously unused arguments. */
if (!ipa_is_param_used (info, i))
removable_args++;
if (lat->type == IPA_CONST_VALUE)
removable_args++;
}
if (lat->type == IPA_CONST_VALUE)
removable_args++;
}
/* We make just very simple estimate of savings for removal of operand from
call site. Precise cost is dificult to get, as our size metric counts
......@@ -1386,16 +1391,21 @@ ipcp_insert_stage (void)
count = ipa_get_param_count (info);
replace_trees = VEC_alloc (ipa_replace_map_p, gc, 1);
args_to_skip = BITMAP_GGC_ALLOC ();
if (node->local.can_change_signature)
args_to_skip = BITMAP_GGC_ALLOC ();
else
args_to_skip = NULL;
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
parm_tree = ipa_get_param (info, i);
/* We can proactively remove obviously unused arguments. */
if (!ipa_is_param_used (info, i))
if (!ipa_is_param_used (info, i))
{
bitmap_set_bit (args_to_skip, i);
if (args_to_skip)
bitmap_set_bit (args_to_skip, i);
continue;
}
......@@ -1404,7 +1414,8 @@ ipcp_insert_stage (void)
replace_param =
ipcp_create_replace_map (parm_tree, lat);
VEC_safe_push (ipa_replace_map_p, gc, replace_trees, replace_param);
bitmap_set_bit (args_to_skip, i);
if (args_to_skip)
bitmap_set_bit (args_to_skip, i);
}
}
......
......@@ -1997,6 +1997,22 @@ compute_inline_parameters (struct cgraph_node *node)
/* Can this function be inlined at all? */
node->local.inlinable = tree_inlinable_function_p (node->decl);
/* Inlinable functions always can change signature. */
if (node->local.inlinable)
node->local.can_change_signature = true;
else
{
struct cgraph_edge *e;
/* Functions calling builtlin_apply can not change signature. */
for (e = node->callees; e; e = e->next_callee)
if (DECL_BUILT_IN (e->callee->decl)
&& DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_APPLY_ARGS)
break;
node->local.can_change_signature = !e;
}
if (node->local.inlinable && !node->local.disregard_inline_limits)
node->local.disregard_inline_limits
= DECL_DISREGARD_INLINE_LIMITS (node->decl);
......
......@@ -670,6 +670,7 @@ visit_bb (basic_block bb, basic_block return_bb,
way to store builtin_stack_save result in non-SSA variable
since all calls to those are compiler generated. */
case BUILT_IN_APPLY:
case BUILT_IN_APPLY_ARGS:
case BUILT_IN_VA_START:
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
......
......@@ -499,6 +499,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->local.finalized, 1);
bp_pack_value (&bp, node->local.inlinable, 1);
bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 1);
bp_pack_value (&bp, node->local.disregard_inline_limits, 1);
bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
bp_pack_value (&bp, node->local.vtable_method, 1);
......@@ -950,6 +951,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->local.finalized = bp_unpack_value (bp, 1);
node->local.inlinable = bp_unpack_value (bp, 1);
node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = bp_unpack_value (bp, 1);
node->local.disregard_inline_limits = bp_unpack_value (bp, 1);
node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
node->local.vtable_method = bp_unpack_value (bp, 1);
......
#define INTEGER_ARG 5
extern void abort(void);
static void foo(int arg)
{
if (arg != INTEGER_ARG)
abort();
}
static void bar(int arg)
{
foo(arg);
__builtin_apply(foo, __builtin_apply_args(), 16);
}
int main(void)
{
bar(INTEGER_ARG);
return 0;
}
......@@ -4425,6 +4425,13 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
return false;
}
if (!node->local.can_change_signature)
{
if (dump_file)
fprintf (dump_file, "Function can not change signature.\n");
return false;
}
if (!tree_versionable_function_p (node->decl))
{
if (dump_file)
......
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