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:
parent
a57d75dc70
commit
2c9561b513
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
1475
gcc/ipa-cp.c
1475
gcc/ipa-cp.c
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
436
gcc/ipa-prop.c
436
gcc/ipa-prop.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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: */
|
||||
|
|
|
@ -58,7 +58,8 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
|
|||
"symbol_nodes",
|
||||
"opts",
|
||||
"cgraphopt",
|
||||
"inline"
|
||||
"inline",
|
||||
"ipcp_trans"
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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. */
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } } */
|
|
@ -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" } }
|
|
@ -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
|
||||
|
|
|
@ -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" } }
|
Loading…
Reference in New Issue