summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-31 17:17:19 +0000
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-31 17:17:19 +0000
commit982ffd8d9a1d9df5d91298d89d38293f4f3c86b4 (patch)
treea322acd3f7b7a719b28233053d2eace8859ab328
parent0a31490eb184a86a9a05a144cf8c6b6f1769d1ad (diff)
downloadgcc-982ffd8d9a1d9df5d91298d89d38293f4f3c86b4.tar.gz
2011-08-31 Martin Jambor <mjambor@suse.cz>
PR middle-end/49886 * ipa-inline-analysis.c (compute_inline_parameters): Set can_change_signature of noes with typde attributes. * ipa-split.c (split_function): Do not skip any arguments if can_change_signature is set. * testsuite/gcc.c-torture/execute/pr49886.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178386 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/ipa-inline-analysis.c30
-rw-r--r--gcc/ipa-split.c31
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr49886.c100
5 files changed, 154 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 60bb4b53047..afb213b586b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2011-08-31 Martin Jambor <mjambor@suse.cz>
+ PR middle-end/49886
+ * ipa-inline-analysis.c (compute_inline_parameters): Set
+ can_change_signature of noes with typde attributes.
+ * ipa-split.c (split_function): Do not skip any arguments if
+ can_change_signature is set.
+
+2011-08-31 Martin Jambor <mjambor@suse.cz>
+
* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Alias
check removed.
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index c0eacbb62fd..b56c66944e5 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1660,18 +1660,28 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
/* Can this function be inlined at all? */
info->inlinable = tree_inlinable_function_p (node->decl);
- /* Inlinable functions always can change signature. */
- if (info->inlinable)
- node->local.can_change_signature = true;
+ /* Type attributes can use parameter indices to describe them. */
+ if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
+ node->local.can_change_signature = false;
else
{
- /* Functions calling builtin_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;
+ /* 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);
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index 7413d81aeee..4373a1b423e 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -945,10 +945,10 @@ static void
split_function (struct split_point *split_point)
{
VEC (tree, heap) *args_to_pass = NULL;
- bitmap args_to_skip = BITMAP_ALLOC (NULL);
+ bitmap args_to_skip;
tree parm;
int num = 0;
- struct cgraph_node *node;
+ struct cgraph_node *node, *cur_node = cgraph_get_node (current_function_decl);
basic_block return_bb = find_return_bb ();
basic_block call_bb;
gimple_stmt_iterator gsi;
@@ -968,17 +968,30 @@ split_function (struct split_point *split_point)
dump_split_point (dump_file, split_point);
}
+ if (cur_node->local.can_change_signature)
+ args_to_skip = BITMAP_ALLOC (NULL);
+ else
+ args_to_skip = NULL;
+
/* Collect the parameters of new function and args_to_skip bitmap. */
for (parm = DECL_ARGUMENTS (current_function_decl);
parm; parm = DECL_CHAIN (parm), num++)
- if (!is_gimple_reg (parm)
- || !gimple_default_def (cfun, parm)
- || !bitmap_bit_p (split_point->ssa_names_to_pass,
- SSA_NAME_VERSION (gimple_default_def (cfun, parm))))
+ if (args_to_skip
+ && (!is_gimple_reg (parm)
+ || !gimple_default_def (cfun, parm)
+ || !bitmap_bit_p (split_point->ssa_names_to_pass,
+ SSA_NAME_VERSION (gimple_default_def (cfun,
+ parm)))))
bitmap_set_bit (args_to_skip, num);
else
{
arg = gimple_default_def (cfun, parm);
+ if (!arg)
+ {
+ arg = make_ssa_name (parm, gimple_build_nop ());
+ set_default_def (parm, arg);
+ }
+
if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
!= TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
{
@@ -1081,9 +1094,7 @@ split_function (struct split_point *split_point)
/* Now create the actual clone. */
rebuild_cgraph_edges ();
- node = cgraph_function_versioning (cgraph_get_node (current_function_decl),
- NULL, NULL,
- args_to_skip,
+ node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip,
split_point->split_bbs,
split_point->entry_bb, "part");
/* For usual cloning it is enough to clear builtin only when signature
@@ -1094,7 +1105,7 @@ split_function (struct split_point *split_point)
DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
}
- cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
+ cgraph_node_remove_callees (cur_node);
if (!split_part_return_p)
TREE_THIS_VOLATILE (node->decl) = 1;
if (dump_file)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7fa86ebee80..05ee81bc9b1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-08-31 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/49886
+ * gcc.c-torture/execute/pr49886.c: New testcase.
+
2011-08-31 Tom de Vries <tom@codesourcery.com>
PR middle-end/43513
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr49886.c b/gcc/testsuite/gcc.c-torture/execute/pr49886.c
new file mode 100644
index 00000000000..9e9ceb26294
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr49886.c
@@ -0,0 +1,100 @@
+struct PMC {
+ unsigned flags;
+};
+
+typedef struct Pcc_cell
+{
+ struct PMC *p;
+ long bla;
+ long type;
+} Pcc_cell;
+
+int gi;
+int cond;
+
+extern void abort ();
+extern void never_ever(int interp, struct PMC *pmc)
+ __attribute__((noinline,noclone));
+
+void never_ever (int interp, struct PMC *pmc)
+{
+ abort ();
+}
+
+static void mark_cell(int * interp, Pcc_cell *c)
+ __attribute__((__nonnull__(1)));
+
+static void
+mark_cell(int * interp, Pcc_cell *c)
+{
+ if (!cond)
+ return;
+
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<18)))
+ never_ever(gi + 1, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<17)))
+ never_ever(gi + 2, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<16)))
+ never_ever(gi + 3, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<15)))
+ never_ever(gi + 4, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<14)))
+ never_ever(gi + 5, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<13)))
+ never_ever(gi + 6, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<12)))
+ never_ever(gi + 7, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<11)))
+ never_ever(gi + 8, c->p);
+ if (c && c->type == 4 && c->p
+ && !(c->p->flags & (1<<10)))
+ never_ever(gi + 9, c->p);
+}
+
+static void
+foo(int * interp, Pcc_cell *c)
+{
+ mark_cell(interp, c);
+}
+
+static struct Pcc_cell *
+__attribute__((noinline,noclone))
+getnull(void)
+{
+ return (struct Pcc_cell *) 0;
+}
+
+
+int main()
+{
+ int i;
+
+ cond = 1;
+ for (i = 0; i < 100; i++)
+ foo (&gi, getnull ());
+ return 0;
+}
+
+
+void
+bar_1 (int * interp, Pcc_cell *c)
+{
+ c->bla += 1;
+ mark_cell(interp, c);
+}
+
+void
+bar_2 (int * interp, Pcc_cell *c)
+{
+ c->bla += 2;
+ mark_cell(interp, c);
+}
+