re PR tree-optimization/53787 (Possible IPA-SRA / IPA-CP improvement)

2012-11-07  Martin Jambor  <mjambor@suse.cz>

	PR tree-optimization/53787
	* ipa-cp.c (ipcp_value_source): New field offset.
	(ipcp_agg_lattice): New type.
	(ipcp_param_lattices): Likewise, move virt_call from ipcp_lattice here.
	(ipcp_agg_lattice_pool): New variable.
	(ipa_get_parm_lattices): New function.
	(ipa_get_lattice): Turned into ipa_get_scalar_lat, use the above.
	Adjusted all callers.
	(print_lattice): New function.
	(print_all_lattices): Use the above, also print aggregate lattices.
	(set_agg_lats_to_bottom): New function.
	(set_agg_lats_contain_variable): Likewise.
	(set_all_contains_variable): Likewise.
	(initialize_node_lattices): Also handle aggregate lattices, set
	virt_call in ipcp_param_lattices.
	(add_value_source): Handle offsets.
	(add_value_to_lattice): Likewise.
	(add_scalar_value_to_lattice): New function.
	(propagate_vals_accross_pass_through): Use add_scalar_value_to_lattice.
	(propagate_vals_accross_ancestor): Likewise.
	(propagate_accross_jump_function): Renamed to
	propagate_scalar_accross_jump_function, use
	add_scalar_value_to_lattice.
	(set_check_aggs_by_ref): New function.
	(merge_agg_lats_step): Likewise.
	(set_chain_of_aglats_contains_variable): Likewise.
	(merge_aggregate_lattices): Likewise.
	(propagate_constants_accross_call): Also handle aggregate lattices.
	(hint_time_bonus): New function.
	(context_independent_aggregate_values): Likewise.
	(gather_context_independent_values): Also handle agggregate values.
	(agg_jmp_p_vec_for_t_vec): New function.
	(estimate_local_effects): Also handle agggregate values.
	(add_all_node_vals_to_toposort): Likewise.
	(ipcp_propagate_stage): Use struct ipcp_param_lattices.
	(get_clone_agg_value): New function.
	(cgraph_edge_brings_value_p): Also handle agggregate values.
	(create_specialized_node): Likewise.
	(find_more_values_for_callers_subset): Rename to
	find_more_scalar_values_for_callers_subset.  Modify dump.
	(copy_plats_to_inter): New function.
	(intersect_with_plats): Likewise.
	(agg_replacements_to_vector): Likewise.
	(intersect_with_agg_replacements): Likewise.
	(find_aggregate_values_for_callers_subset): Likewise.
	(known_aggs_to_agg_replacement_list): Likewise.
	(cgraph_edge_brings_all_scalars_for_node): Likewise.
	(cgraph_edge_brings_all_agg_vals_for_node): Likewise.
	(perhaps_add_new_callers): Old functionality moved to
	cgraph_edge_brings_all_scalars_for_node, call it and
	cgraph_edge_brings_all_agg_vals_for_node.
	(ipcp_val_in_agg_replacements_p): New function.
	(decide_about_value): New function.
	(decide_whether_version_node): A lot of functionality moved to
	decide_about_value.  Also handle agggregate values.
	(ipcp_driver): Also allocate ipcp_agg_lattice_pool.
	(pass_ipa_cp): Fill in new entries.
	* ipa-prop.c (ipa_node_agg_replacements): New variable.
	(free_parms_ainfo): New function.
	(ipa_analyze_node): Use free_parms_ainfo to free stuff.
	(ipa_find_agg_cst_for_param): Do not rely on offset ordering.
	(ipa_set_node_agg_value_chain): New function.
	(ipa_node_removal_hook): Also handle ipa_node_agg_replacements.
	(ipa_node_duplication_hook): Likewise.
	(ipa_free_all_structures_after_ipa_cp): Also free ipcp_agg_lattice_pool.
	(ipa_free_all_structures_after_iinln): Likewise.
	(ipa_dump_agg_replacement_values): New function.
	(write_agg_replacement_chain): Likewise.
	(read_agg_replacement_chain): Likewise.
	(ipa_prop_write_all_agg_replacement): Likewise.
	(read_replacements_section): Likewise.
	(ipa_prop_read_all_agg_replacement): Likewise.
	(adjust_agg_replacement_values): Likewise.
	(ipcp_transform_function): Likewise.
	* ipa-prop.h: Also define heap vector of ipa_agg_jf_item_t and of
	ipa_agg_jump_function_t.
	(ipa_node_params): Make lattices an array of ipcp_param_lattices.
	(ipa_agg_replacement_value): New type and its vector.
	(ipa_set_node_agg_value_chain) Declare.
	(ipa_node_agg_replacements): Likewise.
	(ipa_get_agg_replacements_for_node): New function.
	(ipcp_agg_lattice_pool): Declare.
	(ipa_dump_agg_replacement_values): Likewise.
	(ipa_prop_write_all_agg_replacement): Likewise.
	(ipa_prop_read_all_agg_replacement): Likewise.
	(ipcp_transform_function): Likewise.
	* ipa-inline-analysis.c (estimate_ipcp_clone_size_and_time): Pass around
	known aggregates and hints.
	* ipa-inline.h: include ipa-prop.h.
	(estimate_ipcp_clone_size_and_time): Adjust declaration.
	* lto-streamer.h (lto_section_type): New item
	LTO_section_ipcp_transform.
	* lto-section-in.c (lto_section_name): New element ipcp_trans.
	* params.def (PARAM_IPA_CP_LOOP_HINT_BONUS): New parameter.
	* Makefile.in (IPA_INLINE_H): New.  Use everywhee instead of
	ipa-inline.h.

	* testsuite/gcc.dg/ipa/ipa-5.c: Adjust.
	* testsuite/gcc.dg/ipa/ipcp-agg-1.c: New test.
	* testsuite/gcc.dg/ipa/ipcp-agg-2.c: Likewise.
	* testsuite/gcc.dg/ipa/ipcp-agg-3.c: Likewise.
	* testsuite/gcc.dg/ipa/ipcp-agg-4.c: Likewise.
	* testsuite/gcc.dg/ipa/ipcp-agg-5.c: Likewise.
	* testsuite/gcc.dg/ipa/ipcp-agg-6.c: Likewise.
	* testsuite/gfortran.dg/pr48636.f90: Add -fno-ipa-cp.
	* testsuite/gfortran.dg/pr48636-2.f90: New test.
	* testsuite/gfortran.dg/pr53787.f90: Likewise.

From-SVN: r193298
This commit is contained in:
Martin Jambor 2012-11-07 16:55:54 +01:00 committed by Martin Jambor
parent a57d75dc70
commit 2c9561b513
21 changed files with 2235 additions and 288 deletions

View File

@ -1,3 +1,102 @@
2012-11-07 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/53787
* ipa-cp.c (ipcp_value_source): New field offset.
(ipcp_agg_lattice): New type.
(ipcp_param_lattices): Likewise, move virt_call from ipcp_lattice here.
(ipcp_agg_lattice_pool): New variable.
(ipa_get_parm_lattices): New function.
(ipa_get_lattice): Turned into ipa_get_scalar_lat, use the above.
Adjusted all callers.
(print_lattice): New function.
(print_all_lattices): Use the above, also print aggregate lattices.
(set_agg_lats_to_bottom): New function.
(set_agg_lats_contain_variable): Likewise.
(set_all_contains_variable): Likewise.
(initialize_node_lattices): Also handle aggregate lattices, set
virt_call in ipcp_param_lattices.
(add_value_source): Handle offsets.
(add_value_to_lattice): Likewise.
(add_scalar_value_to_lattice): New function.
(propagate_vals_accross_pass_through): Use add_scalar_value_to_lattice.
(propagate_vals_accross_ancestor): Likewise.
(propagate_accross_jump_function): Renamed to
propagate_scalar_accross_jump_function, use
add_scalar_value_to_lattice.
(set_check_aggs_by_ref): New function.
(merge_agg_lats_step): Likewise.
(set_chain_of_aglats_contains_variable): Likewise.
(merge_aggregate_lattices): Likewise.
(propagate_constants_accross_call): Also handle aggregate lattices.
(hint_time_bonus): New function.
(context_independent_aggregate_values): Likewise.
(gather_context_independent_values): Also handle agggregate values.
(agg_jmp_p_vec_for_t_vec): New function.
(estimate_local_effects): Also handle agggregate values.
(add_all_node_vals_to_toposort): Likewise.
(ipcp_propagate_stage): Use struct ipcp_param_lattices.
(get_clone_agg_value): New function.
(cgraph_edge_brings_value_p): Also handle agggregate values.
(create_specialized_node): Likewise.
(find_more_values_for_callers_subset): Rename to
find_more_scalar_values_for_callers_subset. Modify dump.
(copy_plats_to_inter): New function.
(intersect_with_plats): Likewise.
(agg_replacements_to_vector): Likewise.
(intersect_with_agg_replacements): Likewise.
(find_aggregate_values_for_callers_subset): Likewise.
(known_aggs_to_agg_replacement_list): Likewise.
(cgraph_edge_brings_all_scalars_for_node): Likewise.
(cgraph_edge_brings_all_agg_vals_for_node): Likewise.
(perhaps_add_new_callers): Old functionality moved to
cgraph_edge_brings_all_scalars_for_node, call it and
cgraph_edge_brings_all_agg_vals_for_node.
(ipcp_val_in_agg_replacements_p): New function.
(decide_about_value): New function.
(decide_whether_version_node): A lot of functionality moved to
decide_about_value. Also handle agggregate values.
(ipcp_driver): Also allocate ipcp_agg_lattice_pool.
(pass_ipa_cp): Fill in new entries.
* ipa-prop.c (ipa_node_agg_replacements): New variable.
(free_parms_ainfo): New function.
(ipa_analyze_node): Use free_parms_ainfo to free stuff.
(ipa_find_agg_cst_for_param): Do not rely on offset ordering.
(ipa_set_node_agg_value_chain): New function.
(ipa_node_removal_hook): Also handle ipa_node_agg_replacements.
(ipa_node_duplication_hook): Likewise.
(ipa_free_all_structures_after_ipa_cp): Also free ipcp_agg_lattice_pool.
(ipa_free_all_structures_after_iinln): Likewise.
(ipa_dump_agg_replacement_values): New function.
(write_agg_replacement_chain): Likewise.
(read_agg_replacement_chain): Likewise.
(ipa_prop_write_all_agg_replacement): Likewise.
(read_replacements_section): Likewise.
(ipa_prop_read_all_agg_replacement): Likewise.
(adjust_agg_replacement_values): Likewise.
(ipcp_transform_function): Likewise.
* ipa-prop.h: Also define heap vector of ipa_agg_jf_item_t and of
ipa_agg_jump_function_t.
(ipa_node_params): Make lattices an array of ipcp_param_lattices.
(ipa_agg_replacement_value): New type and its vector.
(ipa_set_node_agg_value_chain) Declare.
(ipa_node_agg_replacements): Likewise.
(ipa_get_agg_replacements_for_node): New function.
(ipcp_agg_lattice_pool): Declare.
(ipa_dump_agg_replacement_values): Likewise.
(ipa_prop_write_all_agg_replacement): Likewise.
(ipa_prop_read_all_agg_replacement): Likewise.
(ipcp_transform_function): Likewise.
* ipa-inline-analysis.c (estimate_ipcp_clone_size_and_time): Pass around
known aggregates and hints.
* ipa-inline.h: include ipa-prop.h.
(estimate_ipcp_clone_size_and_time): Adjust declaration.
* lto-streamer.h (lto_section_type): New item
LTO_section_ipcp_transform.
* lto-section-in.c (lto_section_name): New element ipcp_trans.
* params.def (PARAM_IPA_CP_LOOP_HINT_BONUS): New parameter.
* Makefile.in (IPA_INLINE_H): New. Use everywhee instead of
ipa-inline.h.
2012-11-07 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (enum upper_128bits_state): Remove.

