re PR middle-end/49886 (pass_split_functions cannot deal with function type attributes)
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. From-SVN: r178386
This commit is contained in:
parent
51093fca4c
commit
201176d348
|
@ -1,3 +1,11 @@
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue