diff options
-rw-r--r-- | gcc/ChangeLog | 45 | ||||
-rw-r--r-- | gcc/ipa-cp.c | 28 | ||||
-rw-r--r-- | gcc/ipa-inline.c | 8 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 303 | ||||
-rw-r--r-- | gcc/ipa-prop.h | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/iinline-3.C | 64 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/modif-1.c | 41 |
8 files changed, 292 insertions, 223 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 54faa83f186..f64b9691005 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,48 @@ +2010-06-25 Martin Jambor <mjambor@suse.cz> + + * ipa-prop.h (struct ipa_param_descriptor): Removed the modified flag. + (struct ipa_node_params): Removed the modification_analysis_done flag. + (ipa_is_param_modified): Removed. + (ipa_analyze_node): Declare. + (ipa_compute_jump_functions): Remove declaration. + (ipa_count_arguments): Likewise. + (ipa_detect_param_modifications): Likewise. + (ipa_analyze_params_uses): Likewise. + * ipa-prop.c (struct param_analysis_info): New type. + (visit_store_addr_for_mod_analysis): Removed. + (visit_load_for_mod_analysis): Renamed to visit_ref_for_mod_analysis, + moved down in the file. + (ipa_detect_param_modifications): Merged into ipa_analyze_params_uses. + (ipa_count_arguments): Made static. + (mark_modified): New function. + (is_parm_modified_before_call): New function. + (compute_pass_through_member_ptrs): New parameter parms_info, call + is_parm_modified_before_call instead of ipa_is_param_modified. + (ipa_compute_jump_functions_for_edge): New parameter parms_info, pass + it to compute_pass_through_member_ptrs. + (ipa_compute_jump_functions): New parameter parms_info, pass it to + ipa_compute_jump_functions_for_edge. Call ipa_initialize_node_params + on the callee if it is analyzed. Made static. + (ipa_analyze_indirect_call_uses): New parameter parms_info, call + is_parm_modified_before_call instead of ipa_is_param_modified. + (ipa_analyze_call_uses): New parameter parms_info, pass it to + ipa_analyze_indirect_call_uses. + (ipa_analyze_stmt_uses): New parameter parms_info, pass it to + ipa_analyze_call_uses. + (ipa_analyze_params_uses): New parameter parms_info, pass it to + ipa_analyze_stmt_uses. Also perform the used analysis. Made static. + (ipa_analyze_node): New function. + (ipa_print_node_params): Do not dump the modified flag. + (ipa_write_node_info): Assert uses_analysis_done rather than streaming + it. Do not stream the modified parameter flag. + (ipa_read_node_info): Set uses_analysis_done to 1 instead of streaming + it. Do not stream the modified parameter flag. + * ipa-cp.c (ipcp_analyze_node): Removed. + (ipcp_init_stage): Iterate only once over the nodes, analyze each one + with only a call to ipa_analyze_node. + * ipa-inline.c (inline_indirect_intraprocedural_analysis): Analyze the + node with only a call to ipa_analyze_node. + 2010-06-25 Manuel López-Ibáñez <manu@gcc.gnu.org> * doc/invoke.texi (-Wsuggest-attribute): Add item for noreturn. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 1c1809b61d0..78dccf85b04 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -177,18 +177,6 @@ ipcp_init_cloned_node (struct cgraph_node *orig_node, IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node; } -/* Perform intraprocedrual analysis needed for ipcp. */ -static void -ipcp_analyze_node (struct cgraph_node *node) -{ - /* Unreachable nodes should have been eliminated before ipcp. */ - gcc_assert (node->needed || node->reachable); - - node->local.versionable = tree_versionable_function_p (node->decl); - ipa_initialize_node_params (node); - ipa_detect_param_modifications (node); -} - /* Return scale for NODE. */ static inline gcov_type ipcp_get_node_scale (struct cgraph_node *node) @@ -611,6 +599,7 @@ ipcp_compute_node_scale (struct cgraph_node *node) /* Initialization and computation of IPCP data structures. This is the initial intraprocedural analysis of functions, which gathers information to be propagated later on. */ + static void ipcp_init_stage (void) { @@ -618,16 +607,13 @@ ipcp_init_stage (void) for (node = cgraph_nodes; node; node = node->next) if (node->analyzed) - ipcp_analyze_node (node); - for (node = cgraph_nodes; node; node = node->next) - { - if (!node->analyzed) - continue; + { + /* Unreachable nodes should have been eliminated before ipcp. */ + gcc_assert (node->needed || node->reachable); - ipa_analyze_params_uses (node); - /* building jump functions */ - ipa_compute_jump_functions (node); - } + node->local.versionable = tree_versionable_function_p (node->decl); + ipa_analyze_node (node); + } } /* Return true if there are some formal parameters whose value is IPA_TOP (in diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 46bce87b16f..266d481950f 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -2011,12 +2011,8 @@ struct gimple_opt_pass pass_inline_parameters = static void inline_indirect_intraprocedural_analysis (struct cgraph_node *node) { - ipa_initialize_node_params (node); - ipa_detect_param_modifications (node); - ipa_analyze_params_uses (node); - ipa_compute_jump_functions (node); - - if (dump_file) + ipa_analyze_node (node); + if (dump_file && (dump_flags & TDF_DETAILS)) { ipa_print_node_params (dump_file, node); ipa_print_node_jump_functions (dump_file, node); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 8b537f4d48d..3fd284bff7a 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -39,6 +39,16 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "lto-streamer.h" + +/* Intermediate information about a parameter that is only useful during the + run of ipa_analyze_node and is not kept afterwards. */ + +struct param_analysis_info +{ + bool modified; + bitmap visited_statements; +}; + /* Vector where the parameter infos are actually stored. */ VEC (ipa_node_params_t, heap) *ipa_node_params_vector; /* Vector where the parameter infos are actually stored. */ @@ -196,101 +206,10 @@ ipa_initialize_node_params (struct cgraph_node *node) } } -/* Callback of walk_stmt_load_store_addr_ops for the visit_store and visit_addr - parameters. If OP is a parameter declaration, mark it as modified in the - info structure passed in DATA. */ - -static bool -visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, - tree op, void *data) -{ - struct ipa_node_params *info = (struct ipa_node_params *) data; - - op = get_base_address (op); - if (op - && TREE_CODE (op) == PARM_DECL) - { - int index = ipa_get_param_decl_index (info, op); - gcc_assert (index >= 0); - info->params[index].modified = true; - info->params[index].used = true; - } - - return false; -} - -/* Callback of walk_stmt_load_store_addr_ops for the visit_load. - If OP is a parameter declaration, mark it as used in the info structure - passed in DATA. */ - -static bool -visit_load_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, - tree op, void *data) -{ - struct ipa_node_params *info = (struct ipa_node_params *) data; - - op = get_base_address (op); - if (op - && TREE_CODE (op) == PARM_DECL) - { - int index = ipa_get_param_decl_index (info, op); - gcc_assert (index >= 0); - info->params[index].used = true; - } - - return false; -} - -/* Compute which formal parameters of function associated with NODE are locally - modified or their address is taken. Note that this does not apply on - parameters with SSA names but those can and should be analyzed - differently. */ - -void -ipa_detect_param_modifications (struct cgraph_node *node) -{ - tree decl = node->decl; - basic_block bb; - struct function *func; - gimple_stmt_iterator gsi; - struct ipa_node_params *info = IPA_NODE_REF (node); - int i; - - if (ipa_get_param_count (info) == 0 || info->modification_analysis_done) - return; - - for (i = 0; i < ipa_get_param_count (info); i++) - { - tree parm = ipa_get_param (info, i); - /* For SSA regs see if parameter is used. For non-SSA we compute - the flag during modification analysis. */ - if (is_gimple_reg (parm) - && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm)) - info->params[i].used = true; - } - - func = DECL_STRUCT_FUNCTION (decl); - FOR_EACH_BB_FN (bb, func) - { - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, - visit_load_for_mod_analysis, - visit_store_addr_for_mod_analysis, - visit_store_addr_for_mod_analysis); - for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) - walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, - visit_load_for_mod_analysis, - visit_store_addr_for_mod_analysis, - visit_store_addr_for_mod_analysis); - } - - info->modification_analysis_done = 1; -} - /* Count number of arguments callsite CS has and store it in ipa_edge_args structure corresponding to this callsite. */ -void +static void ipa_count_arguments (struct cgraph_edge *cs) { gimple stmt; @@ -707,14 +626,53 @@ type_like_member_ptr_p (tree type, tree *method_ptr, tree *delta) return true; } +/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the + boolean variable pointed to by DATA. */ + +static bool +mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED, + void *data) +{ + bool *b = (bool *) data; + *b = true; + return true; +} + +/* Return true if the formal parameter PARM might have been modified in this + function before reaching the statement CALL. PARM_INFO is a pointer to a + structure containing intermediate information about PARM. */ + +static bool +is_parm_modified_before_call (struct param_analysis_info *parm_info, + gimple call, tree parm) +{ + bool modified = false; + ao_ref refd; + + if (parm_info->modified) + return true; + + ao_ref_init (&refd, parm); + walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified, + &modified, &parm_info->visited_statements); + if (modified) + { + parm_info->modified = true; + return true; + } + return false; +} + /* Go through arguments of the CALL and for every one that looks like a member pointer, check whether it can be safely declared pass-through and if so, mark that to the corresponding item of jump FUNCTIONS. Return true iff there are non-pass-through member pointers within the arguments. INFO - describes formal parameters of the caller. */ + describes formal parameters of the caller. PARMS_INFO is a pointer to a + vector containing intermediate information about each formal parameter. */ static bool compute_pass_through_member_ptrs (struct ipa_node_params *info, + struct param_analysis_info *parms_info, struct ipa_jump_func *functions, gimple call) { @@ -733,7 +691,7 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info, int index = ipa_get_param_decl_index (info, arg); gcc_assert (index >=0); - if (!ipa_is_param_modified (info, index)) + if (!is_parm_modified_before_call (&parms_info[index], call, arg)) { functions[num].type = IPA_JF_PASS_THROUGH; functions[num].value.pass_through.formal_id = index; @@ -886,7 +844,8 @@ compute_cst_member_ptr_arguments (struct ipa_jump_func *functions, to this callsite. */ static void -ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs) +ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_info, + struct cgraph_edge *cs) { struct ipa_node_params *info = IPA_NODE_REF (cs->caller); struct ipa_edge_args *arguments = IPA_EDGE_REF (cs); @@ -905,7 +864,8 @@ ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs) /* Let's check whether there are any potential member pointers and if so, whether we can determine their functions as pass_through. */ - if (!compute_pass_through_member_ptrs (info, arguments->jump_functions, call)) + if (!compute_pass_through_member_ptrs (info, parms_info, + arguments->jump_functions, call)) return; /* Finally, let's check whether we actually pass a new constant member @@ -916,8 +876,9 @@ ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs) /* Compute jump functions for all edges - both direct and indirect - outgoing from NODE. Also count the actual arguments in the process. */ -void -ipa_compute_jump_functions (struct cgraph_node *node) +static void +ipa_compute_jump_functions (struct cgraph_node *node, + struct param_analysis_info *parms_info) { struct cgraph_edge *cs; @@ -928,16 +889,20 @@ ipa_compute_jump_functions (struct cgraph_node *node) if (!cs->callee->analyzed && !flag_lto && !flag_whopr) continue; ipa_count_arguments (cs); + /* If the descriptor of the callee is not initialized yet, we have to do + it now. */ + if (cs->callee->analyzed) + ipa_initialize_node_params (cs->callee); if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) != ipa_get_param_count (IPA_NODE_REF (cs->callee))) ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee)); - ipa_compute_jump_functions_for_edge (cs); + ipa_compute_jump_functions_for_edge (parms_info, cs); } for (cs = node->indirect_calls; cs; cs = cs->next_callee) { ipa_count_arguments (cs); - ipa_compute_jump_functions_for_edge (cs); + ipa_compute_jump_functions_for_edge (parms_info, cs); } } @@ -1021,13 +986,15 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt, } /* Analyze the CALL and examine uses of formal parameters of the caller NODE - (described by INFO). Currently it checks whether the call calls a pointer - that is a formal parameter and if so, the parameter is marked with the - called flag and an indirect call graph edge describing the call is created. - This is very simple for ordinary pointers represented in SSA but not-so-nice - when it comes to member pointers. The ugly part of this function does - nothing more than trying to match the pattern of such a call. An example of - such a pattern is the gimple dump below, the call is on the last line: + (described by INFO). PARMS_INFO is a pointer to a vector containing + intermediate information about each formal parameter. Currently it checks + whether the call calls a pointer that is a formal parameter and if so, the + parameter is marked with the called flag and an indirect call graph edge + describing the call is created. This is very simple for ordinary pointers + represented in SSA but not-so-nice when it comes to member pointers. The + ugly part of this function does nothing more than trying to match the + pattern of such a call. An example of such a pattern is the gimple dump + below, the call is on the last line: <bb 2>: f$__delta_5 = f.__delta; @@ -1073,6 +1040,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt, static void ipa_analyze_indirect_call_uses (struct cgraph_node *node, struct ipa_node_params *info, + struct param_analysis_info *parms_info, gimple call, tree target) { gimple def; @@ -1184,7 +1152,8 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node, return; index = ipa_get_param_decl_index (info, rec); - if (index >= 0 && !ipa_is_param_modified (info, index)) + if (index >= 0 && !is_parm_modified_before_call (&parms_info[index], + call, rec)) ipa_note_param_call (node, index, call, false); return; @@ -1227,16 +1196,18 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node, } /* Analyze a call statement CALL whether and how it utilizes formal parameters - of the caller (described by INFO). */ + of the caller (described by INFO). PARMS_INFO is a pointer to a vector + containing intermediate information about each formal parameter. */ static void ipa_analyze_call_uses (struct cgraph_node *node, - struct ipa_node_params *info, gimple call) + struct ipa_node_params *info, + struct param_analysis_info *parms_info, gimple call) { tree target = gimple_call_fn (call); if (TREE_CODE (target) == SSA_NAME) - ipa_analyze_indirect_call_uses (node, info, call, target); + ipa_analyze_indirect_call_uses (node, info, parms_info, call, target); else if (TREE_CODE (target) == OBJ_TYPE_REF) ipa_analyze_virtual_call_uses (node, info, call, target); } @@ -1244,45 +1215,120 @@ ipa_analyze_call_uses (struct cgraph_node *node, /* Analyze the call statement STMT with respect to formal parameters (described in INFO) of caller given by NODE. Currently it only checks whether formal - parameters are called. */ + parameters are called. PARMS_INFO is a pointer to a vector containing + intermediate information about each formal parameter. */ static void ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info, - gimple stmt) + struct param_analysis_info *parms_info, gimple stmt) { if (is_gimple_call (stmt)) - ipa_analyze_call_uses (node, info, stmt); + ipa_analyze_call_uses (node, info, parms_info, stmt); +} + +/* Callback of walk_stmt_load_store_addr_ops for the visit_load. + If OP is a parameter declaration, mark it as used in the info structure + passed in DATA. */ + +static bool +visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, + tree op, void *data) +{ + struct ipa_node_params *info = (struct ipa_node_params *) data; + + op = get_base_address (op); + if (op + && TREE_CODE (op) == PARM_DECL) + { + int index = ipa_get_param_decl_index (info, op); + gcc_assert (index >= 0); + info->params[index].used = true; + } + + return false; } /* Scan the function body of NODE and inspect the uses of formal parameters. Store the findings in various structures of the associated ipa_node_params - structure, such as parameter flags, notes etc. */ + structure, such as parameter flags, notes etc. PARMS_INFO is a pointer to a + vector containing intermediate information about each formal parameter. */ -void -ipa_analyze_params_uses (struct cgraph_node *node) +static void +ipa_analyze_params_uses (struct cgraph_node *node, + struct param_analysis_info *parms_info) { tree decl = node->decl; basic_block bb; struct function *func; gimple_stmt_iterator gsi; struct ipa_node_params *info = IPA_NODE_REF (node); + int i; if (ipa_get_param_count (info) == 0 || info->uses_analysis_done) return; + for (i = 0; i < ipa_get_param_count (info); i++) + { + tree parm = ipa_get_param (info, i); + /* For SSA regs see if parameter is used. For non-SSA we compute + the flag during modification analysis. */ + if (is_gimple_reg (parm) + && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm)) + info->params[i].used = true; + } + func = DECL_STRUCT_FUNCTION (decl); FOR_EACH_BB_FN (bb, func) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - ipa_analyze_stmt_uses (node, info, stmt); + + if (is_gimple_debug (stmt)) + continue; + + ipa_analyze_stmt_uses (node, info, parms_info, stmt); + walk_stmt_load_store_addr_ops (stmt, info, + visit_ref_for_mod_analysis, + visit_ref_for_mod_analysis, + visit_ref_for_mod_analysis); } + for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi)) + walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, + visit_ref_for_mod_analysis, + visit_ref_for_mod_analysis, + visit_ref_for_mod_analysis); } info->uses_analysis_done = 1; } +/* Initialize the array describing properties of of formal parameters of NODE, + analyze their uses and and compute jump functions associated witu actual + arguments of calls from within NODE. */ + +void +ipa_analyze_node (struct cgraph_node *node) +{ + struct ipa_node_params *info = IPA_NODE_REF (node); + struct param_analysis_info *parms_info; + int i, param_count; + + ipa_initialize_node_params (node); + + param_count = ipa_get_param_count (info); + parms_info = XALLOCAVEC (struct param_analysis_info, param_count); + memset (parms_info, 0, sizeof (struct param_analysis_info) * param_count); + + ipa_analyze_params_uses (node, parms_info); + ipa_compute_jump_functions (node, parms_info); + + for (i = 0; i < param_count; i++) + if (parms_info[i].visited_statements) + BITMAP_FREE (parms_info[i].visited_statements); +} + + /* Update the jump function DST when the call graph edge correspondng to SRC is is being inlined, knowing that DST is of type ancestor and src of known type. */ @@ -1854,8 +1900,6 @@ ipa_print_node_params (FILE * f, struct cgraph_node *node) (DECL_NAME (temp) ? (*lang_hooks.decl_printable_name) (temp, 2) : "(unnamed)")); - if (ipa_is_param_modified (info, i)) - fprintf (f, " modified"); if (ipa_is_param_used (info, i)) fprintf (f, " used"); fprintf (f, "\n"); @@ -2464,16 +2508,12 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, info->called_with_var_arguments, 1); - bp_pack_value (&bp, info->uses_analysis_done, 1); - gcc_assert (info->modification_analysis_done + gcc_assert (info->uses_analysis_done || ipa_get_param_count (info) == 0); gcc_assert (!info->node_enqueued); gcc_assert (!info->ipcp_orig_node); for (j = 0; j < ipa_get_param_count (info); j++) - { - bp_pack_value (&bp, info->params[j].modified, 1); - bp_pack_value (&bp, info->params[j].used, 1); - } + bp_pack_value (&bp, info->params[j].used, 1); lto_output_bitpack (&bp); for (e = node->callees; e; e = e->next_callee) { @@ -2503,18 +2543,11 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, bp = lto_input_bitpack (ib); info->called_with_var_arguments = bp_unpack_value (&bp, 1); - info->uses_analysis_done = bp_unpack_value (&bp, 1); if (ipa_get_param_count (info) != 0) - { - info->modification_analysis_done = true; - info->uses_analysis_done = true; - } + info->uses_analysis_done = true; info->node_enqueued = false; for (k = 0; k < ipa_get_param_count (info); k++) - { - info->params[k].modified = bp_unpack_value (&bp, 1); - info->params[k].used = bp_unpack_value (&bp, 1); - } + info->params[k].used = bp_unpack_value (&bp, 1); for (e = node->callees; e; e = e->next_callee) { struct ipa_edge_args *args = IPA_EDGE_REF (e); diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 110044e4da4..c73367a4945 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -161,8 +161,6 @@ struct ipa_param_descriptor struct ipcp_lattice ipcp_lattice; /* PARAM_DECL of this parameter. */ tree decl; - /* Whether the value parameter has been modified within the function. */ - unsigned modified : 1; /* The parameter is used. */ unsigned used : 1; }; @@ -179,8 +177,6 @@ struct ipa_node_params /* Whether this function is called with variable number of actual arguments. */ unsigned called_with_var_arguments : 1; - /* Whether the modification analysis has already been performed. */ - unsigned modification_analysis_done : 1; /* Whether the param uses analysis has already been performed. */ unsigned uses_analysis_done : 1; /* Whether the function is enqueued in an ipa_func_list. */ @@ -228,17 +224,6 @@ ipa_get_param (struct ipa_node_params *info, int i) return info->params[i].decl; } -/* Return the modification flag corresponding to the Ith formal parameter of - the function associated with INFO. Note that there is no setter method as - the goal is to set all flags when building the array in - ipa_detect_param_modifications. */ - -static inline bool -ipa_is_param_modified (struct ipa_node_params *info, int i) -{ - return info->params[i].modified; -} - /* Return the used flag corresponding to the Ith formal parameter of the function associated with INFO. */ @@ -412,14 +397,10 @@ ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *node) ipa_push_func_to_list_1 (wl, node, info); } -/* Callsite related calculations. */ -void ipa_compute_jump_functions (struct cgraph_node *); -void ipa_count_arguments (struct cgraph_edge *); +void ipa_analyze_node (struct cgraph_node *); /* Function formal parameters related computations. */ void ipa_initialize_node_params (struct cgraph_node *node); -void ipa_detect_param_modifications (struct cgraph_node *); -void ipa_analyze_params_uses (struct cgraph_node *); bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, VEC (cgraph_edge_p, heap) **new_edges); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 738ada28def..d0e19bc2801 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-06-25 Martin Jambor <mjambor@suse.cz> + + * g++.dg/ipa/iinline-3.C: New test. + * gcc.dg/ipa/modif-1.c: Removed. + 2010-06-25 Jan Hubicka <jh@suse.cz> * testsuite/gcc.dg/tree-ssa/ipa-split-1.c diff --git a/gcc/testsuite/g++.dg/ipa/iinline-3.C b/gcc/testsuite/g++.dg/ipa/iinline-3.C new file mode 100644 index 00000000000..3daee9a8681 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/iinline-3.C @@ -0,0 +1,64 @@ +/* Verify that we do not indirect-inline using member pointer + parameters which have been modified. */ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-early-inlining" } */ +/* { dg-add-options bind_pic_locally } */ + +extern "C" void abort (void); + +class String +{ +private: + const char *data; + +public: + String (const char *d) : data(d) + {} + + int funcOne (int stuff) const; + int funcTwo (int stuff) const; +}; + + +int String::funcOne (int stuff) const +{ + return stuff + 1; +} + +int String::funcTwo (int stuff) const +{ + return stuff + 100; +} + +int (String::* gmp)(int stuff) const = &String::funcTwo; + +int docalling_1 (int (String::* f)(int stuff) const) +{ + String S ("muhehehe"); + + return (S.*f)(4); +} + +int docalling (int a, int (String::* f)(int stuff) const) +{ + if (a < 200) + f = gmp; + + return docalling_1 (f); +} + +int __attribute__ ((noinline,noclone)) get_input (void) +{ + return 1; +} + +int main (int argc, char *argv[]) +{ + int i = 0; + while (i < 10) + i += docalling (get_input (), &String::funcOne); + + if (i != 104) + abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/ipa/modif-1.c b/gcc/testsuite/gcc.dg/ipa/modif-1.c deleted file mode 100644 index db6915a9d9e..00000000000 --- a/gcc/testsuite/gcc.dg/ipa/modif-1.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Verify that modification analysis detects modfications. */ -/* { dg-do compile } */ -/* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining" } */ - -struct whatever -{ - int first; - unsigned second; -}; - -void func1 (struct whatever w); -void func2 (struct whatever *pw); -void func3 (int i); -void func4 (int *pi); - -void the_test (struct whatever u, struct whatever v, - struct whatever w, struct whatever x, - int i, int k, int l) -{ - struct whatever *pw = &w; - int *pk = &k; - - v.first = 9; - - func1 (u); - func1 (v); - func2 (pw); - func2 (&x); - func3 (i); - func4 (pk); - func4 (&l); -} - -/* { dg-final { scan-ipa-dump-not "param 0\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 1\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 2\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 3\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump-not "param 4\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 5\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 6\[^\\n\]*modified" "inline" } } */ -/* { dg-final { cleanup-ipa-dump "inline" } } */ |