View File

@ -953,6 +953,7 @@ TREE_STREAMER_H = tree-streamer.h $(TREE_H) $(LTO_STREAMER_H) \
STREAMER_HOOKS_H = streamer-hooks.h $(TREE_H)
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) $(TARGET_H)
IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
IPA_INLINE_H = ipa-inline.h $(IPA_PROP_H)
GSTAB_H = gstab.h stab.def
BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h plugin.def \
@ -2834,14 +2835,14 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h \
gt-cgraph.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
$(TREE_INLINE_H) $(TREE_FLOW_H) cif-code.def \
value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \
ipa-inline.h $(LTO_STREAMER_H) $(CFGLOOP_H) $(GIMPLE_PRETTY_PRINT_H)
$(IPA_INLINE_H) $(LTO_STREAMER_H) $(CFGLOOP_H) $(GIMPLE_PRETTY_PRINT_H)
cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
$(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
$(TREE_FLOW_H) $(TREE_PASS_H) debug.h $(DIAGNOSTIC_H) \
$(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(IPA_PROP_H) \
gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) \
$(GIMPLE_PRETTY_PRINT_H) ipa-inline.h $(IPA_UTILS_H) \
$(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(IPA_UTILS_H) \
$(LTO_STREAMER_H) output.h $(REGSET_H) $(EXCEPT_H) $(GCC_PLUGIN_H) plugin.h
cgraphclones.o : cgraphclones.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
@ -2849,12 +2850,12 @@ cgraphclones.o : cgraphclones.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_FLOW_H) $(TREE_PASS_H) debug.h $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
$(PARAMS_H) $(RTL_H) $(IPA_PROP_H) \
tree-iterator.h $(COVERAGE_H) \
$(GIMPLE_PRETTY_PRINT_H) ipa-inline.h $(IPA_UTILS_H) \
$(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(IPA_UTILS_H) \
$(LTO_STREAMER_H) $(EXCEPT_H) $(GCC_PLUGIN_H) gt-cgraphclones.h
cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \
$(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \
ipa-inline.h
$(IPA_INLINE_H)
varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) \
$(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \
@ -2874,21 +2875,22 @@ ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) $(TARGET_H) $(GIMPLE_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) \
$(TREE_INLINE_H) $(PARAMS_H) $(TREE_PRETTY_PRINT_H) ipa-inline.h
$(TREE_INLINE_H) $(PARAMS_H) $(TREE_PRETTY_PRINT_H) $(IPA_INLINE_H)
ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
$(TREE_INLINE_H) $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) ipa-inline.h
$(TREE_INLINE_H) $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H)
ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TREE_PASS_H) \
$(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(RTL_H) $(IPA_PROP_H) \
$(EXCEPT_H) $(GIMPLE_PRETTY_PRINT_H) ipa-inline.h $(TARGET_H) $(IPA_UTILS_H)
$(EXCEPT_H) $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(TARGET_H) \
$(IPA_UTILS_H)
ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(PARAMS_H) $(TREE_PASS_H) $(CFGLOOP_H) \
$(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
$(GIMPLE_PRETTY_PRINT_H) ipa-inline.h $(LTO_STREAMER_H) $(DATA_STREAMER_H) \
$(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) $(LTO_STREAMER_H) $(DATA_STREAMER_H) \
$(TREE_STREAMER_H)
ipa-inline-transform.o : ipa-inline-transform.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \

File diff suppressed because it is too large Load Diff

View File

@ -2913,16 +2913,18 @@ estimate_node_size_and_time (struct cgraph_node *node,
void
estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos,
int *ret_size, int *ret_time)
VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos,
VEC (ipa_agg_jump_function_p, heap) *known_aggs,
int *ret_size, int *ret_time,
inline_hints *hints)
{
clause_t clause;
clause = evaluate_conditions_for_known_args (node, false, known_vals, NULL);
estimate_node_size_and_time (node, clause, known_vals, known_binfos, NULL,
ret_size, ret_time, NULL,
NULL);
clause = evaluate_conditions_for_known_args (node, false, known_vals,
known_aggs);
estimate_node_size_and_time (node, clause, known_vals, known_binfos,
known_aggs, ret_size, ret_time, hints, NULL);
}
/* Translate all conditions from callee representation into caller

View File

@ -19,6 +19,8 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "ipa-prop.h"
/* Representation of inline parameters that do depend on context function is
inlined into (i.e. known constant values of function parameters.
@ -207,9 +209,9 @@ void initialize_inline_failed (struct cgraph_edge *);
int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
void estimate_ipcp_clone_size_and_time (struct cgraph_node *,
VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos,
int *, int *);
VEC (tree, heap) *, VEC (tree, heap) *,
VEC (ipa_agg_jump_function_p, heap) *,
int *, int *, inline_hints *);
int do_estimate_growth (struct cgraph_node *);
void inline_merge_summary (struct cgraph_edge *edge);
void inline_update_overall_summary (struct cgraph_node *node);

View File

@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-streamer.h"
#include "params.h"
/* Intermediate information about a parameter that is only useful during the
run of ipa_analyze_node and is not kept afterwards. */
@ -52,6 +51,8 @@ struct param_analysis_info
/* Vector where the parameter infos are actually stored. */
VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
/* Vector of known aggregate values in cloned nodes. */
VEC (ipa_agg_replacement_value_p, gc) *ipa_node_agg_replacements;
/* Vector where the parameter infos are actually stored. */
VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector;
@ -1936,6 +1937,22 @@ ipa_analyze_params_uses (struct cgraph_node *node,
info->uses_analysis_done = 1;
}
/* Free stuff in PARMS_AINFO, assume there are PARAM_COUNT parameters. */
static void
free_parms_ainfo (struct param_analysis_info *parms_ainfo, int param_count)
{
int i;
for (i = 0; i < param_count; i++)
{
if (parms_ainfo[i].parm_visited_statements)
BITMAP_FREE (parms_ainfo[i].parm_visited_statements);
if (parms_ainfo[i].pt_visited_statements)
BITMAP_FREE (parms_ainfo[i].pt_visited_statements);
}
}
/* Initialize the array describing properties of of formal parameters
of NODE, analyze their uses and compute jump functions associated
with actual arguments of calls from within NODE. */
@ -1945,7 +1962,7 @@ ipa_analyze_node (struct cgraph_node *node)
{
struct ipa_node_params *info;
struct param_analysis_info *parms_ainfo;
int i, param_count;
int param_count;
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
@ -1960,14 +1977,7 @@ ipa_analyze_node (struct cgraph_node *node)
ipa_analyze_params_uses (node, parms_ainfo);
ipa_compute_jump_functions (node, parms_ainfo);
for (i = 0; i < param_count; i++)
{
if (parms_ainfo[i].parm_visited_statements)
BITMAP_FREE (parms_ainfo[i].parm_visited_statements);
if (parms_ainfo[i].pt_visited_statements)
BITMAP_FREE (parms_ainfo[i].pt_visited_statements);
}
free_parms_ainfo (parms_ainfo, param_count);
pop_cfun ();
}
@ -2163,17 +2173,13 @@ ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg,
return NULL;
FOR_EACH_VEC_ELT (ipa_agg_jf_item_t, agg->items, i, item)
{
if (item->offset == offset)
{
/* Currently we do not have clobber values, return NULL for them once
we do. */
gcc_checking_assert (is_gimple_ip_invariant (item->value));
return item->value;
}
else if (item->offset > offset)
return NULL;
}
if (item->offset == offset)
{
/* Currently we do not have clobber values, return NULL for them once
we do. */
gcc_checking_assert (is_gimple_ip_invariant (item->value));
return item->value;
}
return NULL;
}
@ -2436,6 +2442,21 @@ ipa_free_all_node_params (void)
ipa_node_params_vector = NULL;
}
/* Set the aggregate replacements of NODE to be AGGVALS. */
void
ipa_set_node_agg_value_chain (struct cgraph_node *node,
struct ipa_agg_replacement_value *aggvals)
{
if (VEC_length (ipa_agg_replacement_value_p, ipa_node_agg_replacements)
<= (unsigned) cgraph_max_uid)
VEC_safe_grow_cleared (ipa_agg_replacement_value_p, gc,
ipa_node_agg_replacements, cgraph_max_uid + 1);
VEC_replace (ipa_agg_replacement_value_p, ipa_node_agg_replacements,
node->uid, aggvals);
}
/* Hook that is called by cgraph.c when an edge is removed. */
static void
@ -2455,9 +2476,12 @@ ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
/* During IPA-CP updating we can be called on not-yet analyze clones. */
if (VEC_length (ipa_node_params_t, ipa_node_params_vector)
<= (unsigned)node->uid)
return;
ipa_free_node_params_substructures (IPA_NODE_REF (node));
> (unsigned)node->uid)
ipa_free_node_params_substructures (IPA_NODE_REF (node));
if (VEC_length (ipa_agg_replacement_value_p, ipa_node_agg_replacements)
> (unsigned)node->uid)
VEC_replace (ipa_agg_replacement_value_p, ipa_node_agg_replacements,
(unsigned)node->uid, NULL);
}
/* Hook that is called by cgraph.c when an edge is duplicated. */
@ -2491,6 +2515,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
ATTRIBUTE_UNUSED void *data)
{
struct ipa_node_params *old_info, *new_info;
struct ipa_agg_replacement_value *old_av, *new_av;
ipa_check_create_node_params ();
old_info = IPA_NODE_REF (src);
@ -2503,6 +2528,23 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
new_info->uses_analysis_done = old_info->uses_analysis_done;
new_info->node_enqueued = old_info->node_enqueued;
old_av = ipa_get_agg_replacements_for_node (src);
if (!old_av)
return;
new_av = NULL;
while (old_av)
{
struct ipa_agg_replacement_value *v;
v = ggc_alloc_ipa_agg_replacement_value ();
memcpy (v, old_av, sizeof (*v));
v->next = new_av;
new_av = v;
old_av = old_av->next;
}
ipa_set_node_agg_value_chain (dst, new_av);
}
@ -2564,6 +2606,7 @@ ipa_free_all_structures_after_ipa_cp (void)
ipa_free_all_node_params ();
free_alloc_pool (ipcp_sources_pool);
free_alloc_pool (ipcp_values_pool);
free_alloc_pool (ipcp_agg_lattice_pool);
ipa_unregister_cgraph_hooks ();
}
}
@ -2581,13 +2624,15 @@ ipa_free_all_structures_after_iinln (void)
free_alloc_pool (ipcp_sources_pool);
if (ipcp_values_pool)
free_alloc_pool (ipcp_values_pool);
if (ipcp_agg_lattice_pool)
free_alloc_pool (ipcp_agg_lattice_pool);
}
/* Print ipa_tree_map data structures of all functions in the
callgraph to F. */
void
ipa_print_node_params (FILE * f, struct cgraph_node *node)
ipa_print_node_params (FILE *f, struct cgraph_node *node)
{
int i, count;
tree temp;
@ -3171,6 +3216,23 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
VEC_free (tree, heap, parms);
}
/* Dump the AV linked list. */
void
ipa_dump_agg_replacement_values (FILE *f, struct ipa_agg_replacement_value *av)
{
bool comma = false;
fprintf (f, " Aggregate replacements:");
for (; av; av = av->next)
{
fprintf (f, "%s %i[" HOST_WIDE_INT_PRINT_DEC "]=", comma ? "," : "",
av->index, av->offset);
print_generic_expr (f, av->value, 0);
comma = true;
}
fprintf (f, "\n");
}
/* Stream out jump function JUMP_FUNC to OB. */
static void
@ -3550,3 +3612,327 @@ ipa_update_after_lto_read (void)
if (node->analyzed)
ipa_initialize_node_params (node);
}
void
write_agg_replacement_chain (struct output_block *ob, struct cgraph_node *node)
{
int node_ref;
unsigned int count = 0;
lto_symtab_encoder_t encoder;
struct ipa_agg_replacement_value *aggvals, *av;
aggvals = ipa_get_agg_replacements_for_node (node);
encoder = ob->decl_state->symtab_node_encoder;
node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
streamer_write_uhwi (ob, node_ref);
for (av = aggvals; av; av = av->next)
count++;
streamer_write_uhwi (ob, count);
for (av = aggvals; av; av = av->next)
{
streamer_write_uhwi (ob, av->offset);
streamer_write_uhwi (ob, av->index);
stream_write_tree (ob, av->value, true);
}
}
/* Stream in the aggregate value replacement chain for NODE from IB. */
static void
read_agg_replacement_chain (struct lto_input_block *ib,
struct cgraph_node *node,
struct data_in *data_in)
{
struct ipa_agg_replacement_value *aggvals = NULL;
unsigned int count, i;
count = streamer_read_uhwi (ib);
for (i = 0; i <count; i++)
{
struct ipa_agg_replacement_value *av;
av = ggc_alloc_ipa_agg_replacement_value ();
av->offset = streamer_read_uhwi (ib);
av->index = streamer_read_uhwi (ib);
av->value = stream_read_tree (ib, data_in);
av->next = aggvals;
aggvals = av;
}
ipa_set_node_agg_value_chain (node, aggvals);
}
/* Write all aggregate replacement for nodes in set. */
void
ipa_prop_write_all_agg_replacement (void)
{
struct cgraph_node *node;
struct output_block *ob;
unsigned int count = 0;
lto_symtab_encoder_iterator lsei;
lto_symtab_encoder_t encoder;
if (!ipa_node_agg_replacements)
return;
ob = create_output_block (LTO_section_ipcp_transform);
encoder = ob->decl_state->symtab_node_encoder;
ob->cgraph_node = NULL;
for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
lsei_next_function_in_partition (&lsei))
{
node = lsei_cgraph_node (lsei);
if (cgraph_function_with_gimple_body_p (node)
&& ipa_get_agg_replacements_for_node (node) != NULL)
count++;
}
streamer_write_uhwi (ob, count);
for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
lsei_next_function_in_partition (&lsei))
{
node = lsei_cgraph_node (lsei);
if (cgraph_function_with_gimple_body_p (node)
&& ipa_get_agg_replacements_for_node (node) != NULL)
write_agg_replacement_chain (ob, node);
}
streamer_write_char_stream (ob->main_stream, 0);
produce_asm (ob, NULL);
destroy_output_block (ob);
}
/* Read replacements section in file FILE_DATA of length LEN with data
DATA. */
static void
read_replacements_section (struct lto_file_decl_data *file_data,
const char *data,
size_t len)
{
const struct lto_function_header *header =
(const struct lto_function_header *) data;
const int cfg_offset = sizeof (struct lto_function_header);
const int main_offset = cfg_offset + header->cfg_size;
const int string_offset = main_offset + header->main_size;
struct data_in *data_in;
struct lto_input_block ib_main;
unsigned int i;
unsigned int count;
LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
header->main_size);
data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
header->string_size, NULL);
count = streamer_read_uhwi (&ib_main);
for (i = 0; i < count; i++)
{
unsigned int index;
struct cgraph_node *node;
lto_symtab_encoder_t encoder;
index = streamer_read_uhwi (&ib_main);
encoder = file_data->symtab_node_encoder;
node = cgraph (lto_symtab_encoder_deref (encoder, index));
gcc_assert (node->analyzed);
read_agg_replacement_chain (&ib_main, node, data_in);
}
lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
len);
lto_data_in_delete (data_in);
}
/* Read IPA-CP aggregate replacements. */
void
ipa_prop_read_all_agg_replacement (void)
{
struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
struct lto_file_decl_data *file_data;
unsigned int j = 0;
while ((file_data = file_data_vec[j++]))
{
size_t len;
const char *data = lto_get_section_data (file_data,
LTO_section_ipcp_transform,
NULL, &len);
if (data)
read_replacements_section (file_data, data, len);
}
}
/* Adjust the aggregate replacements in AGGVAL to reflect parameters skipped in
NODE. */
static void
adjust_agg_replacement_values (struct cgraph_node *node,
struct ipa_agg_replacement_value *aggval)
{
struct ipa_agg_replacement_value *v;
int i, c = 0, d = 0, *adj;
if (!node->clone.combined_args_to_skip)
return;
for (v = aggval; v; v = v->next)
{
gcc_assert (v->index >= 0);
if (c < v->index)
c = v->index;
}
c++;
adj = XALLOCAVEC (int, c);
for (i = 0; i < c; i++)
if (bitmap_bit_p (node->clone.combined_args_to_skip, i))
{
adj[i] = -1;
d++;
}
else
adj[i] = i - d;
for (v = aggval; v; v = v->next)
v->index = adj[v->index];
}
/* Function body transformation phase. */
unsigned int
ipcp_transform_function (struct cgraph_node *node)
{
VEC (ipa_param_descriptor_t, heap) *descriptors = NULL;
struct param_analysis_info *parms_ainfo;
struct ipa_agg_replacement_value *aggval;
gimple_stmt_iterator gsi;
basic_block bb;
int param_count;
bool cfg_changed = false, something_changed = false;
gcc_checking_assert (cfun);
gcc_checking_assert (current_function_decl);
if (dump_file)
fprintf (dump_file, "Modification phase of node %s/%i\n",
cgraph_node_name (node), node->uid);
aggval = ipa_get_agg_replacements_for_node (node);
if (!aggval)
return 0;
param_count = count_formal_params (node->symbol.decl);
if (param_count == 0)
return 0;
adjust_agg_replacement_values (node, aggval);
if (dump_file)
ipa_dump_agg_replacement_values (dump_file, aggval);
parms_ainfo = XALLOCAVEC (struct param_analysis_info, param_count);
memset (parms_ainfo, 0, sizeof (struct param_analysis_info) * param_count);
VEC_safe_grow_cleared (ipa_param_descriptor_t, heap,
descriptors, param_count);
ipa_populate_param_decls (node, descriptors);
FOR_EACH_BB (bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
struct ipa_agg_replacement_value *v;
gimple stmt = gsi_stmt (gsi);
tree rhs, val, t;
HOST_WIDE_INT offset;
int index;
bool by_ref, vce;
if (!gimple_assign_load_p (stmt))
continue;
rhs = gimple_assign_rhs1 (stmt);
if (!is_gimple_reg_type (TREE_TYPE (rhs)))
continue;
vce = false;
t = rhs;
while (handled_component_p (t))
{
/* V_C_E can do things like convert an array of integers to one
bigger integer and similar things we do not handle below. */
if (TREE_CODE (rhs) == VIEW_CONVERT_EXPR)
{
vce = true;
break;
}
t = TREE_OPERAND (t, 0);
}
if (vce)
continue;
if (!ipa_load_from_parm_agg_1 (descriptors, parms_ainfo, stmt,
rhs, &index, &offset, &by_ref))
continue;
for (v = aggval; v; v = v->next)
if (v->index == index
&& v->offset == offset)
break;
if (!v)
continue;
gcc_checking_assert (is_gimple_ip_invariant (v->value));
if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (v->value)))
{
if (fold_convertible_p (TREE_TYPE (rhs), v->value))
val = fold_build1 (NOP_EXPR, TREE_TYPE (rhs), v->value);
else if (TYPE_SIZE (TREE_TYPE (rhs))
== TYPE_SIZE (TREE_TYPE (v->value)))
val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), v->value);
else
{
if (dump_file)
{
fprintf (dump_file, " const ");
print_generic_expr (dump_file, v->value, 0);
fprintf (dump_file, " can't be converted to type of ");
print_generic_expr (dump_file, rhs, 0);
fprintf (dump_file, "\n");
}
continue;
}
}
else
val = v->value;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Modifying stmt:\n ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
gimple_assign_set_rhs_from_tree (&gsi, val);
update_stmt (stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "into:\n ");
print_gimple_stmt (dump_file, stmt, 0, 0);
fprintf (dump_file, "\n");
}
something_changed = true;
if (maybe_clean_eh_stmt (stmt)
&& gimple_purge_dead_eh_edges (gimple_bb (stmt)))
cfg_changed = true;
}
VEC_replace (ipa_agg_replacement_value_p, ipa_node_agg_replacements,
node->uid, NULL);
free_parms_ainfo (parms_ainfo, param_count);
VEC_free (ipa_param_descriptor_t, heap, descriptors);
if (!something_changed)
return 0;
else if (cfg_changed)
return TODO_update_ssa_only_virtuals | TODO_cleanup_cfg;
else
return TODO_update_ssa_only_virtuals;
}

