From 61e03ffc6b8284abe34837fc85a82566ee4552ee Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 26 Jan 2011 14:06:20 +0000 Subject: [PATCH] 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 --- gcc/cgraph.c | 2 + gcc/cgraph.h | 4 ++ gcc/cgraphunit.c | 2 + gcc/config/i386/i386.c | 6 +-- gcc/ipa-cp.c | 59 ++++++++++++++++----------- gcc/ipa-inline.c | 16 ++++++++ gcc/ipa-split.c | 1 + gcc/lto-cgraph.c | 2 + gcc/testsuite/gcc.c-torture/execute/pr47237.c | 22 ++++++++++ gcc/tree-sra.c | 7 ++++ 10 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr47237.c diff --git a/gcc/cgraph.c b/gcc/cgraph.c index c8f9b04bb12..6176b4d6a45 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -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); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 33b31679535..2df3fa54d9f 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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; diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2eb3285290b..2245164c3eb 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -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) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ee1790f577a..4d927c2b259 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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)) diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index ce6fd598715..b06238d84c8 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -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); } } diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 116abd6619a..8087c81896e 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -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); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 30060440fe2..dce57eaeb63 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -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, diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 18bb83b8ad6..fb05a1d05cb 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -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); diff --git a/gcc/testsuite/gcc.c-torture/execute/pr47237.c b/gcc/testsuite/gcc.c-torture/execute/pr47237.c new file mode 100644 index 00000000000..2100e154099 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr47237.c @@ -0,0 +1,22 @@ +#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; +} diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index c2ec2042932..47613f6298a 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -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) -- 2.11.4.GIT