diff options
author | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-09-02 15:37:38 +0000 |
---|---|---|
committer | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-09-02 15:37:38 +0000 |
commit | 03f99d3c9c661055b5308b39a6939ae8598f604f (patch) | |
tree | c5080ee359d717b439069963cb722bd18f086222 /gcc | |
parent | d6b19f6bc6c71621f8c894b07706e14e1301cb39 (diff) | |
download | gcc-03f99d3c9c661055b5308b39a6939ae8598f604f.tar.gz |
2011-09-02 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (ipa_node_params): Removed fields
called_with_var_arguments and node_versionable.
(ipa_set_called_with_variable_arg): Removed.
(ipa_is_called_with_var_arguments): Likewise.
* ipa-cp.c (ipa_get_lattice): Fixed index check in an assert.
(determine_versionability): Do not check for type attributes and va
builtins. Record versionability into inline summary.
(initialize_node_lattices): Do not check
ipa_is_called_with_var_arguments.
(propagate_constants_accross_call): Likewise, ignore arguments we do
not have PARM_DECLs for, set variable flag for parameters that were
not passed a value.
(create_specialized_node): Dump info that we cannot change signature.
* ipa-prop.c (ipa_compute_jump_functions): Do not care about variable
number of arguments.
(ipa_make_edge_direct_to_target): Likewise.
(ipa_update_after_lto_read): Likewise.
(ipa_node_duplication_hook): Do not copy called_with_var_arguments flag.
* tree-inline.c (copy_arguments_for_versioning): Copy PARM_DECLs if
they were remapped.
* testsuite/gcc.dg/ipa/ipcp-3.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178485 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/ipa-cp.c | 48 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 31 | ||||
-rw-r--r-- | gcc/ipa-prop.h | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/ipcp-3.c | 70 | ||||
-rw-r--r-- | gcc/tree-inline.c | 2 |
7 files changed, 119 insertions, 80 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a54f1d13895..959a4a623b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2011-09-02 Martin Jambor <mjambor@suse.cz> + + * ipa-prop.h (ipa_node_params): Removed fields + called_with_var_arguments and node_versionable. + (ipa_set_called_with_variable_arg): Removed. + (ipa_is_called_with_var_arguments): Likewise. + * ipa-cp.c (ipa_get_lattice): Fixed index check in an assert. + (determine_versionability): Do not check for type attributes and va + builtins. Record versionability into inline summary. + (initialize_node_lattices): Do not check + ipa_is_called_with_var_arguments. + (propagate_constants_accross_call): Likewise, ignore arguments we do + not have PARM_DECLs for, set variable flag for parameters that were + not passed a value. + (create_specialized_node): Dump info that we cannot change signature. + * ipa-prop.c (ipa_compute_jump_functions): Do not care about variable + number of arguments. + (ipa_make_edge_direct_to_target): Likewise. + (ipa_update_after_lto_read): Likewise. + (ipa_node_duplication_hook): Do not copy called_with_var_arguments flag. + * tree-inline.c (copy_arguments_for_versioning): Copy PARM_DECLs if + they were remapped. + 2011-09-02 Richard Guenther <rguenther@suse.de> PR tree-optimization/27460 diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 23eb1e27cf3..e751899f131 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -221,7 +221,7 @@ static struct ipcp_value *values_topo; static inline struct ipcp_lattice * ipa_get_lattice (struct ipa_node_params *info, int i) { - gcc_assert (i >= 0 && i <= ipa_get_param_count (info)); + gcc_assert (i >= 0 && i < ipa_get_param_count (info)); gcc_checking_assert (!info->ipcp_orig_node); gcc_checking_assert (info->lattices); return &(info->lattices[i]); @@ -360,7 +360,6 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) static void determine_versionability (struct cgraph_node *node) { - struct cgraph_edge *edge; const char *reason = NULL; /* There are a number of generic reasons functions cannot be versioned. We @@ -369,32 +368,15 @@ determine_versionability (struct cgraph_node *node) if (node->alias || node->thunk.thunk_p) reason = "alias or thunk"; else if (!inline_summary (node)->versionable) - reason = "inliner claims it is so"; - else if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) - reason = "there are type attributes"; + reason = "not a tree_versionable_function"; else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) reason = "insufficient body availability"; - else - /* Removing arguments doesn't work if the function takes varargs - or use __builtin_apply_args. - FIXME: handle this together with can_change_signature flag. */ - for (edge = node->callees; edge; edge = edge->next_callee) - { - tree t = edge->callee->decl; - if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL - && (DECL_FUNCTION_CODE (t) == BUILT_IN_APPLY_ARGS - || DECL_FUNCTION_CODE (t) == BUILT_IN_VA_START)) - { - reason = "prohibitive builtins called"; - break; - }; - } if (reason && dump_file && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", cgraph_node_name (node), node->uid, reason); - IPA_NODE_REF (node)->node_versionable = (reason == NULL); + inline_summary (node)->versionable = (reason == NULL); } /* Return true if it is at all technically possible to create clones of a @@ -403,7 +385,7 @@ determine_versionability (struct cgraph_node *node) static bool ipcp_versionable_function_p (struct cgraph_node *node) { - return IPA_NODE_REF (node)->node_versionable; + return inline_summary (node)->versionable; } /* Structure holding accumulated information about callers of a node. */ @@ -610,9 +592,7 @@ initialize_node_lattices (struct cgraph_node *node) int i; gcc_checking_assert (cgraph_function_with_gimple_body_p (node)); - if (ipa_is_called_with_var_arguments (info)) - disable = true; - else if (!node->local.local) + if (!node->local.local) { /* When cloning is allowed, we can assume that externally visible functions are not called. We will compensate this by cloning @@ -1068,18 +1048,17 @@ propagate_constants_accross_call (struct cgraph_edge *cs) struct cgraph_node *callee, *alias_or_thunk; struct ipa_edge_args *args; bool ret = false; - int i, count; + int i, args_count, parms_count; callee = cgraph_function_node (cs->callee, &availability); if (!callee->analyzed) return false; gcc_checking_assert (cgraph_function_with_gimple_body_p (callee)); callee_info = IPA_NODE_REF (callee); - if (ipa_is_called_with_var_arguments (callee_info)) - return false; args = IPA_EDGE_REF (cs); - count = ipa_get_cs_argument_count (args); + args_count = ipa_get_cs_argument_count (args); + parms_count = ipa_get_param_count (callee_info); /* If this call goes through a thunk we must not propagate to the first (0th) parameter. However, we might need to uncover a thunk from below a series @@ -1095,7 +1074,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) else i = 0; - for (; i < count; i++) + for (; (i < args_count) && (i < parms_count); i++) { struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); struct ipcp_lattice *dest_lat = ipa_get_lattice (callee_info, i); @@ -1105,6 +1084,9 @@ propagate_constants_accross_call (struct cgraph_edge *cs) else ret |= propagate_accross_jump_function (cs, jump_func, dest_lat); } + for (; i < parms_count; i++) + ret |= set_lattice_contains_variable (ipa_get_lattice (callee_info, i)); + return ret; } @@ -2004,7 +1986,11 @@ create_specialized_node (struct cgraph_node *node, } } else - args_to_skip = NULL; + { + args_to_skip = NULL; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " cannot change function signature\n"); + } for (i = 0; i < count ; i++) { diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index f21ab893995..5c0bd90c16b 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -1032,19 +1032,13 @@ ipa_compute_jump_functions (struct cgraph_node *node, for (cs = node->callees; cs; cs = cs->next_callee) { - struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, NULL); + struct cgraph_node *callee = cgraph_function_or_thunk_node (cs->callee, + NULL); /* We do not need to bother analyzing calls to unknown functions unless they may become known during lto/whopr. */ - if (!cs->callee->analyzed && !flag_lto) + if (!callee->analyzed && !flag_lto) continue; ipa_count_arguments (cs); - /* If the descriptor of the callee is not initialized yet, we have to do - it now. */ - if (callee->analyzed) - ipa_initialize_node_params (callee); - if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) - != ipa_get_param_count (IPA_NODE_REF (callee))) - ipa_set_called_with_variable_arg (IPA_NODE_REF (callee)); ipa_compute_jump_functions_for_edge (parms_info, cs); } @@ -1649,10 +1643,6 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) } callee = cgraph_function_or_thunk_node (callee, NULL); - if (ipa_get_cs_argument_count (IPA_EDGE_REF (ie)) - != ipa_get_param_count (IPA_NODE_REF (callee))) - ipa_set_called_with_variable_arg (IPA_NODE_REF (callee)); - return ie; } @@ -1964,7 +1954,6 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, new_info->lattices = NULL; new_info->ipcp_orig_node = old_info->ipcp_orig_node; - new_info->called_with_var_arguments = old_info->called_with_var_arguments; new_info->uses_analysis_done = old_info->uses_analysis_done; new_info->node_enqueued = old_info->node_enqueued; } @@ -2949,7 +2938,6 @@ void ipa_update_after_lto_read (void) { struct cgraph_node *node; - struct cgraph_edge *cs; ipa_check_create_node_params (); ipa_check_create_edge_args (); @@ -2957,17 +2945,4 @@ ipa_update_after_lto_read (void) for (node = cgraph_nodes; node; node = node->next) if (node->analyzed) ipa_initialize_node_params (node); - - for (node = cgraph_nodes; node; node = node->next) - if (node->analyzed) - for (cs = node->callees; cs; cs = cs->next_callee) - { - struct cgraph_node *callee; - - callee = cgraph_function_or_thunk_node (cs->callee, NULL); - if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) - != ipa_get_param_count (IPA_NODE_REF (callee))) - ipa_set_called_with_variable_arg (IPA_NODE_REF (callee)); - } } - diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 126df48811f..618b5a0b9cd 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -168,11 +168,6 @@ struct ipa_node_params /* If this node is an ipa-cp clone, these are the known values that describe what it has been specialized for. */ VEC (tree, heap) *known_vals; - /* Whether this function is called with variable number of actual - arguments. */ - unsigned called_with_var_arguments : 1; - /* Set when it is possible to create specialized versions of this node. */ - unsigned node_versionable : 1; /* Whether the param uses analysis has already been performed. */ unsigned uses_analysis_done : 1; /* Whether the function is enqueued in ipa-cp propagation stack. */ @@ -224,22 +219,6 @@ ipa_is_param_used (struct ipa_node_params *info, int i) return VEC_index (ipa_param_descriptor_t, info->descriptors, i)->used; } -/* Flag this node as having callers with variable number of arguments. */ - -static inline void -ipa_set_called_with_variable_arg (struct ipa_node_params *info) -{ - info->called_with_var_arguments = 1; -} - -/* Have we detected this node was called with variable number of arguments? */ - -static inline bool -ipa_is_called_with_var_arguments (struct ipa_node_params *info) -{ - return info->called_with_var_arguments; -} - /* ipa_edge_args stores information related to a callsite and particularly its arguments. It can be accessed by the IPA_EDGE_REF macro. */ typedef struct GTY(()) ipa_edge_args diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1584cff6427..d779df33487 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-09-02 Martin Jambor <mjambor@suse.cz> + + * gcc.dg/ipa/ipcp-3.c: New test. + 2011-09-02 Richard Guenther <rguenther@suse.de> PR tree-optimization/27460 diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-3.c b/gcc/testsuite/gcc.dg/ipa/ipcp-3.c new file mode 100644 index 00000000000..1443b73ebcd --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-3.c @@ -0,0 +1,70 @@ +/* Verify that IPA-CP can clone mark_cell without miscompiling it despite its + type_attributes. */ +/* { dg-do run } */ +/* { dg-options "-O3 -fdump-ipa-cp" } */ + + +struct PMC { + unsigned flags; +}; + +typedef struct Pcc_cell +{ + struct PMC *p; + long bla; + long type; +} Pcc_cell; + +int gi; + +extern void abort (); +extern void never_ever(int * interp, struct PMC *pmc) + __attribute__((noinline)); + +void never_ever (int * interp, struct PMC *pmc) +{ + abort (); +} + +static void mark_cell(int * interp, Pcc_cell *c) + __attribute__((__nonnull__(1))) + __attribute__((noinline)); + +static void +mark_cell(int * interp, Pcc_cell *c) +{ + if (c && c->type == 4 && c->p + && !(c->p->flags & (1<<18))) + never_ever(interp, c->p); +} + +static void foo(int * interp, Pcc_cell *c) + __attribute__((noinline)); + +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; + + for (i = 0; i < 100; i++) + foo (&gi, getnull ()); + return 0; +} + + +/* { dg-final { scan-ipa-dump "Creating a specialized node of mark_cell" "cp" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */ + diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 741e8e4d005..3610289dc35 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4840,6 +4840,8 @@ copy_arguments_for_versioning (tree orig_parm, copy_body_data * id, if (!args_to_skip || !bitmap_bit_p (args_to_skip, i)) { tree new_tree = remap_decl (arg, id); + if (TREE_CODE (new_tree) != PARM_DECL) + new_tree = id->copy_decl (arg, id); lang_hooks.dup_lang_specific_decl (new_tree); *parg = new_tree; parg = &DECL_CHAIN (new_tree); |