View File

@ -144,6 +144,7 @@ typedef struct GTY(()) ipa_agg_jf_item
DEF_VEC_O (ipa_agg_jf_item_t);
DEF_VEC_ALLOC_O (ipa_agg_jf_item_t, gc);
DEF_VEC_ALLOC_O (ipa_agg_jf_item_t, heap);
/* Aggregate jump function - i.e. description of contents of aggregates passed
either by reference or value. */
@ -159,6 +160,9 @@ struct GTY(()) ipa_agg_jump_function
typedef struct ipa_agg_jump_function *ipa_agg_jump_function_p;
DEF_VEC_P (ipa_agg_jump_function_p);
DEF_VEC_ALLOC_P (ipa_agg_jump_function_p, heap);
typedef struct ipa_agg_jump_function ipa_agg_jump_function_t;
DEF_VEC_P (ipa_agg_jump_function_t);
DEF_VEC_ALLOC_P (ipa_agg_jump_function_t, heap);
/* A jump function for a callsite represents the values passed as actual
arguments of the callsite. See enum jump_func_type for the various
@ -322,7 +326,7 @@ struct ipa_node_params
VEC (ipa_param_descriptor_t, heap) *descriptors;
/* Pointer to an array of structures describing individual formal
parameters. */
struct ipcp_lattice *lattices;
struct ipcp_param_lattices *lattices;
/* Only for versioned nodes this field would not be NULL,
it points to the node that IPA cp cloned from. */
struct cgraph_node *ipcp_orig_node;
@ -380,6 +384,27 @@ ipa_is_param_used (struct ipa_node_params *info, int i)
return VEC_index (ipa_param_descriptor_t, info->descriptors, i).used;
}
/* Information about replacements done in aggregates for a given node (each
node has its linked list). */
struct GTY(()) ipa_agg_replacement_value
{
/* Next item in the linked list. */
struct ipa_agg_replacement_value *next;
/* Offset within the aggregate. */
HOST_WIDE_INT offset;
/* The constant value. */
tree value;
/* The paramter index. */
int index;
};
typedef struct ipa_agg_replacement_value *ipa_agg_replacement_value_p;
DEF_VEC_P (ipa_agg_replacement_value_p);
DEF_VEC_ALLOC_P (ipa_agg_replacement_value_p, gc);
void ipa_set_node_agg_value_chain (struct cgraph_node *node,
struct ipa_agg_replacement_value *aggvals);
/* 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
@ -420,6 +445,8 @@ DEF_VEC_ALLOC_O (ipa_edge_args_t, gc);
/* Vector where the parameter infos are actually stored. */
extern VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
/* Vector of known aggregate values in cloned nodes. */
extern GTY(()) VEC (ipa_agg_replacement_value_p, gc) *ipa_node_agg_replacements;
/* Vector where the parameter infos are actually stored. */
extern GTY(()) VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector;
@ -487,6 +514,18 @@ ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge)
ipa_edge_args_vector));
}
/* Return the aggregate replacements for NODE, if there are any. */
static inline struct ipa_agg_replacement_value *
ipa_get_agg_replacements_for_node (struct cgraph_node *node)
{
if ((unsigned) node->uid >= VEC_length (ipa_agg_replacement_value_p,
ipa_node_agg_replacements))
return NULL;
return VEC_index (ipa_agg_replacement_value_p, ipa_node_agg_replacements,
node->uid);
}
/* Function formal parameters related computations. */
void ipa_initialize_node_params (struct cgraph_node *node);
bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
@ -517,6 +556,7 @@ void ipcp_verify_propagated_values (void);
extern alloc_pool ipcp_values_pool;
extern alloc_pool ipcp_sources_pool;
extern alloc_pool ipcp_agg_lattice_pool;
/* Structure to describe transformations of formal parameters and actual
arguments. Each instance describes one new parameter and they are meant to
@ -589,13 +629,17 @@ void ipa_modify_call_arguments (struct cgraph_edge *, gimple,
ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec,
ipa_parm_adjustment_vec);
void ipa_dump_param_adjustments (FILE *, ipa_parm_adjustment_vec, tree);
void ipa_dump_agg_replacement_values (FILE *f,
struct ipa_agg_replacement_value *av);
void ipa_prop_write_jump_functions (void);
void ipa_prop_read_jump_functions (void);
void ipa_prop_write_all_agg_replacement (void);
void ipa_prop_read_all_agg_replacement (void);
void ipa_update_after_lto_read (void);
int ipa_get_param_decl_index (struct ipa_node_params *, tree);
tree ipa_value_from_jfunc (struct ipa_node_params *info,
struct ipa_jump_func *jfunc);
unsigned int ipcp_transform_function (struct cgraph_node *node);
/* From tree-sra.c: */

