aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@gcc.gnu.org>2011-01-26 14:06:20 +0000
committerJan Hubicka <hubicka@gcc.gnu.org>2011-01-26 14:06:20 +0000
commit61e03ffc6b8284abe34837fc85a82566ee4552ee (patch)
tree4e831ce4ac2924d53233e6215470e4dbd88eea9a
parent980ca89173da230e449a8e8017f0b2c2b46a374a (diff)
downloadgcc-61e03ffc6b8284abe34837fc85a82566ee4552ee.zip
gcc-61e03ffc6b8284abe34837fc85a82566ee4552ee.tar.gz
gcc-61e03ffc6b8284abe34837fc85a82566ee4552ee.tar.bz2
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
-rw-r--r--gcc/cgraph.c2
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/cgraphunit.c2
-rw-r--r--gcc/config/i386/i386.c6
-rw-r--r--gcc/ipa-cp.c59
-rw-r--r--gcc/ipa-inline.c16
-rw-r--r--gcc/ipa-split.c1
-rw-r--r--gcc/lto-cgraph.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr47237.c22
-rw-r--r--gcc/tree-sra.c7
10 files changed, 94 insertions, 27 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index c8f9b04..6176b4d 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 33b3167..2df3fa5 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 2eb3285..2245164 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 ee1790f..4d927c2 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 ce6fd59..b06238d 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 116abd6..8087c81 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 3006044..dce57ea 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 18bb83b..fb05a1d 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 0000000..2100e15
--- /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 c2ec204..47613f6 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)