Message ID | 20110902124257.GB21553@virgil.arch.suse.de |
---|---|
State | New |
Headers | show |
On Fri, Sep 2, 2011 at 2:42 PM, Martin Jambor <mjambor@suse.cz> wrote: > Hi, > > On Wed, Aug 31, 2011 at 09:33:03AM +0200, Richard Guenther wrote: >> On Tue, Aug 30, 2011 at 6:50 PM, Martin Jambor <mjambor@suse.cz> wrote: >> > Ping. Re-bootstrapped and re-tested yesterday on x86_64-linux. >> >> Ok. Does this also apply (maybe in modifed form) to the 4.6 branch? >> > > Below is a modified patch for the 4.6 branch. It already has the fix > for PR 50260 that my trunk patch introduced and its testcase. It also > makes ipa-split test for type attributes itself rather than doing it > in ipa-inline-analysis.c because there is no such file in 4.6 and I > did not want to change meaning of flags on the branch. > > Bootstrapped and tested on x86_64-linux, OK for the branch? Ok. Thanks, Richard. > Thanks, > > Martin > > > > 2011-09-01 Martin Jambor <mjambor@suse.cz> > > PR middle-end/49886 > * ipa-split.c (split_function): Do not skip any arguments if > can_change_signature is set or there are function type attributes. > > * testsuite/gcc.c-torture/execute/pr49886.c: New testcase. > * testsuite/gfortran.fortran-torture/compile/pr50260.f90: Likewise. > > Index: gcc/testsuite/gcc.c-torture/execute/pr49886.c > =================================================================== > --- gcc/testsuite/gcc.c-torture/execute/pr49886.c (revision 0) > +++ gcc/testsuite/gcc.c-torture/execute/pr49886.c (revision 0) > @@ -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); > +} > + > Index: gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 > =================================================================== > --- gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 (revision 0) > +++ gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 (revision 0) > @@ -0,0 +1,48 @@ > +MODULE cp_parser_methods > + INTEGER, PARAMETER :: default_string_length=80 > + INTEGER, PARAMETER :: default_path_length=250 > + TYPE ilist_type > + LOGICAL :: in_use > + END TYPE ilist_type > + TYPE cp_parser_type > + CHARACTER(LEN=default_path_length) :: ifn > + INTEGER :: icol,icol1,icol2 > + TYPE(ilist_type), POINTER :: ilist > + END TYPE cp_parser_type > + TYPE cp_error_type > + END TYPE cp_error_type > +CONTAINS > + FUNCTION cts(i) RESULT(res) > + CHARACTER(len=6) :: res > + END FUNCTION cts > + FUNCTION parser_location(parser,error) RESULT(res) > + TYPE(cp_parser_type), POINTER :: parser > + TYPE(cp_error_type), INTENT(inout) :: error > + CHARACTER(len=default_path_length+default_string_length) :: res > + LOGICAL :: failure > + IF (.NOT. failure) THEN > + res="file:'"//TRIM(parser%ifn)//"' line:"//cts(parser%icol) > + END IF > + END FUNCTION parser_location > + SUBROUTINE parser_get_integer(parser,at_end, error) > + TYPE(cp_parser_type), POINTER :: parser > + TYPE(cp_error_type), INTENT(inout) :: error > + LOGICAL :: failure, my_at_end > + IF (.NOT.failure) THEN > + IF (.NOT.parser%ilist%in_use) THEN > + CALL cp_assert("A"// TRIM(parser_location(parser,error))) > + END IF > + END IF > + END SUBROUTINE parser_get_integer > + SUBROUTINE parser_get_string(parser,at_end,error) > + TYPE(cp_parser_type), POINTER :: parser > + LOGICAL, INTENT(out), OPTIONAL :: at_end > + TYPE(cp_error_type), INTENT(inout) :: error > + LOGICAL :: failure, my_at_end > + IF (.NOT.failure) THEN > + IF (PRESENT(at_end)) THEN > + CALL cp_assert("s"//TRIM(parser_location(parser,error))) > + END IF > + END IF > + END SUBROUTINE parser_get_string > +END MODULE cp_parser_methods > Index: gcc/ipa-split.c > =================================================================== > --- gcc/ipa-split.c (revision 178386) > +++ gcc/ipa-split.c (working copy) > @@ -943,10 +943,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_node (current_function_decl); > basic_block return_bb = find_return_bb (); > basic_block call_bb; > gimple_stmt_iterator gsi; > @@ -966,17 +966,34 @@ split_function (struct split_point *spli > dump_split_point (dump_file, split_point); > } > > + if (cur_node->local.can_change_signature > + && !TYPE_ATTRIBUTES (TREE_TYPE (cur_node->decl))) > + 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) > + { > + /* This parm wasn't used up to now, but is going to be used, > + hence register it. */ > + add_referenced_var (parm); > + 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))) > { > @@ -1057,9 +1074,7 @@ split_function (struct split_point *spli > > /* Now create the actual clone. */ > rebuild_cgraph_edges (); > - node = cgraph_function_versioning (cgraph_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 > @@ -1070,7 +1085,7 @@ split_function (struct split_point *spli > DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN; > DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0; > } > - cgraph_node_remove_callees (cgraph_node (current_function_decl)); > + cgraph_node_remove_callees (cur_node); > if (!split_part_return_p) > TREE_THIS_VOLATILE (node->decl) = 1; > if (dump_file) >
Index: gcc/testsuite/gcc.c-torture/execute/pr49886.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/pr49886.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr49886.c (revision 0) @@ -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); +} + Index: gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 =================================================================== --- gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 (revision 0) +++ gcc/testsuite/gfortran.fortran-torture/compile/pr50260.f90 (revision 0) @@ -0,0 +1,48 @@ +MODULE cp_parser_methods + INTEGER, PARAMETER :: default_string_length=80 + INTEGER, PARAMETER :: default_path_length=250 + TYPE ilist_type + LOGICAL :: in_use + END TYPE ilist_type + TYPE cp_parser_type + CHARACTER(LEN=default_path_length) :: ifn + INTEGER :: icol,icol1,icol2 + TYPE(ilist_type), POINTER :: ilist + END TYPE cp_parser_type + TYPE cp_error_type + END TYPE cp_error_type +CONTAINS + FUNCTION cts(i) RESULT(res) + CHARACTER(len=6) :: res + END FUNCTION cts + FUNCTION parser_location(parser,error) RESULT(res) + TYPE(cp_parser_type), POINTER :: parser + TYPE(cp_error_type), INTENT(inout) :: error + CHARACTER(len=default_path_length+default_string_length) :: res + LOGICAL :: failure + IF (.NOT. failure) THEN + res="file:'"//TRIM(parser%ifn)//"' line:"//cts(parser%icol) + END IF + END FUNCTION parser_location + SUBROUTINE parser_get_integer(parser,at_end, error) + TYPE(cp_parser_type), POINTER :: parser + TYPE(cp_error_type), INTENT(inout) :: error + LOGICAL :: failure, my_at_end + IF (.NOT.failure) THEN + IF (.NOT.parser%ilist%in_use) THEN + CALL cp_assert("A"// TRIM(parser_location(parser,error))) + END IF + END IF + END SUBROUTINE parser_get_integer + SUBROUTINE parser_get_string(parser,at_end,error) + TYPE(cp_parser_type), POINTER :: parser + LOGICAL, INTENT(out), OPTIONAL :: at_end + TYPE(cp_error_type), INTENT(inout) :: error + LOGICAL :: failure, my_at_end + IF (.NOT.failure) THEN + IF (PRESENT(at_end)) THEN + CALL cp_assert("s"//TRIM(parser_location(parser,error))) + END IF + END IF + END SUBROUTINE parser_get_string +END MODULE cp_parser_methods Index: gcc/ipa-split.c =================================================================== --- gcc/ipa-split.c (revision 178386) +++ gcc/ipa-split.c (working copy) @@ -943,10 +943,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_node (current_function_decl); basic_block return_bb = find_return_bb (); basic_block call_bb; gimple_stmt_iterator gsi; @@ -966,17 +966,34 @@ split_function (struct split_point *spli dump_split_point (dump_file, split_point); } + if (cur_node->local.can_change_signature + && !TYPE_ATTRIBUTES (TREE_TYPE (cur_node->decl))) + 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) + { + /* This parm wasn't used up to now, but is going to be used, + hence register it. */ + add_referenced_var (parm); + 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))) { @@ -1057,9 +1074,7 @@ split_function (struct split_point *spli /* Now create the actual clone. */ rebuild_cgraph_edges (); - node = cgraph_function_versioning (cgraph_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 @@ -1070,7 +1085,7 @@ split_function (struct split_point *spli DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN; DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0; } - cgraph_node_remove_callees (cgraph_node (current_function_decl)); + cgraph_node_remove_callees (cur_node); if (!split_part_return_p) TREE_THIS_VOLATILE (node->decl) = 1; if (dump_file)