View File

@ -58,7 +58,8 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
"symbol_nodes",
"opts",
"cgraphopt",
"inline"
"inline",
"ipcp_trans"
};

View File

@ -248,6 +248,7 @@ enum lto_section_type
LTO_section_opts,
LTO_section_cgraph_opt_sum,
LTO_section_inline_summary,
LTO_section_ipcp_transform,
LTO_N_SECTION_TYPES /* Must be last. */
};

View File

@ -901,6 +901,12 @@ DEFPARAM (PARAM_IPA_MAX_AGG_ITEMS,
"jump functions and lattices",
16, 0, 0)
DEFPARAM (PARAM_IPA_CP_LOOP_HINT_BONUS,
"ipa-cp-loop-hint-bonus",
"Compile-time bonus IPA-CP assigns to candidates which make loop "
"bounds or strides known.",
64, 0, 0)
/* WHOPR partitioning configuration. */
DEFPARAM (PARAM_LTO_PARTITIONS,

View File

@ -1,3 +1,17 @@
2012-11-07 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/53787
* gcc.dg/ipa/ipa-5.c: Adjust.
* gcc.dg/ipa/ipcp-agg-1.c: New test.
* gcc.dg/ipa/ipcp-agg-2.c: Likewise.
* gcc.dg/ipa/ipcp-agg-3.c: Likewise.
* gcc.dg/ipa/ipcp-agg-4.c: Likewise.
* gcc.dg/ipa/ipcp-agg-5.c: Likewise.
* gcc.dg/ipa/ipcp-agg-6.c: Likewise.
* gfortran.dg/pr48636.f90: Add -fno-ipa-cp.
* gfortran.dg/pr48636-2.f90: New test.
* gfortran.dg/pr53787.f90: Likewise.
2012-11-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/55226

View File

@ -5,7 +5,7 @@
/* Float & short constants. */
#include <stdio.h>
void t(void);
int t(void);
int g (float b, short c)
{
t();
@ -13,10 +13,11 @@ int g (float b, short c)
}
int f (float a)
{
t();
int i, j = t();
/* a is modified. */
if (a++ > 0)
g (a, 3);
for (i = 0; i < j; i++)
g (a, 3);
}
int main ()
{
@ -26,7 +27,7 @@ int main ()
return 0;
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node" 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Creating a specialized node" 3 "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */

View File

@ -0,0 +1,37 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
void
entry (void)
{
struct S s;
s.a = 1;
s.b = 64;
s.c = 32;
foo (&s);
}
/* { dg-final { scan-ipa-dump "Creating a specialized node of foo.*for all known contexts" "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 2 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,43 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
void
entry (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 1;
s.b = 64;
s.c = 32;
foo (&s);
}
s.c = 2;
foo (&s);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 4 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,44 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (int z, struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
void
entry (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 1;
s.b = 64;
s.c = 32;
foo (i, &s);
}
s.c = 2;
foo (0, &s);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements: 1" 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements: 0" 2 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,62 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
void
entry1 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 1;
s.b = 64;
s.c = 32;
foo (&s);
}
s.c = 2;
foo (&s);
}
void
entry2 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 6;
s.b = 64;
s.c = 32;
foo (&s);
}
s.c = 2;
foo (&s);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 4 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,68 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
static void __attribute__ ((noinline))
bar (struct S *p)
{
foo (p);
}
void
entry1 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 1;
s.b = 64;
s.c = 32;
bar (&s);
}
s.c = 2;
bar (&s);
}
void
entry2 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 6;
s.b = 64;
s.c = 32;
foo (&s);
}
s.c = 2;
foo (&s);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of bar/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 8 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,75 @@
/* { dg-do compile } */
/* { dg-options "-O3 -fno-ipa-sra -fdump-ipa-cp-details -fdump-tree-optimized-slim" } */
/* { dg-add-options bind_pic_locally } */
struct S
{
int a, b, c;
};
void *blah(int, void *);
static void __attribute__ ((noinline))
foo (struct S *p)
{
int i, c = p->c;
int b = p->b;
void *v = (void *) p;
for (i= 0; i< c; i++)
v = blah(b + i, v);
}
static void __attribute__ ((noinline))
bar (struct S *p)
{
foo (p);
}
static void __attribute__ ((noinline))
bar_2 (struct S *p)
{
foo (p);
}
void
entry1 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 1;
s.b = 64;
s.c = 32;
bar (&s);
}
s.c = 2;
bar (&s);
}
void
entry2 (int c)
{
struct S s;
int i;
for (i = 0; i<c; i++)
{
s.a = 6;
s.b = 64;
s.c = 32;
bar_2 (&s);
}
s.c = 2;
foo (&s);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of bar/\[0-9\]*\\." 2 "cp" } } */
/* { dg-final { scan-ipa-dump "Creating a specialized node of bar_2.*for all known contexts" "cp" } } */
/* { dg-final { scan-ipa-dump-times "Aggregate replacements:" 10 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { scan-tree-dump-not "->c;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */

View File

@ -0,0 +1,38 @@
! { dg-do compile }
! { dg-options "-O3 -fdump-ipa-cp-details -fno-inline" }
module foo
implicit none
contains
subroutine bar(a,x)
real, dimension(:,:), intent(in) :: a
real, intent(out) :: x
integer :: i,j
x = 0
do j=1,ubound(a,2)
do i=1,ubound(a,1)
x = x + a(i,j)**2
end do
end do
end subroutine bar
end module foo
program main
use foo
implicit none
real, dimension(2,3) :: a
real :: x
integer :: i
data a /1.0, 2.0, 3.0, -1.0, -2.0, -3.0/
do i=1,2000000
call bar(a,x)
end do
print *,x
end program main
! { dg-final { scan-ipa-dump "Creating a specialized node of bar/\[0-9\]*\\." "cp" } }
! { dg-final { scan-ipa-dump-times "Aggregate replacements\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=\[^=\]*=" 2 "cp" } }
! { dg-final { cleanup-ipa-dump "cp" } }

View File

@ -1,5 +1,5 @@
! { dg-do compile }
! { dg-options "-O3 -fdump-ipa-inline-details" }
! { dg-options "-O3 -fdump-ipa-inline-details -fno-ipa-cp" }
module foo
implicit none

View File

@ -0,0 +1,21 @@
! { dg-do compile }
! { dg-options "-O3 -fdump-ipa-cp-details -fno-inline -fwhole-program" }
real x(10)
n = 10
call init(x,n)
print *, x
end program
subroutine init(x, n)
real x(10)
do i=1,n
x(i) = i*i + 1
enddo
return
end subroutine init
! { dg-final { scan-ipa-dump "Creating a specialized node of init" "cp" } }
! { dg-final { scan-ipa-dump-times "Aggregate replacements" 2 "cp" } }
! { dg-final { cleanup-ipa-dump "cp" } }