diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2005-07-05 16:20:53 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2005-07-05 16:20:53 +0000 |
commit | ef3303124e42a68b2fb48632746242069123c852 (patch) | |
tree | d89a5fdebc6c5d682db6ca72c2bac0046b3ef373 | |
parent | 47bcb538b497203e13bcf965302e5af682f2bf12 (diff) | |
download | gcc-ef3303124e42a68b2fb48632746242069123c852.zip gcc-ef3303124e42a68b2fb48632746242069123c852.tar.gz gcc-ef3303124e42a68b2fb48632746242069123c852.tar.bz2 |
Makefile.in: Adjust dependencies.
2005-07-05 Paolo Bonzini <bonzini@gnu.org>
* Makefile.in: Adjust dependencies.
* tree-pass.h: Add new passes and passes formerly in tree-optimize.c.
* basic-block.h (duplicate_computed_gotos): Remove, it is now static.
* alias.c (rest_of_handle_cfg, pass_cfg): New.
* bb-reorder.c (duplicate_computed_gotos): Make it static.
* cfgexpand.c (tree_expand_cfg): Add code formerly at the beginning of
rest_of_compilation.
* bb-reorder.c (gate_duplicate_computed_gotos,
pass_duplicate_computed_gotos, gate_handle_reorder_blocks,
rest_of_handle_reorder_blocks, pass_reorder_blocks,
gate_handle_partition_blocks, rest_of_handle_partition_blocks,
pass_partition_blocks): New.
* bt-load.c (gate_handle_branch_target_load_optimize,
rest_of_handle_branch_target_load_optimize,
pass_branch_target_load_optimize): New.
* cfgcleanup.c (rest_of_handle_jump, pass_jump, rest_of_handle_jump2,
pass_jump2): New.
* cfglayout.c (pass_insn_locators_initialize): New.
* cfgrtl.c (pass_free_cfg): New.
* combine.c (gate_handle_combine, rest_of_handle_combine,
pass_combine): New.
* cse.c (gate_handle_cse, rest_of_handle_cse, pass_cse,
gate_handle_cse2, rest_of_handle_cse2, pass_cse2): New.
* emit-rtl.c (pass_unshare_all_rtl, pass_remove_unnecessary_notes): New.
* except.c (pass_set_nothrow_function_flags,
pass_convert_to_eh_region_ranges, gate_handle_eh, rest_of_handle_eh,
pass_rtl_eh): New.
* final.c (pass_compute_alignments, rest_of_handle_final, pass_final,
rest_of_handle_shorten_branches, pass_shorten_branches,
rest_of_clean_state, pass_clean_state): New.
* flow.c (pass_recompute_reg_usage, gate_remove_death_notes,
rest_of_handle_remove_death_notes, pass_remove_death_notes,
rest_of_handle_life, pass_life, rest_of_handle_flow2,
pass_flow2): New.
* function.c (pass_instantiate_virtual_regs, pass_init_function,
rest_of_handle_check_leaf_regs, pass_leaf_regs): New.
* gcse.c (gate_handle_jump_bypass, rest_of_handle_jump_bypass,
pass_jump_bypass, gate_handle_gcse, rest_of_handle_gcse,
pass_gcse): New.
* global.c (rest_of_handle_global_alloc, pass_global_alloc): New.
* ifcvt.c (gate_handle_if_conversion, rest_of_handle_if_conversion,
pass_rtl_ifcvt, gate_handle_if_after_combine,
rest_of_handle_if_after_combine, pass_if_after_combine,
gate_handle_if_after_reload, rest_of_handle_if_after_reload,
pass_if_after_reload): New.
* integrate.c (pass_initial_value_sets): New.
* jump.c (pass_cleanup_barriers, purge_line_number_notes,
pass_purge_lineno_notes): New.
* mode-switching.c (rest_of_handle_mode_switching,
pass_mode_switching): New.
* local-alloc.c (rest_of_handle_local_alloc, pass_local_alloc): New.
* loop-init.c (gate_handle_loop2, rest_of_handle_loop2,
pass_loop2): New.
* loop.c (gate_handle_loop_optimize, rest_of_handle_loop_optimize,
pass_loop_optimize): New.
* modulo-sched.c (gate_handle_sms, rest_of_handle_sms,
pass_sms): New.
* postreload-gcse.c (gate_handle_gcse2, rest_of_handle_gcse2,
pass_gcse2): New.
* postreload.c (gate_handle_postreload, rest_of_handle_postreload,
pass_postreload_cse): New.
* profile.c (gate_handle_profiling, pass_profiling,
rest_of_handle_branch_prob, pass_branch_prob): New.
* recog.c (pass pass_split_for_shorten_branches, gate_do_final_split,
pass_split_before_regstack, gate_handle_split_before_regstack,
gate_handle_peephole2, rest_of_handle_peephole2, pass_peephole2,
rest_of_handle_split_all_insns, pass_split_all_insns): New.
* reg-stack.c (gate_handle_stack_regs, rest_of_handle_stack_regs,
pass_stack_regs): New.
* regmove.c (gate_handle_regmove, rest_of_handle_regmove, pass_regmove,
gate_handle_stack_adjustments, rest_of_handle_stack_adjustments,
pass_stack_adjustments): New.
* regrename.c (gate_handle_regrename, rest_of_handle_regrename,
pass_regrename): New.
* reorg.c (gate_handle_delay_slots, rest_of_handle_delay_slots,
pass_delay_slots, gate_handle_machine_reorg,
rest_of_handle_machine_reorg, pass_machine_reorg): New.
* rtl.h (extern void purge_line_number_notes): New.
* sched-rgn.c (gate_handle_sched, rest_of_handle_sched,
gate_handle_sched2, rest_of_handle_sched2, pass_sched,
pass_sched2): New.
* tracer.c (gate_handle_tracer, rest_of_handle_tracer,
pass_tracer): New.
* value-prof.c (gate_handle_value_profile_transformations,
rest_of_handle_value_profile_transformations,
pass_value_profile_transformations): New.
* var-tracking.c (gate_handle_var_tracking,
pass_variable_tracking): New.
* web.c (gate_handle_web, rest_of_handle_web, pass_web): New.
* passes.c (open_dump_file, close_dump_file, rest_of_handle_final,
rest_of_handle_delay_slots, rest_of_handle_stack_regs,
rest_of_handle_variable_tracking, rest_of_handle_machine_reorg,
rest_of_handle_old_regalloc, rest_of_handle_regrename,
rest_of_handle_reorder_blocks, rest_of_handle_partition_blocks,
rest_of_handle_sms, rest_of_handle_sched, rest_of_handle_sched2,
rest_of_handle_gcse2, rest_of_handle_regmove,
rest_of_handle_tracer, rest_of_handle_if_conversion,
rest_of_handle_if_after_combine, rest_of_handle_if_after_reload,
rest_of_handle_web, rest_of_handle_branch_prob,
rest_of_handle_value_profile_transformations, rest_of_handle_cfg,
rest_of_handle_jump_bypass, rest_of_handle_combine,
rest_of_handle_life, rest_of_handle_cse, rest_of_handle_cse2,
rest_of_handle_gcse, rest_of_handle_loop_optimize,
rest_of_handle_loop2, rest_of_handle_branch_target_load_optimize,
rest_of_handle_mode_switching, rest_of_handle_jump,
rest_of_handle_eh, rest_of_handle_stack_adjustments,
rest_of_handle_flow2, rest_of_handle_jump2,
rest_of_handle_peephole2, rest_of_handle_postreload,
rest_of_handle_shorten_branches, rest_of_clean_state,
rest_of_compilation): Remove.
* cgraphunit.c (ipa_passes): Moved from tree-optimize.c.
* passes.c (dump_flags, in_gimple_form, all_passes,
all_ipa_passes, all_lowering_passes, register_one_dump_file,
register_dump_files, next_pass_1, last_verified, execute_todo,
execute_one_pass, execute_pass_list, execute_ipa_pass_list): Moved
from tree-optimize.c.
(init_optimization_passes): Moved from tree-optimize.c,
adding the RTL optimizations.
* tree-dump.h (dump_info_p, dump_flag): Moved from tree.h.
* tree-optimize.c (dump_flags, in_gimple_form, all_passes,
all_ipa_passes, all_lowering_passes, register_one_dump_file,
register_dump_files, next_pass_1, last_verified, execute_todo,
execute_one_pass, execute_pass_list, execute_ipa_pass_list,
init_tree_optimization_passes, ipa_passes): Delete.
* tree-pass.h (enum tree_dump_index): Moved from tree.h, removing
the RTL dumps.
(TDF_*, get_dump_file_name, dump_enabled_p, dump_initialized_p,
dump_begin, dump_end, dump_node, dump_switch_p, dump_flag_name): Moved
from tree.h.
(ipa_passes): Remove.
(all_passes, all_ipa_passes, all_lowering_passes): Now extern.
* tree.h (enum tree_dump_index, TDF_*, get_dump_file_name,
dump_enabled_p, dump_initialized_p, dump_begin, dump_end, dump_node,
dump_switch_p, dump_flag_name): Moved to tree-pass.h.
(dump_info_p, dump_flag): Moved to tree-dump.h.
* Makefile.in: Adjust dependencies for tree-pretty-print.c,
cgraph.c, opts.c.
* passes.c (finish_optimization_passes): Use dump_begin
and dump_end, TDI_end.
(gate_rest_of_compilation): New.
(pass_rest_of_compilation): Use it.
(gate_postreload, pass_postreload): New.
* toplev.c (general_init): Rename init_tree_optimization_passes.
* toplev.h (init_tree_optimization_passes): Rename to
init_optimizations_passes.
* tree-dump.c (dump_flag): Make static.
(dump_files): Remove RTL dumps.
* tree-optimize.c (pass_all_optimizations, pass_early_local_passes,
pass_cleanup_cfg, pass_free_cfg_annotations,
pass_cleanup_cfg_post_optimizing, pass_free_datastructures,
pass_init_datastructures, pass_fixup_cfg): Make non-static.
* tree-pretty-print.c: Include tree-pass.h.
* cgraph.c: Include tree-dump.h.
cp:
2005-07-05 Paolo Bonzini <bonzini@gnu.org>
* Makefile.in (class.o, decl2.o): Adjust dependencies.
* class.c: Include tree-dump.h.
* decl2.c: Include tree-dump.h.
java:
2005-07-05 Paolo Bonzini <bonzini@gnu.org>
* Makefile.in (parse.o): Adjust dependencies.
* parse.y: Include tree-dump.h.
From-SVN: r101627
60 files changed, 3394 insertions, 2205 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 32e6c58..d680ff8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,163 @@ +2005-07-05 Paolo Bonzini <bonzini@gnu.org> + + * Makefile.in: Adjust dependencies. + * tree-pass.h: Add new passes and passes formerly in tree-optimize.c. + * basic-block.h (duplicate_computed_gotos): Remove, it is now static. + * alias.c (rest_of_handle_cfg, pass_cfg): New. + * bb-reorder.c (duplicate_computed_gotos): Make it static. + * cfgexpand.c (tree_expand_cfg): Add code formerly at the beginning of + rest_of_compilation. + + * bb-reorder.c (gate_duplicate_computed_gotos, + pass_duplicate_computed_gotos, gate_handle_reorder_blocks, + rest_of_handle_reorder_blocks, pass_reorder_blocks, + gate_handle_partition_blocks, rest_of_handle_partition_blocks, + pass_partition_blocks): New. + * bt-load.c (gate_handle_branch_target_load_optimize, + rest_of_handle_branch_target_load_optimize, + pass_branch_target_load_optimize): New. + * cfgcleanup.c (rest_of_handle_jump, pass_jump, rest_of_handle_jump2, + pass_jump2): New. + * cfglayout.c (pass_insn_locators_initialize): New. + * cfgrtl.c (pass_free_cfg): New. + * combine.c (gate_handle_combine, rest_of_handle_combine, + pass_combine): New. + * cse.c (gate_handle_cse, rest_of_handle_cse, pass_cse, + gate_handle_cse2, rest_of_handle_cse2, pass_cse2): New. + * emit-rtl.c (pass_unshare_all_rtl, pass_remove_unnecessary_notes): New. + * except.c (pass_set_nothrow_function_flags, + pass_convert_to_eh_region_ranges, gate_handle_eh, rest_of_handle_eh, + pass_rtl_eh): New. + * final.c (pass_compute_alignments, rest_of_handle_final, pass_final, + rest_of_handle_shorten_branches, pass_shorten_branches, + rest_of_clean_state, pass_clean_state): New. + * flow.c (pass_recompute_reg_usage, gate_remove_death_notes, + rest_of_handle_remove_death_notes, pass_remove_death_notes, + rest_of_handle_life, pass_life, rest_of_handle_flow2, + pass_flow2): New. + * function.c (pass_instantiate_virtual_regs, pass_init_function, + rest_of_handle_check_leaf_regs, pass_leaf_regs): New. + * gcse.c (gate_handle_jump_bypass, rest_of_handle_jump_bypass, + pass_jump_bypass, gate_handle_gcse, rest_of_handle_gcse, + pass_gcse): New. + * global.c (rest_of_handle_global_alloc, pass_global_alloc): New. + * ifcvt.c (gate_handle_if_conversion, rest_of_handle_if_conversion, + pass_rtl_ifcvt, gate_handle_if_after_combine, + rest_of_handle_if_after_combine, pass_if_after_combine, + gate_handle_if_after_reload, rest_of_handle_if_after_reload, + pass_if_after_reload): New. + * integrate.c (pass_initial_value_sets): New. + * jump.c (pass_cleanup_barriers, purge_line_number_notes, + pass_purge_lineno_notes): New. + * mode-switching.c (rest_of_handle_mode_switching, + pass_mode_switching): New. + * local-alloc.c (rest_of_handle_local_alloc, pass_local_alloc): New. + * loop-init.c (gate_handle_loop2, rest_of_handle_loop2, + pass_loop2): New. + * loop.c (gate_handle_loop_optimize, rest_of_handle_loop_optimize, + pass_loop_optimize): New. + * modulo-sched.c (gate_handle_sms, rest_of_handle_sms, + pass_sms): New. + * postreload-gcse.c (gate_handle_gcse2, rest_of_handle_gcse2, + pass_gcse2): New. + * postreload.c (gate_handle_postreload, rest_of_handle_postreload, + pass_postreload_cse): New. + * profile.c (gate_handle_profiling, pass_profiling, + rest_of_handle_branch_prob, pass_branch_prob): New. + * recog.c (pass pass_split_for_shorten_branches, gate_do_final_split, + pass_split_before_regstack, gate_handle_split_before_regstack, + gate_handle_peephole2, rest_of_handle_peephole2, pass_peephole2, + rest_of_handle_split_all_insns, pass_split_all_insns): New. + * reg-stack.c (gate_handle_stack_regs, rest_of_handle_stack_regs, + pass_stack_regs): New. + * regmove.c (gate_handle_regmove, rest_of_handle_regmove, pass_regmove, + gate_handle_stack_adjustments, rest_of_handle_stack_adjustments, + pass_stack_adjustments): New. + * regrename.c (gate_handle_regrename, rest_of_handle_regrename, + pass_regrename): New. + * reorg.c (gate_handle_delay_slots, rest_of_handle_delay_slots, + pass_delay_slots, gate_handle_machine_reorg, + rest_of_handle_machine_reorg, pass_machine_reorg): New. + * rtl.h (extern void purge_line_number_notes): New. + * sched-rgn.c (gate_handle_sched, rest_of_handle_sched, + gate_handle_sched2, rest_of_handle_sched2, pass_sched, + pass_sched2): New. + * tracer.c (gate_handle_tracer, rest_of_handle_tracer, + pass_tracer): New. + * value-prof.c (gate_handle_value_profile_transformations, + rest_of_handle_value_profile_transformations, + pass_value_profile_transformations): New. + * var-tracking.c (gate_handle_var_tracking, + pass_variable_tracking): New. + * web.c (gate_handle_web, rest_of_handle_web, pass_web): New. + + * passes.c (open_dump_file, close_dump_file, rest_of_handle_final, + rest_of_handle_delay_slots, rest_of_handle_stack_regs, + rest_of_handle_variable_tracking, rest_of_handle_machine_reorg, + rest_of_handle_old_regalloc, rest_of_handle_regrename, + rest_of_handle_reorder_blocks, rest_of_handle_partition_blocks, + rest_of_handle_sms, rest_of_handle_sched, rest_of_handle_sched2, + rest_of_handle_gcse2, rest_of_handle_regmove, + rest_of_handle_tracer, rest_of_handle_if_conversion, + rest_of_handle_if_after_combine, rest_of_handle_if_after_reload, + rest_of_handle_web, rest_of_handle_branch_prob, + rest_of_handle_value_profile_transformations, rest_of_handle_cfg, + rest_of_handle_jump_bypass, rest_of_handle_combine, + rest_of_handle_life, rest_of_handle_cse, rest_of_handle_cse2, + rest_of_handle_gcse, rest_of_handle_loop_optimize, + rest_of_handle_loop2, rest_of_handle_branch_target_load_optimize, + rest_of_handle_mode_switching, rest_of_handle_jump, + rest_of_handle_eh, rest_of_handle_stack_adjustments, + rest_of_handle_flow2, rest_of_handle_jump2, + rest_of_handle_peephole2, rest_of_handle_postreload, + rest_of_handle_shorten_branches, rest_of_clean_state, + rest_of_compilation): Remove. + + * cgraphunit.c (ipa_passes): Moved from tree-optimize.c. + * passes.c (dump_flags, in_gimple_form, all_passes, + all_ipa_passes, all_lowering_passes, register_one_dump_file, + register_dump_files, next_pass_1, last_verified, execute_todo, + execute_one_pass, execute_pass_list, execute_ipa_pass_list): Moved + from tree-optimize.c. + (init_optimization_passes): Moved from tree-optimize.c, + adding the RTL optimizations. + * tree-dump.h (dump_info_p, dump_flag): Moved from tree.h. + * tree-optimize.c (dump_flags, in_gimple_form, all_passes, + all_ipa_passes, all_lowering_passes, register_one_dump_file, + register_dump_files, next_pass_1, last_verified, execute_todo, + execute_one_pass, execute_pass_list, execute_ipa_pass_list, + init_tree_optimization_passes, ipa_passes): Delete. + * tree-pass.h (enum tree_dump_index): Moved from tree.h, removing + the RTL dumps. + (TDF_*, get_dump_file_name, dump_enabled_p, dump_initialized_p, + dump_begin, dump_end, dump_node, dump_switch_p, dump_flag_name): Moved + from tree.h. + (ipa_passes): Remove. + (all_passes, all_ipa_passes, all_lowering_passes): Now extern. + * tree.h (enum tree_dump_index, TDF_*, get_dump_file_name, + dump_enabled_p, dump_initialized_p, dump_begin, dump_end, dump_node, + dump_switch_p, dump_flag_name): Moved to tree-pass.h. + (dump_info_p, dump_flag): Moved to tree-dump.h. + + * Makefile.in: Adjust dependencies for tree-pretty-print.c, + cgraph.c, opts.c. + * passes.c (finish_optimization_passes): Use dump_begin + and dump_end, TDI_end. + (gate_rest_of_compilation): New. + (pass_rest_of_compilation): Use it. + (gate_postreload, pass_postreload): New. + * toplev.c (general_init): Rename init_tree_optimization_passes. + * toplev.h (init_tree_optimization_passes): Rename to + init_optimizations_passes. + * tree-dump.c (dump_flag): Make static. + (dump_files): Remove RTL dumps. + * tree-optimize.c (pass_all_optimizations, pass_early_local_passes, + pass_cleanup_cfg, pass_free_cfg_annotations, + pass_cleanup_cfg_post_optimizing, pass_free_datastructures, + pass_init_datastructures, pass_fixup_cfg): Make non-static. + * tree-pretty-print.c: Include tree-pass.h. + * cgraph.c: Include tree-dump.h. + 2005-07-04 Daniel Berlin <dberlin@dberlin.org> * tree-ssa-structalias.c (get_constraint_exp_from_ssa_var): diff --git a/gcc/Makefile.in b/gcc/Makefile.in index bf2a843..0d08b79 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1966,7 +1966,7 @@ tree-nomudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) tree-inline.h \ $(GGC_H) gt-tree-mudflap.h tree-pass.h toplev.h tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(DIAGNOSTIC_H) real.h $(HASHTAB_H) $(TREE_FLOW_H) \ - $(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h + $(TM_H) coretypes.h tree-iterator.h tree-chrec.h langhooks.h tree-pass.h fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(FLAGS_H) real.h toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \ $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) @@ -1976,7 +1976,7 @@ diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ opts.o : opts.c opts.h options.h toplev.h $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \ output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \ - $(FLAGS_H) $(PARAMS_H) + $(FLAGS_H) $(PARAMS_H) tree-pass.h targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ $(EXPR_H) $(TM_H) $(RTL_H) $(TM_P_H) function.h output.h toplev.h \ $(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h @@ -2002,7 +2002,7 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(PARAMS_H) $(TM_P_H) reload.h dwarf2asm.h $(TARGET_H) \ langhooks.h insn-flags.h $(CFGLAYOUT_H) real.h $(CFGLOOP_H) \ hosthooks.h $(CGRAPH_H) $(COVERAGE_H) tree-pass.h $(TREE_DUMP_H) \ - $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h + $(GGC_H) $(INTEGRATE_H) $(CPPLIB_H) opts.h tree-flow.h tree-inline.h main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h @@ -2032,7 +2032,8 @@ function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(CFGLAYOUT_H) $(TREE_GIMPLE_H) $(FLAGS_H) function.h $(EXPR_H) \ $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \ output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) $(TM_P_H) langhooks.h \ - gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(INTEGRATE_H) $(PREDICT_H) + gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(INTEGRATE_H) $(PREDICT_H) \ + tree-pass.h stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) function.h insn-config.h hard-reg-set.h $(EXPR_H) \ libfuncs.h except.h $(RECOG_H) toplev.h output.h $(GGC_H) $(TM_P_H) \ @@ -2043,7 +2044,7 @@ except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \ dwarf2asm.h dwarf2out.h toplev.h $(HASHTAB_H) intl.h $(GGC_H) \ gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \ - $(TARGET_H) $(TM_P_H) + $(TARGET_H) $(TM_P_H) tree-pass.h timevar.h expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) function.h $(REGS_H) $(EXPR_H) $(OPTABS_H) \ libfuncs.h $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \ @@ -2100,16 +2101,17 @@ xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) function.h $(REGS_H) insn-config.h $(RECOG_H) real.h \ $(GGC_H) $(EXPR_H) hard-reg-set.h bitmap.h toplev.h $(BASIC_BLOCK_H) \ - $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h gt-emit-rtl.h + $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h tree-pass.h gt-emit-rtl.h real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ toplev.h $(TM_P_H) real.h integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) $(FLAGS_H) debug.h $(INTEGRATE_H) insn-config.h \ $(EXPR_H) real.h $(REGS_H) intl.h function.h output.h $(RECOG_H) \ except.h toplev.h $(PARAMS_H) $(TM_P_H) $(TARGET_H) langhooks.h \ - gt-integrate.h $(GGC_H) + gt-integrate.h $(GGC_H) tree-pass.h jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \ - hard-reg-set.h $(REGS_H) insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h function.h \ + hard-reg-set.h $(REGS_H) insn-config.h $(RECOG_H) $(EXPR_H) real.h except.h \ + function.h tree-pass.h \ toplev.h $(INSN_ATTR_H) $(TM_P_H) reload.h $(PREDICT_H) $(TIMEVAR_H) \ $(DIAGNOSTIC_H) @@ -2120,7 +2122,7 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ langhooks.h toplev.h $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \ gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ - tree-inline.h $(VARRAY_H) + tree-inline.h $(VARRAY_H) tree-dump.h cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h tree-inline.h toplev.h $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h function.h $(TREE_GIMPLE_H) \ @@ -2142,24 +2144,25 @@ cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ cse.o : cse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ hard-reg-set.h $(FLAGS_H) real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \ output.h function.h $(BASIC_BLOCK_H) $(GGC_H) $(TM_P_H) $(TIMEVAR_H) \ - except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h + except.h $(TARGET_H) $(PARAMS_H) rtlhooks-def.h tree-pass.h web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) function.h output.h toplev.h \ - $(DF_H) $(OBSTACK_H) + $(DF_H) $(OBSTACK_H) timevar.h tree-pass.h gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h $(GGC_H) \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) function.h output.h toplev.h \ $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h $(TREE_H) cselib.h $(TIMEVAR_H) \ - intl.h $(OBSTACK_H) + intl.h $(OBSTACK_H) tree-pass.h resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) \ coretypes.h $(TM_H) $(REGS_H) $(FLAGS_H) output.h $(RESOURCE_H) \ function.h toplev.h $(INSN_ATTR_H) except.h $(PARAMS_H) $(TM_P_H) lcm.o : lcm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \ hard-reg-set.h $(FLAGS_H) real.h insn-config.h $(INSN_ATTR_H) $(RECOG_H) \ $(BASIC_BLOCK_H) $(TM_P_H) function.h output.h -mode-switching.o : mode-switching.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ - $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h \ - $(INSN_ATTR_H) $(RECOG_H) $(BASIC_BLOCK_H) $(TM_P_H) function.h output.h +mode-switching.o : mode-switching.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h \ + $(INSN_ATTR_H) $(RECOG_H) $(BASIC_BLOCK_H) $(TM_P_H) function.h output.h \ + tree-pass.h timevar.h tree-ssa-dce.o : tree-ssa-dce.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \ $(RTL_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) \ coretypes.h $(TREE_DUMP_H) tree-pass.h $(FLAGS_H) $(BASIC_BLOCK_H) \ @@ -2190,12 +2193,13 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \ $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ - $(REGS_H) $(EXPR_H) + $(REGS_H) $(EXPR_H) timevar.h tree-pass.h conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \ $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) function.h \ - toplev.h $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h + toplev.h $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \ + cfgloop.h timevar.h tree-pass.h tree-profile.o : tree-profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \ function.h toplev.h $(COVERAGE_H) $(TREE_H) value-prof.h $(TREE_DUMP_H) \ @@ -2207,11 +2211,12 @@ value-prof.o : value-prof.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(BASIC_BLOCK_H) hard-reg-set.h value-prof.h $(EXPR_H) output.h $(FLAGS_H) \ $(RECOG_H) insn-config.h $(OPTABS_H) $(REGS_H) $(GGC_H) $(DIAGNOSTIC_H) \ $(TREE_H) $(COVERAGE_H) $(RTL_H) $(GCOV_IO_H) $(TREE_FLOW_H) \ - tree-flow-inline.h + tree-flow-inline.h timevar.h tree-pass.h loop.o : loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) insn-config.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) \ real.h $(PREDICT_H) $(BASIC_BLOCK_H) function.h $(CFGLOOP_H) \ - toplev.h except.h cselib.h $(OPTABS_H) $(TM_P_H) $(GGC_H) insn-flags.h + toplev.h except.h cselib.h $(OPTABS_H) $(TM_P_H) $(GGC_H) insn-flags.h \ + timevar.h tree-pass.h loop-doloop.o : loop-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \ toplev.h $(CFGLOOP_H) output.h $(PARAMS_H) @@ -2219,7 +2224,7 @@ alloc-pool.o : alloc-pool.c $(CONFIG_H) $(SYSTEM_H) alloc-pool.h $(HASHTAB_H) flow.o : flow.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) \ hard-reg-set.h output.h toplev.h $(RECOG_H) function.h except.h \ - $(EXPR_H) $(TM_P_H) $(OBSTACK_H) $(SPLAY_TREE_H) $(TIMEVAR_H) + $(EXPR_H) $(TM_P_H) $(OBSTACK_H) $(SPLAY_TREE_H) $(TIMEVAR_H) tree-pass.h cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \ $(REGS_H) hard-reg-set.h output.h toplev.h function.h except.h $(GGC_H) \ $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h $(HASHTAB_H) @@ -2228,11 +2233,12 @@ cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) function.h $(TIMEVAR_H) $(TM_H) \ coretypes.h $(TREE_DUMP_H) except.h langhooks.h tree-pass.h $(RTL_H) \ - $(DIAGNOSTIC_H) toplev.h $(BASIC_BLOCK_H) $(FLAGS_H) $(PARAMS_H) + $(DIAGNOSTIC_H) toplev.h $(BASIC_BLOCK_H) $(FLAGS_H) debug.h $(PARAMS_H) cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ output.h toplev.h function.h except.h $(TM_P_H) insn-config.h $(EXPR_H) \ - $(CFGLAYOUT_H) $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) + $(CFGLAYOUT_H) $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \ + tree-pass.h cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \ $(TIMEVAR_H) $(OBSTACK_H) toplev.h @@ -2242,7 +2248,7 @@ cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TIMEVAR_H) hard-reg-set.h output.h $(FLAGS_H) $(RECOG_H) \ toplev.h insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \ - $(REGS_H) $(EMIT_RTL_H) $(CFGLAYOUT_H) + $(REGS_H) $(EMIT_RTL_H) $(CFGLAYOUT_H) tree-pass.h cfgloop.h expr.h cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(FLAGS_H) function.h \ $(OBSTACK_H) toplev.h $(TREE_FLOW_H) $(TREE_H) @@ -2260,7 +2266,7 @@ cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ coretypes.h $(TM_H) cfghooks.h $(OBSTACK_H) loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) \ - coretypes.h $(TM_H) $(OBSTACK_H) + coretypes.h $(TM_H) $(OBSTACK_H) tree-pass.h timevar.h $(FLAGS_H) loop-unswitch.o : loop-unswitch.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \ output.h $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) @@ -2276,7 +2282,7 @@ combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) function.h insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \ rtlhooks-def.h $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h \ toplev.h $(TM_P_H) $(TREE_H) $(TARGET_H) output.h $(PARAMS_H) $(OPTABS_H) \ - insn-codes.h + insn-codes.h timevar.h tree-pass.h regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(REGS_H) insn-config.h \ $(RECOG_H) reload.h real.h toplev.h function.h output.h $(GGC_H) \ @@ -2284,12 +2290,13 @@ regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \ output.h function.h $(INSN_ATTR_H) toplev.h except.h reload.h $(TM_P_H) \ - $(GGC_H) $(INTEGRATE_H) + $(GGC_H) $(INTEGRATE_H) timevar.h tree-pass.h bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(GGC_H) gt-bitmap.h bitmap.h $(OBSTACK_H) global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) reload.h function.h $(RECOG_H) $(REGS_H) hard-reg-set.h \ - insn-config.h output.h toplev.h $(TM_P_H) $(MACHMODE_H) + insn-config.h output.h toplev.h $(TM_P_H) $(MACHMODE_H) tree-pass.h \ + timevar.h varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \ $(HASHTAB_H) $(BCONFIG_H) $(VARRAY_H) toplev.h vec.o : vec.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) coretypes.h vec.h $(GGC_H) \ @@ -2308,28 +2315,30 @@ postreload.o : postreload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) real.h $(FLAGS_H) $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) \ hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) $(RECOG_H) output.h \ function.h toplev.h cselib.h $(TM_P_H) except.h $(TREE_H) $(MACHMODE_H) \ - $(OBSTACK_H) + $(OBSTACK_H) timevar.h tree-pass.h postreload-gcse.o : postreload-gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) real.h insn-config.h \ $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) function.h output.h toplev.h \ $(TM_P_H) except.h $(TREE_H) $(TARGET_H) $(HASHTAB_H) intl.h $(OBSTACK_H) \ - $(PARAMS_H) + $(PARAMS_H) timevar.h tree-pass.h caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \ $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H) bt-load.o : bt-load.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) except.h \ - $(RTL_H) hard-reg-set.h $(REGS_H) $(TM_P_H) $(FIBHEAP_H) output.h \ - $(TARGET_H) $(EXPR_H) $(FLAGS_H) $(INSN_ATTR_H) function.h + $(RTL_H) hard-reg-set.h $(REGS_H) $(TM_P_H) $(FIBHEAP_H) output.h $(EXPR_H) \ + $(TARGET_H) $(FLAGS_H) $(INSN_ATTR_H) function.h tree-pass.h toplev.h reorg.o : reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ conditions.h hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h \ $(INSN_ATTR_H) except.h $(RECOG_H) function.h $(FLAGS_H) output.h \ - $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H) $(OBSTACK_H) $(RESOURCE_H) + $(EXPR_H) toplev.h $(PARAMS_H) $(TM_P_H) $(OBSTACK_H) $(RESOURCE_H) \ + timevar.h target.h tree-pass.h alias.o : alias.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(FLAGS_H) hard-reg-set.h $(BASIC_BLOCK_H) $(REGS_H) toplev.h output.h \ $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) function.h cselib.h $(TREE_H) $(TM_P_H) \ langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \ - $(SPLAY_TREE_H) $(VARRAY_H) -regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) insn-config.h \ + $(SPLAY_TREE_H) $(VARRAY_H) tree-pass.h +regmove.o : regmove.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ + insn-config.h timevar.h tree-pass.h \ $(RECOG_H) output.h $(REGS_H) hard-reg-set.h $(FLAGS_H) function.h \ $(EXPR_H) $(BASIC_BLOCK_H) toplev.h $(TM_P_H) except.h reload.h ddg.o : ddg.c $(DDG_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) \ @@ -2341,7 +2350,7 @@ modulo-sched.o : modulo-sched.c $(DDG_H) $(CONFIG_H) $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TARGET_H) toplev.h $(RTL_H) $(TM_P_H) $(REGS_H) function.h \ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) except.h $(RECOG_H) \ $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \ - cfghooks.h $(DF_H) $(GCOV_IO_H) hard-reg-set.h $(TM_H) + cfghooks.h $(DF_H) $(GCOV_IO_H) hard-reg-set.h $(TM_H) timevar.h tree-pass.h haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h function.h \ $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) $(TARGET_H) @@ -2352,7 +2361,7 @@ sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ function.h $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \ - $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) + $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) timevar.h tree-pass.h sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ function.h $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(TM_P_H) \ @@ -2363,16 +2372,17 @@ sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) intl.h $(REGS_H) $(RECOG_H) conditions.h \ insn-config.h $(INSN_ATTR_H) function.h real.h output.h hard-reg-set.h \ - except.h debug.h xcoffout.h toplev.h reload.h dwarf2out.h \ - $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) $(CFGLAYOUT_H) dbxout.h + except.h debug.h xcoffout.h toplev.h reload.h dwarf2out.h tree-pass.h \ + $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) $(CFGLAYOUT_H) dbxout.h \ + timevar.h cgraph.h coverage.h recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ function.h $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) hard-reg-set.h \ $(FLAGS_H) insn-config.h $(INSN_ATTR_H) real.h toplev.h output.h reload.h \ - $(TM_P_H) + $(TM_P_H) timevar.h tree-pass.h reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) $(RECOG_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \ insn-config.h toplev.h reload.h function.h $(TM_P_H) $(GGC_H) \ - gt-reg-stack.h $(BASIC_BLOCK_H) output.h $(VARRAY_H) + gt-reg-stack.h $(BASIC_BLOCK_H) output.h $(VARRAY_H) timevar.h tree-pass.h sreal.o: sreal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) sreal.h predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) \ @@ -2385,24 +2395,25 @@ lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h \ bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \ $(TARGET_H) function.h $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) \ - $(PARAMS_H) toplev.h + $(PARAMS_H) toplev.h tree-pass.h tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h output.h $(CFGLAYOUT_H) \ - $(FLAGS_H) $(TIMEVAR_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) + $(FLAGS_H) $(TIMEVAR_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) \ + tree-pass.h cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(TREE_H) insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h output.h \ function.h $(CFGLAYOUT_H) $(CFGLOOP_H) $(TARGET_H) gt-cfglayout.h \ - $(GGC_H) alloc-pool.h $(FLAGS_H) $(OBSTACK_H) + $(GGC_H) alloc-pool.h $(FLAGS_H) $(OBSTACK_H) tree-pass.h timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TIMEVAR_H) $(FLAGS_H) intl.h toplev.h $(RTL_H) timevar.def regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \ output.h $(RECOG_H) function.h $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \ - reload.h toplev.h + reload.h toplev.h timevar.h tree-pass.h ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(REGS_H) toplev.h $(FLAGS_H) insn-config.h function.h $(RECOG_H) \ $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h except.h $(TM_P_H) \ - real.h $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h + real.h $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h timevar.h tree-pass.h lambda-mat.o : lambda-mat.c $(LAMBDA_H) $(GGC_H) $(SYSTEM_H) $(CONFIG_H) \ $(TM_H) coretypes.h $(TREE_H) $(VARRAY_H) lambda-trans.o: lambda-trans.c $(LAMBDA_H) $(GGC_H) $(SYSTEM_H) $(CONFIG_H) \ diff --git a/gcc/alias.c b/gcc/alias.c index e0c9766..9bc11d7 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -44,6 +44,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "target.h" #include "cgraph.h" #include "varray.h" +#include "tree-pass.h" /* The alias sets assigned to MEMs assist the back-end in determining which MEMs can alias which other MEMs. In general, two MEMs in @@ -2967,5 +2968,57 @@ end_alias_analysis (void) alias_invariant_size = 0; } } + +/* Do control and data flow analysis; write some of the results to the + dump file. */ +static void +rest_of_handle_cfg (void) +{ + if (dump_file) + dump_flow_info (dump_file); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + + /* It may make more sense to mark constant functions after dead code is + eliminated by life_analysis, but we need to do it early, as -fprofile-arcs + may insert code making function non-constant, but we still must consider + it as constant, otherwise -fbranch-probabilities will not read data back. + + life_analysis rarely eliminates modification of external memory. + + FIXME: now with tree based profiling we are in the trap described above + again. It seems to be easiest to disable the optimization for time + being before the problem is either solved by moving the transformation + to the IPA level (we need the CFG for this) or the very early optimization + passes are made to ignore the const/pure flags so code does not change. */ + if (optimize + && (!flag_tree_based_profiling + || (!profile_arc_flag && !flag_branch_probabilities))) + { + /* Alias analysis depends on this information and mark_constant_function + depends on alias analysis. */ + reg_scan (get_insns (), max_reg_num ()); + mark_constant_function (); + } +} + +struct tree_opt_pass pass_cfg = +{ + "cfg", /* name */ + NULL, /* gate */ + rest_of_handle_cfg, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FLOW, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'f' /* letter */ +}; + #include "gt-alias.h" diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 46bd83d..267b02d 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -926,7 +926,6 @@ extern bool control_flow_insn_p (rtx); /* In bb-reorder.c */ extern void reorder_basic_blocks (unsigned int); -extern void duplicate_computed_gotos (void); extern void partition_hot_cold_basic_blocks (void); /* In dominance.c */ diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index e81deba..76faeda 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -83,6 +83,11 @@ #include "expr.h" #include "params.h" #include "toplev.h" +#include "tree-pass.h" + +#ifndef HAVE_conditional_execution +#define HAVE_conditional_execution 0 +#endif /* The number of rounds. In most cases there will only be 4 rounds, but when partitioning hot and cold basic blocks into separate sections of @@ -1894,8 +1899,6 @@ reorder_basic_blocks (unsigned int flags) if (targetm.cannot_modify_jumps_p ()) return; - timevar_push (TV_REORDER_BLOCKS); - cfg_layout_initialize (flags); set_edge_can_fallthru_flag (); @@ -1931,8 +1934,6 @@ reorder_basic_blocks (unsigned int flags) cfg_layout_finalize (); if (flag_reorder_blocks_and_partition) verify_hot_cold_block_grouping (); - - timevar_pop (TV_REORDER_BLOCKS); } /* Determine which partition the first basic block in the function @@ -1970,7 +1971,14 @@ insert_section_boundary_note (void) which can seriously pessimize code with many computed jumps in the source code, such as interpreters. See e.g. PR15242. */ -void +static bool +gate_duplicate_computed_gotos (void) +{ + return (optimize > 0 && flag_expensive_optimizations && !optimize_size); +} + + +static void duplicate_computed_gotos (void) { basic_block bb, new_bb; @@ -1983,8 +1991,6 @@ duplicate_computed_gotos (void) if (targetm.cannot_modify_jumps_p ()) return; - timevar_push (TV_REORDER_BLOCKS); - cfg_layout_initialize (0); /* We are estimating the length of uncond jump insn only once @@ -2076,10 +2082,26 @@ done: cfg_layout_finalize (); BITMAP_FREE (candidates); - - timevar_pop (TV_REORDER_BLOCKS); } +struct tree_opt_pass pass_duplicate_computed_gotos = +{ + NULL, /* name */ + gate_duplicate_computed_gotos, /* gate */ + duplicate_computed_gotos, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REORDER_BLOCKS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + /* This function is the main 'entrance' for the optimization that partitions hot and cold basic blocks into separate sections of the .o file (to improve performance and cache locality). Ideally it @@ -2169,3 +2191,104 @@ partition_hot_cold_basic_blocks (void) cfg_layout_finalize(); } + +static bool +gate_handle_reorder_blocks (void) +{ + return (optimize > 0); +} + + +/* Reorder basic blocks. */ +static void +rest_of_handle_reorder_blocks (void) +{ + bool changed; + unsigned int liveness_flags; + + /* Last attempt to optimize CFG, as scheduling, peepholing and insn + splitting possibly introduced more crossjumping opportunities. */ + liveness_flags = (!HAVE_conditional_execution ? CLEANUP_UPDATE_LIFE : 0); + changed = cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags); + + if (flag_sched2_use_traces && flag_schedule_insns_after_reload) + { + timevar_push (TV_TRACER); + tracer (liveness_flags); + timevar_pop (TV_TRACER); + } + + if (flag_reorder_blocks || flag_reorder_blocks_and_partition) + reorder_basic_blocks (liveness_flags); + if (flag_reorder_blocks || flag_reorder_blocks_and_partition + || (flag_sched2_use_traces && flag_schedule_insns_after_reload)) + changed |= cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags); + + /* On conditional execution targets we can not update the life cheaply, so + we deffer the updating to after both cleanups. This may lose some cases + but should not be terribly bad. */ + if (changed && HAVE_conditional_execution) + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_DEATH_NOTES); +} + +struct tree_opt_pass pass_reorder_blocks = +{ + "bbro", /* name */ + gate_handle_reorder_blocks, /* gate */ + rest_of_handle_reorder_blocks, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REORDER_BLOCKS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'B' /* letter */ +}; + +static bool +gate_handle_partition_blocks (void) +{ + /* The optimization to partition hot/cold basic blocks into separate + sections of the .o file does not work well with linkonce or with + user defined section attributes. Don't call it if either case + arises. */ + + return (flag_reorder_blocks_and_partition + && !DECL_ONE_ONLY (current_function_decl) + && !user_defined_section_attribute); +} + +/* Partition hot and cold basic blocks. */ +static void +rest_of_handle_partition_blocks (void) +{ + no_new_pseudos = 0; + partition_hot_cold_basic_blocks (); + allocate_reg_life_data (); + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); + no_new_pseudos = 1; +} + +struct tree_opt_pass pass_partition_blocks = +{ + NULL, /* name */ + gate_handle_partition_blocks, /* gate */ + rest_of_handle_partition_blocks, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REORDER_BLOCKS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + diff --git a/gcc/bt-load.c b/gcc/bt-load.c index c1b794d..e8b0225 100644 --- a/gcc/bt-load.c +++ b/gcc/bt-load.c @@ -34,6 +34,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "function.h" #include "except.h" #include "tm_p.h" +#include "toplev.h" +#include "tree-pass.h" /* Target register optimizations - these are performed after reload. */ @@ -1479,3 +1481,50 @@ branch_target_load_optimize (bool after_prologue_epilogue_gen) PROP_DEATH_NOTES | PROP_REG_INFO); } } + +static bool +gate_handle_branch_target_load_optimize (void) +{ + return (optimize > 0 && flag_branch_target_load_optimize2); +} + + +static void +rest_of_handle_branch_target_load_optimize (void) +{ + static int warned = 0; + + /* Leave this a warning for now so that it is possible to experiment + with running this pass twice. In 3.6, we should either make this + an error, or use separate dump files. */ + if (flag_branch_target_load_optimize + && flag_branch_target_load_optimize2 + && !warned) + { + warning (0, "branch target register load optimization is not intended " + "to be run twice"); + + warned = 1; + } + + branch_target_load_optimize (epilogue_completed); +} + +struct tree_opt_pass pass_branch_target_load_optimize = +{ + "btl", /* name */ + gate_handle_branch_target_load_optimize, /* gate */ + rest_of_handle_branch_target_load_optimize, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'd' /* letter */ +}; + diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 9d224f9..a5a5d07 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -50,6 +50,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "target.h" #include "cfglayout.h" #include "emit-rtl.h" +#include "tree-pass.h" +#include "cfgloop.h" +#include "expr.h" /* cleanup_cfg maintains following flags for each basic block. */ @@ -2136,3 +2139,81 @@ cleanup_cfg (int mode) return changed; } + +static void +rest_of_handle_jump (void) +{ + delete_unreachable_blocks (); + + if (cfun->tail_call_emit) + fixup_tail_calls (); +} + +struct tree_opt_pass pass_jump = +{ + "sibling", /* name */ + NULL, /* gate */ + rest_of_handle_jump, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_JUMP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_ggc_collect, /* todo_flags_start */ + TODO_dump_func | + TODO_verify_flow, /* todo_flags_finish */ + 'i' /* letter */ +}; + + +static void +rest_of_handle_jump2 (void) +{ + /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this + before jump optimization switches branch directions. */ + if (flag_guess_branch_prob) + expected_value_to_br_prob (); + + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + reg_scan (get_insns (), max_reg_num ()); + if (dump_file) + dump_flow_info (dump_file); + cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + + create_loop_notes (); + + purge_line_number_notes (); + + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); + + /* Jump optimization, and the removal of NULL pointer checks, may + have reduced the number of instructions substantially. CSE, and + future passes, allocate arrays whose dimensions involve the + maximum instruction UID, so if we can reduce the maximum UID + we'll save big on memory. */ + renumber_insns (dump_file); +} + + +struct tree_opt_pass pass_jump2 = +{ + "jump", /* name */ + NULL, /* gate */ + rest_of_handle_jump2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_JUMP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_ggc_collect, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'j' /* letter */ +}; + + diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bb6ca4a..a3bd41c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -37,9 +37,9 @@ Boston, MA 02110-1301, USA. */ #include "flags.h" #include "diagnostic.h" #include "toplev.h" +#include "debug.h" #include "params.h" - /* Verify that there is exactly single jump instruction since last and attach REG_BR_PROB note specifying probability. ??? We really ought to pass the probability down to RTL expanders and let it @@ -1556,6 +1556,30 @@ tree_expand_cfg (void) "\n\n;;\n;; Full RTL generated for this function:\n;;\n"); /* And the pass manager will dump RTL for us. */ } + + /* If we're emitting a nested function, make sure its parent gets + emitted as well. Doing otherwise confuses debug info. */ + { + tree parent; + for (parent = DECL_CONTEXT (current_function_decl); + parent != NULL_TREE; + parent = get_containing_scope (parent)) + if (TREE_CODE (parent) == FUNCTION_DECL) + TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1; + } + + /* We are now committed to emitting code for this function. Do any + preparation, such as emitting abstract debug info for the inline + before it gets mangled by optimization. */ + if (cgraph_function_possibly_inlined_p (current_function_decl)) + (*debug_hooks->outlining_inline_function) (current_function_decl); + + TREE_ASM_WRITTEN (current_function_decl) = 1; + +#ifdef FINALIZE_PIC + if (flag_pic) + FINALIZE_PIC; +#endif } struct tree_opt_pass pass_expand = @@ -1572,6 +1596,6 @@ struct tree_opt_pass pass_expand = PROP_rtl, /* properties_provided */ PROP_gimple_leh, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 'r' /* letter */ }; diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 16438cc..2a8a122 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "ggc.h" #include "alloc-pool.h" #include "flags.h" +#include "tree-pass.h" /* Holds the interesting trailing notes for the function. */ rtx cfg_layout_function_footer, cfg_layout_function_header; @@ -330,6 +331,24 @@ insn_locators_initialize (void) free_block_changes (); } +struct tree_opt_pass pass_insn_locators_initialize = +{ + NULL, /* name */ + NULL, /* gate */ + insn_locators_initialize, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + /* For each lexical block, set BLOCK_NUMBER to the depth at which it is found in the block tree. */ diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 897df5d..30290d4 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -59,6 +59,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "target.h" #include "cfgloop.h" #include "ggc.h" +#include "tree-pass.h" static int can_delete_note_p (rtx); static int can_delete_label_p (rtx); @@ -418,6 +419,23 @@ free_bb_for_insn (void) BLOCK_FOR_INSN (insn) = NULL; } +struct tree_opt_pass pass_free_cfg = +{ + NULL, /* name */ + NULL, /* gate */ + free_bb_for_insn, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + PROP_cfg, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Return RTX to emit after when we want to emit code on the entry of function. */ rtx entry_of_function (void) diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 9364832..2538442 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -98,6 +98,7 @@ The varpool data structure: #include "output.h" #include "intl.h" #include "tree-gimple.h" +#include "tree-dump.h" static void cgraph_node_remove_callers (struct cgraph_node *node); static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index d65a202..6ab04d4 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1190,6 +1190,16 @@ cgraph_preserve_function_body_p (tree decl) return false; } +static void +ipa_passes (void) +{ + cfun = NULL; + tree_register_cfg_hooks (); + bitmap_obstack_initialize (NULL); + execute_ipa_pass_list (all_ipa_passes); + bitmap_obstack_release (NULL); +} + /* Perform simple optimizations based on callgraph. */ void diff --git a/gcc/combine.c b/gcc/combine.c index 9fa68ba..9d2b28b 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -96,6 +96,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA /* Include output.h for dump_file. */ #include "output.h" #include "params.h" +#include "timevar.h" +#include "tree-pass.h" /* Number of attempts to combine instructions in this function. */ @@ -12514,3 +12516,50 @@ dump_combine_total_stats (FILE *file) "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n", total_attempts, total_merges, total_extras, total_successes); } + + +static bool +gate_handle_combine (void) +{ + return (optimize > 0); +} + +/* Try combining insns through substitution. */ +static void +rest_of_handle_combine (void) +{ + int rebuild_jump_labels_after_combine + = combine_instructions (get_insns (), max_reg_num ()); + + /* Combining insns may have turned an indirect jump into a + direct jump. Rebuild the JUMP_LABEL fields of jumping + instructions. */ + if (rebuild_jump_labels_after_combine) + { + timevar_push (TV_JUMP); + rebuild_jump_labels (get_insns ()); + timevar_pop (TV_JUMP); + + delete_dead_jumptables (); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); + } +} + +struct tree_opt_pass pass_combine = +{ + "combine", /* name */ + gate_handle_combine, /* gate */ + rest_of_handle_combine, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_COMBINE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'c' /* letter */ +}; + diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3595594..0140cde 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2005-07-05 Paolo Bonzini <bonzini@gnu.org> + + * Makefile.in (class.o, decl2.o): Adjust dependencies. + * class.c: Include tree-dump.h. + * decl2.c: Include tree-dump.h. + 2005-07-02 Gabriel Dos Reis <gdr@integrable-solutions.net> * dump.c: Use dump_string_field. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index a308375..c3649e1 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -244,7 +244,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h \ debug.h gt-cp-decl.h timevar.h $(TREE_FLOW_H) cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h $(EXPR_H) \ output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h \ - c-pragma.h + c-pragma.h $(TREE_DUMP_H) intl.h cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) $(TREE_H) $(CXX_TREE_H) c-common.h toplev.h langhooks.h \ $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h $(CXX_PRETTY_PRINT_H) \ @@ -254,7 +254,7 @@ cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h \ cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) \ toplev.h diagnostic.h convert.h c-common.h cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \ - $(TARGET_H) convert.h $(CGRAPH_H) + $(TARGET_H) convert.h $(CGRAPH_H) $(TREE_DUMP_H) cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \ $(EXPR_H) diagnostic.h intl.h gt-cp-call.h convert.h target.h cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h \ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4af7412..a226d28 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -36,6 +36,7 @@ Boston, MA 02110-1301, USA. */ #include "target.h" #include "convert.h" #include "cgraph.h" +#include "tree-dump.h" /* The number of nested classes being processed. If we are not in the scope of any class, this is zero. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 2abf30c..cb08ee5 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -49,6 +49,7 @@ Boston, MA 02110-1301, USA. */ #include "cgraph.h" #include "tree-inline.h" #include "c-pragma.h" +#include "tree-dump.h" #include "intl.h" extern cpp_reader *parse_in; @@ -43,6 +43,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "target.h" #include "params.h" #include "rtlhooks-def.h" +#include "tree-pass.h" /* The basic idea of common subexpression elimination is to go through the code, keeping a record of expressions that would @@ -7741,3 +7742,119 @@ cse_condition_code_reg (void) } } } + + +/* Perform common subexpression elimination. Nonzero value from + `cse_main' means that jumps were simplified and some code may now + be unreachable, so do jump optimization again. */ +static bool +gate_handle_cse (void) +{ + return optimize > 0; +} + +static void +rest_of_handle_cse (void) +{ + int tem; + + if (dump_file) + dump_flow_info (dump_file); + + reg_scan (get_insns (), max_reg_num ()); + + tem = cse_main (get_insns (), max_reg_num (), dump_file); + if (tem) + rebuild_jump_labels (get_insns ()); + if (purge_all_dead_edges ()) + delete_unreachable_blocks (); + + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + + /* If we are not running more CSE passes, then we are no longer + expecting CSE to be run. But always rerun it in a cheap mode. */ + cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse; + + if (tem) + delete_dead_jumptables (); + + if (tem || optimize > 1) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); +} + +struct tree_opt_pass pass_cse = +{ + "cse1", /* name */ + gate_handle_cse, /* gate */ + rest_of_handle_cse, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_CSE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 's' /* letter */ +}; + + +static bool +gate_handle_cse2 (void) +{ + return optimize > 0 && flag_rerun_cse_after_loop; +} + +/* Run second CSE pass after loop optimizations. */ +static void +rest_of_handle_cse2 (void) +{ + int tem; + + if (dump_file) + dump_flow_info (dump_file); + + tem = cse_main (get_insns (), max_reg_num (), dump_file); + + /* Run a pass to eliminate duplicated assignments to condition code + registers. We have to run this after bypass_jumps, because it + makes it harder for that pass to determine whether a jump can be + bypassed safely. */ + cse_condition_code_reg (); + + purge_all_dead_edges (); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + + if (tem) + { + timevar_push (TV_JUMP); + rebuild_jump_labels (get_insns ()); + delete_dead_jumptables (); + cleanup_cfg (CLEANUP_EXPENSIVE); + timevar_pop (TV_JUMP); + } + reg_scan (get_insns (), max_reg_num ()); + cse_not_expected = 1; +} + + +struct tree_opt_pass pass_cse2 = +{ + "cse2", /* name */ + gate_handle_cse2, /* gate */ + rest_of_handle_cse2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_CSE2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 't' /* letter */ +}; + diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e9d3213..351c70b 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -55,6 +55,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "ggc.h" #include "debug.h" #include "langhooks.h" +#include "tree-pass.h" /* Commonly used modes. */ @@ -2135,6 +2136,24 @@ unshare_all_rtl (void) unshare_all_rtl_1 (current_function_decl, get_insns ()); } +struct tree_opt_pass pass_unshare_all_rtl = +{ + NULL, /* name */ + NULL, /* gate */ + unshare_all_rtl, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + /* Check that ORIG is not marked when it should not be and mark ORIG as in use, Recursively does the same for subexpressions. */ @@ -3705,6 +3724,23 @@ remove_unnecessary_notes (void) gcc_assert (!eh_stack); } +struct tree_opt_pass pass_remove_unnecessary_notes = +{ + NULL, /* name */ + NULL, /* gate */ + remove_unnecessary_notes, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Emit insn(s) of given code and pattern at a specified place within the doubly-linked list. diff --git a/gcc/except.c b/gcc/except.c index 1d7bcb6..4578ae9 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -75,6 +75,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "langhooks.h" #include "cgraph.h" #include "diagnostic.h" +#include "tree-pass.h" +#include "timevar.h" /* Provide defaults for stuff that may not be defined when using sjlj exceptions. */ @@ -2711,6 +2713,23 @@ set_nothrow_function_flags (void) } } +struct tree_opt_pass pass_set_nothrow_function_flags = +{ + NULL, /* name */ + NULL, /* gate */ + set_nothrow_function_flags, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Various hooks for unwind library. */ @@ -3220,6 +3239,23 @@ convert_to_eh_region_ranges (void) htab_delete (ar_hash); } +struct tree_opt_pass pass_convert_to_eh_region_ranges = +{ + NULL, /* name */ + NULL, /* gate */ + convert_to_eh_region_ranges, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + static void push_uleb128 (varray_type *data_area, unsigned int value) @@ -3768,7 +3804,6 @@ verify_eh_tree (struct function *fun) } } - /* Initialize unwind_resume_libfunc. */ void @@ -3780,4 +3815,37 @@ default_init_unwind_resume_libfunc (void) : "_Unwind_Resume"); } + +static bool +gate_handle_eh (void) +{ + return doing_eh (0); +} + +/* Complete generation of exception handling code. */ +static void +rest_of_handle_eh (void) +{ + cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL); + finish_eh_generation (); + cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL); +} + +struct tree_opt_pass pass_rtl_eh = +{ + "eh", /* name */ + gate_handle_eh, /* gate */ + rest_of_handle_eh, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_JUMP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'h' /* letter */ +}; + #include "gt-except.h" diff --git a/gcc/final.c b/gcc/final.c index 6d99a92..18c53b7 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -72,6 +72,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "debug.h" #include "expr.h" #include "cfglayout.h" +#include "tree-pass.h" +#include "timevar.h" +#include "cgraph.h" +#include "coverage.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -735,6 +739,24 @@ compute_alignments (void) LABEL_TO_MAX_SKIP (label) = max_skip; } } + +struct tree_opt_pass pass_compute_alignments = +{ + NULL, /* name */ + NULL, /* gate */ + compute_alignments, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Make a pass over all insns and compute their actual lengths by shortening any branches of variable length if possible. */ @@ -3862,3 +3884,186 @@ debug_free_queue (void) symbol_queue_size = 0; } } + +/* Turn the RTL into assembly. */ +static void +rest_of_handle_final (void) +{ + rtx x; + const char *fnname; + + /* Get the function's name, as described by its RTL. This may be + different from the DECL_NAME name used in the source file. */ + + x = DECL_RTL (current_function_decl); + gcc_assert (MEM_P (x)); + x = XEXP (x, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + fnname = XSTR (x, 0); + + assemble_start_function (current_function_decl, fnname); + final_start_function (get_insns (), asm_out_file, optimize); + final (get_insns (), asm_out_file, optimize); + final_end_function (); + +#ifdef TARGET_UNWIND_INFO + /* ??? The IA-64 ".handlerdata" directive must be issued before + the ".endp" directive that closes the procedure descriptor. */ + output_function_exception_table (); +#endif + + assemble_end_function (current_function_decl, fnname); + +#ifndef TARGET_UNWIND_INFO + /* Otherwise, it feels unclean to switch sections in the middle. */ + output_function_exception_table (); +#endif + + user_defined_section_attribute = false; + + if (! quiet_flag) + fflush (asm_out_file); + + /* Release all memory allocated by flow. */ + free_basic_block_vars (); + + /* Write DBX symbols if requested. */ + + /* Note that for those inline functions where we don't initially + know for certain that we will be generating an out-of-line copy, + the first invocation of this routine (rest_of_compilation) will + skip over this code by doing a `goto exit_rest_of_compilation;'. + Later on, wrapup_global_declarations will (indirectly) call + rest_of_compilation again for those inline functions that need + to have out-of-line copies generated. During that call, we + *will* be routed past here. */ + + timevar_push (TV_SYMOUT); + (*debug_hooks->function_decl) (current_function_decl); + timevar_pop (TV_SYMOUT); +} + +struct tree_opt_pass pass_final = +{ + NULL, /* name */ + NULL, /* gate */ + rest_of_handle_final, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FINAL, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_ggc_collect, /* todo_flags_finish */ + 0 /* letter */ +}; + + +static void +rest_of_handle_shorten_branches (void) +{ + /* Shorten branches. */ + shorten_branches (get_insns ()); +} + +struct tree_opt_pass pass_shorten_branches = +{ + NULL, /* name */ + NULL, /* gate */ + rest_of_handle_shorten_branches, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FINAL, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + +static void +rest_of_clean_state (void) +{ + rtx insn, next; + + /* It is very important to decompose the RTL instruction chain here: + debug information keeps pointing into CODE_LABEL insns inside the function + body. If these remain pointing to the other insns, we end up preserving + whole RTL chain and attached detailed debug info in memory. */ + for (insn = get_insns (); insn; insn = next) + { + next = NEXT_INSN (insn); + NEXT_INSN (insn) = NULL; + PREV_INSN (insn) = NULL; + } + + /* In case the function was not output, + don't leave any temporary anonymous types + queued up for sdb output. */ +#ifdef SDB_DEBUGGING_INFO + if (write_symbols == SDB_DEBUG) + sdbout_types (NULL_TREE); +#endif + + reload_completed = 0; + epilogue_completed = 0; + flow2_completed = 0; + no_new_pseudos = 0; + + /* Clear out the insn_length contents now that they are no + longer valid. */ + init_insn_lengths (); + + /* Show no temporary slots allocated. */ + init_temp_slots (); + + free_basic_block_vars (); + free_bb_for_insn (); + + + if (targetm.binds_local_p (current_function_decl)) + { + int pref = cfun->preferred_stack_boundary; + if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary) + pref = cfun->stack_alignment_needed; + cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary + = pref; + } + + /* Make sure volatile mem refs aren't considered valid operands for + arithmetic insns. We must call this here if this is a nested inline + function, since the above code leaves us in the init_recog state, + and the function context push/pop code does not save/restore volatile_ok. + + ??? Maybe it isn't necessary for expand_start_function to call this + anymore if we do it here? */ + + init_recog_no_volatile (); + + /* We're done with this function. Free up memory if we can. */ + free_after_parsing (cfun); + free_after_compilation (cfun); +} + +struct tree_opt_pass pass_clean_state = +{ + NULL, /* name */ + NULL, /* gate */ + rest_of_clean_state, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FINAL, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + PROP_rtl, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + @@ -140,6 +140,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "obstack.h" #include "splay-tree.h" +#include "tree-pass.h" #ifndef HAVE_epilogue #define HAVE_epilogue 0 @@ -4357,6 +4358,23 @@ recompute_reg_usage (void) update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES); } +struct tree_opt_pass pass_recompute_reg_usage = +{ + NULL, /* name */ + NULL, /* gate */ + recompute_reg_usage, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Optionally removes all the REG_DEAD and REG_UNUSED notes from a set of blocks. If BLOCKS is NULL, assume the universal set. Returns a count of the number of registers that died. */ @@ -4504,3 +4522,131 @@ reg_set_to_hard_reg_set (HARD_REG_SET *to, bitmap from) SET_HARD_REG_BIT (*to, i); } } + + +static bool +gate_remove_death_notes (void) +{ + return flag_profile_values; +} + +static void +rest_of_handle_remove_death_notes (void) +{ + count_or_remove_death_notes (NULL, 1); +} + +struct tree_opt_pass pass_remove_death_notes = +{ + NULL, /* name */ + gate_remove_death_notes, /* gate */ + rest_of_handle_remove_death_notes, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + +/* Perform life analysis. */ +static void +rest_of_handle_life (void) +{ + regclass_init (); + + life_analysis (dump_file, PROP_FINAL); + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS + | (flag_thread_jumps ? CLEANUP_THREADING : 0)); + + if (extra_warnings) + { + setjmp_vars_warning (DECL_INITIAL (current_function_decl)); + setjmp_args_warning (); + } + + if (optimize) + { + if (initialize_uninitialized_subregs ()) + { + /* Insns were inserted, and possibly pseudos created, so + things might look a bit different. */ + allocate_reg_life_data (); + update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, + PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); + } + } + + no_new_pseudos = 1; +} + +struct tree_opt_pass pass_life = +{ + "life", /* name */ + NULL, /* gate */ + rest_of_handle_life, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FLOW, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_verify_flow, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'f' /* letter */ +}; + +static void +rest_of_handle_flow2 (void) +{ + /* Re-create the death notes which were deleted during reload. */ +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif + + /* If optimizing, then go ahead and split insns now. */ +#ifndef STACK_REGS + if (optimize > 0) +#endif + split_all_insns (0); + + if (flag_branch_target_load_optimize) + branch_target_load_optimize (epilogue_completed); + + if (optimize) + cleanup_cfg (CLEANUP_EXPENSIVE); + + /* On some machines, the prologue and epilogue code, or parts thereof, + can be represented as RTL. Doing so lets us schedule insns between + it and the rest of the code and also allows delayed branch + scheduling to operate in the epilogue. */ + thread_prologue_and_epilogue_insns (get_insns ()); + epilogue_completed = 1; + flow2_completed = 1; +} + +struct tree_opt_pass pass_flow2 = +{ + "flow2", /* name */ + NULL, /* gate */ + rest_of_handle_flow2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_FLOW2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + TODO_verify_flow, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'w' /* letter */ +}; + diff --git a/gcc/function.c b/gcc/function.c index 92415cc..ae8f7fd 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -61,9 +61,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "target.h" #include "cfglayout.h" #include "tree-gimple.h" +#include "tree-pass.h" #include "predict.h" - #ifndef LOCAL_ALIGNMENT #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT #endif @@ -1662,6 +1662,24 @@ instantiate_virtual_regs (void) frame_pointer_rtx. */ virtuals_instantiated = 1; } + +struct tree_opt_pass pass_instantiate_virtual_regs = +{ + NULL, /* name */ + NULL, /* gate */ + instantiate_virtual_regs, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Return 1 if EXP is an aggregate type (or a value with aggregate type). This means a type for which function calls must pass an address to the @@ -3884,6 +3902,24 @@ init_function_for_compilation (void) gcc_assert (VEC_length (int, sibcall_epilogue) == 0); } +struct tree_opt_pass pass_init_function = +{ + NULL, /* name */ + NULL, /* gate */ + init_function_for_compilation, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + void expand_main_function (void) { @@ -5499,5 +5535,33 @@ current_function_name (void) { return lang_hooks.decl_printable_name (cfun->decl, 2); } + + +static void +rest_of_handle_check_leaf_regs (void) +{ +#ifdef LEAF_REGISTERS + current_function_uses_only_leaf_regs + = optimize > 0 && only_leaf_regs_used () && leaf_function_p (); +#endif +} + +struct tree_opt_pass pass_leaf_regs = +{ + NULL, /* name */ + NULL, /* gate */ + rest_of_handle_check_leaf_regs, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + #include "gt-function.h" @@ -169,6 +169,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "intl.h" #include "obstack.h" #include "timevar.h" +#include "tree-pass.h" /* Propagate flow information through back edges and thus enable PRE's moving loop invariant calculations out of loops. @@ -6558,5 +6559,113 @@ is_too_expensive (const char *pass) return false; } + +static bool +gate_handle_jump_bypass (void) +{ + return optimize > 0 && flag_gcse; +} + +/* Perform jump bypassing and control flow optimizations. */ +static void +rest_of_handle_jump_bypass (void) +{ + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); + + if (bypass_jumps (dump_file)) + { + rebuild_jump_labels (get_insns ()); + cleanup_cfg (CLEANUP_EXPENSIVE); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + } +} + +struct tree_opt_pass pass_jump_bypass = +{ + "bypass", /* name */ + gate_handle_jump_bypass, /* gate */ + rest_of_handle_jump_bypass, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_BYPASS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect | TODO_verify_flow, /* todo_flags_finish */ + 'G' /* letter */ +}; + + +static bool +gate_handle_gcse (void) +{ + return optimize > 0 && flag_gcse; +} + + +static void +rest_of_handle_gcse (void) +{ + int save_csb, save_cfj; + int tem2 = 0, tem; + + tem = gcse_main (get_insns (), dump_file); + rebuild_jump_labels (get_insns ()); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + + save_csb = flag_cse_skip_blocks; + save_cfj = flag_cse_follow_jumps; + flag_cse_skip_blocks = flag_cse_follow_jumps = 0; + + /* If -fexpensive-optimizations, re-run CSE to clean up things done + by gcse. */ + if (flag_expensive_optimizations) + { + timevar_push (TV_CSE); + reg_scan (get_insns (), max_reg_num ()); + tem2 = cse_main (get_insns (), max_reg_num (), dump_file); + purge_all_dead_edges (); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + timevar_pop (TV_CSE); + cse_not_expected = !flag_rerun_cse_after_loop; + } + + /* If gcse or cse altered any jumps, rerun jump optimizations to clean + things up. */ + if (tem || tem2) + { + timevar_push (TV_JUMP); + rebuild_jump_labels (get_insns ()); + delete_dead_jumptables (); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); + timevar_pop (TV_JUMP); + } + + flag_cse_skip_blocks = save_csb; + flag_cse_follow_jumps = save_cfj; +} + +struct tree_opt_pass pass_gcse = +{ + "gcse1", /* name */ + gate_handle_gcse, /* gate */ + rest_of_handle_gcse, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_GCSE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */ + 'G' /* letter */ +}; + #include "gt-gcse.h" diff --git a/gcc/global.c b/gcc/global.c index bdd3386..13b8173 100644 --- a/gcc/global.c +++ b/gcc/global.c @@ -36,6 +36,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "reload.h" #include "output.h" #include "toplev.h" +#include "tree-pass.h" +#include "timevar.h" /* This pass of the compiler performs global register allocation. It assigns hard register numbers to all the pseudo registers @@ -2474,3 +2476,50 @@ make_accurate_live_analysis (void) } free_bb_info (); } +/* Run old register allocator. Return TRUE if we must exit + rest_of_compilation upon return. */ +static void +rest_of_handle_global_alloc (void) +{ + bool failure; + + /* If optimizing, allocate remaining pseudo-regs. Do the reload + pass fixing up any insns that are invalid. */ + + if (optimize) + failure = global_alloc (dump_file); + else + { + build_insn_chain (get_insns ()); + failure = reload (get_insns (), 0); + } + + if (dump_enabled_p (pass_global_alloc.static_pass_number)) + { + timevar_push (TV_DUMP); + dump_global_regs (dump_file); + timevar_pop (TV_DUMP); + } + + gcc_assert (reload_completed || failure); + reload_completed = !failure; +} + +struct tree_opt_pass pass_global_alloc = +{ + "greg", /* name */ + NULL, /* gate */ + rest_of_handle_global_alloc, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_GLOBAL_ALLOC, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'g' /* letter */ +}; + diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 750ffa9..d9f18bc 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -41,6 +41,8 @@ #include "tm_p.h" #include "cfgloop.h" #include "target.h" +#include "timevar.h" +#include "tree-pass.h" #ifndef HAVE_conditional_execution @@ -3579,3 +3581,120 @@ if_convert (int x_life_data_ok) verify_flow_info (); #endif } + +static bool +gate_handle_if_conversion (void) +{ + return (optimize > 0); +} + +/* If-conversion and CFG cleanup. */ +static void +rest_of_handle_if_conversion (void) +{ + if (flag_if_conversion) + { + if (dump_file) + dump_flow_info (dump_file); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); + if_convert (0); + } + + timevar_push (TV_JUMP); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); + timevar_pop (TV_JUMP); +} + +struct tree_opt_pass pass_rtl_ifcvt = +{ + "ce1", /* name */ + gate_handle_if_conversion, /* gate */ + rest_of_handle_if_conversion, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IFCVT, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'C' /* letter */ +}; + +static bool +gate_handle_if_after_combine (void) +{ + return (optimize > 0 && flag_if_conversion); +} + + +/* Rerun if-conversion, as combine may have simplified things enough + to now meet sequence length restrictions. */ +static void +rest_of_handle_if_after_combine (void) +{ + no_new_pseudos = 0; + if_convert (1); + no_new_pseudos = 1; +} + +struct tree_opt_pass pass_if_after_combine = +{ + "ce2", /* name */ + gate_handle_if_after_combine, /* gate */ + rest_of_handle_if_after_combine, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IFCVT, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'C' /* letter */ +}; + + +static bool +gate_handle_if_after_reload (void) +{ + return (optimize > 0); +} + +static void +rest_of_handle_if_after_reload (void) +{ + /* Last attempt to optimize CFG, as scheduling, peepholing and insn + splitting possibly introduced more crossjumping opportunities. */ + cleanup_cfg (CLEANUP_EXPENSIVE + | CLEANUP_UPDATE_LIFE + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); + if (flag_if_conversion2) + if_convert (1); +} + + +struct tree_opt_pass pass_if_after_reload = +{ + "ce3", /* name */ + gate_handle_if_after_reload, /* gate */ + rest_of_handle_if_after_reload, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_IFCVT2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'E' /* letter */ +}; + + diff --git a/gcc/integrate.c b/gcc/integrate.c index 28da115..31ff9c7 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -45,6 +45,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "ggc.h" #include "target.h" #include "langhooks.h" +#include "tree-pass.h" /* Round to the next highest integer that meets the alignment. */ #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) @@ -371,6 +372,23 @@ emit_initial_value_sets (void) emit_insn_after (seq, entry_of_function ()); } +struct tree_opt_pass pass_initial_value_sets = +{ + NULL, /* name */ + NULL, /* gate */ + emit_initial_value_sets, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* If the backend knows where to allocate pseudos for hard register initial values, register these allocations now. */ void diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 18edb05..83861f1 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,8 @@ +2005-07-05 Paolo Bonzini <bonzini@gnu.org> + + * Makefile.in (parse.o): Adjust dependencies. + * parse.y: Include tree-dump.h. + 2005-07-02 Joseph S. Myers <joseph@codesourcery.com> * class.c, decl.c, expr.c: Use '+' flag instead of %J. Use 'q' diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index 41fdec7..ddeb12d 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -365,7 +365,8 @@ java/parse-scan.o: java/parse-scan.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) toplev.h $(JAVA_LEX_C) java/parse.h java/lex.h input.h java/parse.o: java/parse.c java/jcf-reader.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) function.h $(JAVA_TREE_H) $(JAVA_LEX_C) java/parse.h \ - java/lex.h input.h $(GGC_H) debug.h gt-java-parse.h gtype-java.h target.h + java/lex.h input.h $(GGC_H) debug.h gt-java-parse.h gtype-java.h target.h \ + $(TREE_DUMP_H) # jcf-io.o needs $(ZLIBINC) added to cflags. java/jcf-io.o: java/jcf-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ diff --git a/gcc/java/parse.y b/gcc/java/parse.y index b54917c..cda54c1 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -72,6 +72,7 @@ definitions and other extensions. */ #include "ggc.h" #include "debug.h" #include "tree-inline.h" +#include "tree-dump.h" #include "cgraph.h" #include "target.h" @@ -56,6 +56,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "reload.h" #include "predict.h" #include "timevar.h" +#include "tree-pass.h" /* Optimize jump y; x: ... y: jumpif... x? Don't know if it is worth bothering with. */ @@ -120,8 +121,25 @@ cleanup_barriers (void) } } +struct tree_opt_pass pass_cleanup_barriers = +{ + NULL, /* name */ + NULL, /* gate */ + cleanup_barriers, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + void -purge_line_number_notes (rtx f) +purge_line_number_notes (void) { rtx last_note = 0; rtx insn; @@ -130,7 +148,7 @@ purge_line_number_notes (rtx f) extraneous. There should be some indication where that line belonged, even if it became empty. */ - for (insn = f; insn; insn = NEXT_INSN (insn)) + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (NOTE_P (insn)) { if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) @@ -157,6 +175,24 @@ purge_line_number_notes (rtx f) } } } + +struct tree_opt_pass pass_purge_lineno_notes = +{ + NULL, /* name */ + NULL, /* gate */ + purge_line_number_notes, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Initialize LABEL_NUSES and JUMP_LABEL fields. Delete any REG_LABEL notes whose labels don't occur in the insn any more. Returns the diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index a5d8c41..cd26174 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -78,6 +78,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "integrate.h" #include "reload.h" #include "ggc.h" +#include "timevar.h" +#include "tree-pass.h" /* Next quantity number available for allocation. */ @@ -2496,3 +2498,69 @@ dump_local_alloc (FILE *file) if (reg_renumber[i] != -1) fprintf (file, ";; Register %d in %d.\n", i, reg_renumber[i]); } + +/* Run old register allocator. Return TRUE if we must exit + rest_of_compilation upon return. */ +static void +rest_of_handle_local_alloc (void) +{ + int rebuild_notes; + + /* Determine if the current function is a leaf before running reload + since this can impact optimizations done by the prologue and + epilogue thus changing register elimination offsets. */ + current_function_is_leaf = leaf_function_p (); + + /* Allocate the reg_renumber array. */ + allocate_reg_info (max_regno, FALSE, TRUE); + + /* And the reg_equiv_memory_loc array. */ + VARRAY_GROW (reg_equiv_memory_loc_varray, max_regno); + reg_equiv_memory_loc = &VARRAY_RTX (reg_equiv_memory_loc_varray, 0); + + allocate_initial_values (reg_equiv_memory_loc); + + regclass (get_insns (), max_reg_num (), dump_file); + rebuild_notes = local_alloc (); + + /* Local allocation may have turned an indirect jump into a direct + jump. If so, we must rebuild the JUMP_LABEL fields of jumping + instructions. */ + if (rebuild_notes) + { + timevar_push (TV_JUMP); + + rebuild_jump_labels (get_insns ()); + purge_all_dead_edges (); + delete_unreachable_blocks (); + + timevar_pop (TV_JUMP); + } + + if (dump_enabled_p (pass_local_alloc.static_pass_number)) + { + timevar_push (TV_DUMP); + dump_flow_info (dump_file); + dump_local_alloc (dump_file); + timevar_pop (TV_DUMP); + } +} + +struct tree_opt_pass pass_local_alloc = +{ + "lreg", /* name */ + NULL, /* gate */ + rest_of_handle_local_alloc, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_LOCAL_ALLOC, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'l' /* letter */ +}; + diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 4702789..375b2bf 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -28,6 +28,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "basic-block.h" #include "cfgloop.h" #include "cfglayout.h" +#include "tree-pass.h" +#include "timevar.h" +#include "flags.h" /* Initialize loop optimizer. */ @@ -116,3 +119,88 @@ loop_optimizer_finalize (struct loops *loops, FILE *dumpfile) verify_flow_info (); #endif } + +static bool +gate_handle_loop2 (void) +{ + return (optimize > 0 && flag_loop_optimize2 + && (flag_move_loop_invariants + || flag_unswitch_loops + || flag_peel_loops + || flag_unroll_loops + || flag_branch_on_count_reg)); +} + +/* Perform loop optimizations. It might be better to do them a bit + sooner, but we want the profile feedback to work more + efficiently. */ +static void +rest_of_handle_loop2 (void) +{ + struct loops *loops; + basic_block bb; + + if (dump_file) + dump_flow_info (dump_file); + + /* Initialize structures for layout changes. */ + cfg_layout_initialize (0); + + loops = loop_optimizer_init (dump_file); + + if (loops) + { + /* The optimizations: */ + if (flag_move_loop_invariants) + move_loop_invariants (loops); + + if (flag_unswitch_loops) + unswitch_loops (loops); + + if (flag_peel_loops || flag_unroll_loops) + unroll_and_peel_loops (loops, + (flag_peel_loops ? UAP_PEEL : 0) | + (flag_unroll_loops ? UAP_UNROLL : 0) | + (flag_unroll_all_loops ? UAP_UNROLL_ALL : 0)); + +#ifdef HAVE_doloop_end + if (flag_branch_on_count_reg && HAVE_doloop_end) + doloop_optimize_loops (loops); +#endif /* HAVE_doloop_end */ + + loop_optimizer_finalize (loops, dump_file); + } + + free_dominance_info (CDI_DOMINATORS); + + /* Finalize layout changes. */ + FOR_EACH_BB (bb) + if (bb->next_bb != EXIT_BLOCK_PTR) + bb->aux = bb->next_bb; + cfg_layout_finalize (); + + cleanup_cfg (CLEANUP_EXPENSIVE); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + reg_scan (get_insns (), max_reg_num ()); + if (dump_file) + dump_flow_info (dump_file); +} + +struct tree_opt_pass pass_loop2 = +{ + "loop2", /* name */ + gate_handle_loop2, /* gate */ + rest_of_handle_loop2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_LOOP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'L' /* letter */ +}; + @@ -66,6 +66,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "optabs.h" #include "cfgloop.h" #include "ggc.h" +#include "timevar.h" +#include "tree-pass.h" /* Get the loop info pointer of a loop. */ #define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux) @@ -11807,3 +11809,66 @@ debug_loops (const struct loops *loops) { flow_loops_dump (loops, stderr, loop_dump_aux, 1); } + +static bool +gate_handle_loop_optimize (void) +{ + return (optimize > 0 && flag_loop_optimize); +} + +/* Move constant computations out of loops. */ +static void +rest_of_handle_loop_optimize (void) +{ + int do_prefetch; + + /* CFG is no longer maintained up-to-date. */ + free_bb_for_insn (); + profile_status = PROFILE_ABSENT; + + do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; + + if (flag_rerun_loop_opt) + { + cleanup_barriers (); + + /* We only want to perform unrolling once. */ + loop_optimize (get_insns (), dump_file, 0); + + /* The first call to loop_optimize makes some instructions + trivially dead. We delete those instructions now in the + hope that doing so will make the heuristics in loop work + better and possibly speed up compilation. */ + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + + /* The regscan pass is currently necessary as the alias + analysis code depends on this information. */ + reg_scan (get_insns (), max_reg_num ()); + } + cleanup_barriers (); + loop_optimize (get_insns (), dump_file, do_prefetch); + + /* Loop can create trivially dead instructions. */ + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + find_basic_blocks (get_insns ()); +} + +struct tree_opt_pass pass_loop_optimize = +{ + "old-loop", /* name */ + gate_handle_loop_optimize, /* gate */ + rest_of_handle_loop_optimize, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_LOOP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'L' /* letter */ +}; + + diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c index 62e7112..9e8ad62 100644 --- a/gcc/mode-switching.c +++ b/gcc/mode-switching.c @@ -34,6 +34,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "output.h" #include "tm_p.h" #include "function.h" +#include "tree-pass.h" +#include "timevar.h" /* We want target macros for the mode switching code to be able to refer to instruction attribute values. */ @@ -708,4 +710,43 @@ optimize_mode_switching (FILE *file) return 1; } + #endif /* OPTIMIZE_MODE_SWITCHING */ + +static bool +gate_mode_switching (void) +{ +#ifdef OPTIMIZE_MODE_SWITCHING + return true; +#else + return false; +#endif +} + +static void +rest_of_handle_mode_switching (void) +{ +#ifdef OPTIMIZE_MODE_SWITCHING + no_new_pseudos = 0; + optimize_mode_switching (NULL); + no_new_pseudos = 1; +#endif /* OPTIMIZE_MODE_SWITCHING */ +} + + +struct tree_opt_pass pass_mode_switching = +{ + NULL, /* name */ + gate_mode_switching, /* gate */ + rest_of_handle_mode_switching, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_MODE_SWITCH, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index b436811..4b3b900 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -47,6 +47,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "gcov-io.h" #include "df.h" #include "ddg.h" +#include "timevar.h" +#include "tree-pass.h" #ifdef INSN_SCHEDULING @@ -2517,5 +2519,67 @@ ps_unschedule_node (partial_schedule_ptr ps, ddg_node_ptr n) return remove_node_from_ps (ps, ps_i); } -#endif /* INSN_SCHEDULING*/ +#endif /* INSN_SCHEDULING */ + +static bool +gate_handle_sms (void) +{ + return (optimize > 0 && flag_modulo_sched); +} + + +/* Run instruction scheduler. */ +/* Perform SMS module scheduling. */ +static void +rest_of_handle_sms (void) +{ +#ifdef INSN_SCHEDULING + basic_block bb; + sbitmap blocks; + + /* We want to be able to create new pseudos. */ + no_new_pseudos = 0; + /* Collect loop information to be used in SMS. */ + cfg_layout_initialize (CLEANUP_UPDATE_LIFE); + sms_schedule (dump_file); + + /* Update the life information, because we add pseudos. */ + max_regno = max_reg_num (); + allocate_reg_info (max_regno, FALSE, FALSE); + blocks = sbitmap_alloc (last_basic_block); + sbitmap_ones (blocks); + update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES, + (PROP_DEATH_NOTES + | PROP_REG_INFO + | PROP_KILL_DEAD_CODE + | PROP_SCAN_DEAD_CODE)); + + no_new_pseudos = 1; + + /* Finalize layout changes. */ + FOR_EACH_BB (bb) + if (bb->next_bb != EXIT_BLOCK_PTR) + bb->aux = bb->next_bb; + cfg_layout_finalize (); + free_dominance_info (CDI_DOMINATORS); +#endif /* INSN_SCHEDULING */ +} + +struct tree_opt_pass pass_sms = +{ + "sms", /* name */ + gate_handle_sms, /* gate */ + rest_of_handle_sms, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_SMS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'm' /* letter */ +}; @@ -38,6 +38,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tm_p.h" /* For OPTIMIZATION_OPTIONS. */ #include "insn-attr.h" /* For INSN_SCHEDULING. */ #include "target.h" +#include "tree-pass.h" /* Value of the -G xx switch, and whether it was passed or not. */ unsigned HOST_WIDE_INT g_switch_value; diff --git a/gcc/passes.c b/gcc/passes.c index a5670e2..67ffffb 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -78,6 +78,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "opts.h" #include "coverage.h" #include "value-prof.h" +#include "tree-inline.h" +#include "tree-flow.h" #include "tree-pass.h" #include "tree-dump.h" @@ -98,80 +100,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA declarations for e.g. AIX 4.x. */ #endif -#ifndef HAVE_conditional_execution -#define HAVE_conditional_execution 0 -#endif - -/* Format to use to print dumpfile index value */ -#ifndef DUMPFILE_FORMAT -#define DUMPFILE_FORMAT ".%02d." -#endif - -static int initializing_dump = 0; - -/* Routine to open a dump file. Return true if the dump file is enabled. */ - -static int -open_dump_file (enum tree_dump_index index, tree decl) -{ - if (! dump_enabled_p (index)) - return 0; - - timevar_push (TV_DUMP); - - gcc_assert (!dump_file && !dump_file_name); - - dump_file_name = get_dump_file_name (index); - initializing_dump = !dump_initialized_p (index); - dump_file = dump_begin (index, NULL); - - if (dump_file == NULL) - fatal_error ("can't open %s: %m", dump_file_name); - - if (decl) - fprintf (dump_file, "\n;; Function %s%s\n\n", - lang_hooks.decl_printable_name (decl, 2), - cfun->function_frequency == FUNCTION_FREQUENCY_HOT - ? " (hot)" - : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED - ? " (unlikely executed)" - : ""); +/* Global variables used to communicate with passes. */ +int dump_flags; +bool in_gimple_form; - timevar_pop (TV_DUMP); - return 1; -} - -/* Routine to close a dump file. */ - -static void -close_dump_file (enum tree_dump_index index, - void (*func) (FILE *, rtx), - rtx insns) -{ - if (! dump_file) - return; - - timevar_push (TV_DUMP); - if (insns - && graph_dump_format != no_graph) - { - /* If we've not initialized the files, do so now. */ - if (initializing_dump) - clean_graph_dump_file (dump_file_name); - - print_rtl_graph_with_bb (dump_file_name, insns); - } - - if (func && insns) - func (dump_file, insns); - - dump_end (index, dump_file); - free ((char *) dump_file_name); - - dump_file = NULL; - dump_file_name = NULL; - timevar_pop (TV_DUMP); -} /* This is called from various places for FUNCTION_DECL, VAR_DECL, and TYPE_DECL nodes. @@ -270,1539 +202,640 @@ rest_of_type_compilation (tree type, int toplev) timevar_pop (TV_SYMOUT); } -/* Turn the RTL into assembly. */ -static void -rest_of_handle_final (void) -{ - timevar_push (TV_FINAL); - { - rtx x; - const char *fnname; - - /* Get the function's name, as described by its RTL. This may be - different from the DECL_NAME name used in the source file. */ - - x = DECL_RTL (current_function_decl); - gcc_assert (MEM_P (x)); - x = XEXP (x, 0); - gcc_assert (GET_CODE (x) == SYMBOL_REF); - fnname = XSTR (x, 0); - - assemble_start_function (current_function_decl, fnname); - final_start_function (get_insns (), asm_out_file, optimize); - final (get_insns (), asm_out_file, optimize); - final_end_function (); - -#ifdef TARGET_UNWIND_INFO - /* ??? The IA-64 ".handlerdata" directive must be issued before - the ".endp" directive that closes the procedure descriptor. */ - output_function_exception_table (); -#endif - - assemble_end_function (current_function_decl, fnname); - -#ifndef TARGET_UNWIND_INFO - /* Otherwise, it feels unclean to switch sections in the middle. */ - output_function_exception_table (); -#endif - - user_defined_section_attribute = false; - - if (! quiet_flag) - fflush (asm_out_file); - - /* Release all memory allocated by flow. */ - free_basic_block_vars (); - } - - /* Write DBX symbols if requested. */ - - /* Note that for those inline functions where we don't initially - know for certain that we will be generating an out-of-line copy, - the first invocation of this routine (rest_of_compilation) will - skip over this code by doing a `goto exit_rest_of_compilation;'. - Later on, wrapup_global_declarations will (indirectly) call - rest_of_compilation again for those inline functions that need - to have out-of-line copies generated. During that call, we - *will* be routed past here. */ - - timevar_push (TV_SYMOUT); - (*debug_hooks->function_decl) (current_function_decl); - timevar_pop (TV_SYMOUT); - - ggc_collect (); - timevar_pop (TV_FINAL); -} + -#ifdef DELAY_SLOTS -/* Run delay slot optimization. */ -static void -rest_of_handle_delay_slots (void) +void +finish_optimization_passes (void) { - timevar_push (TV_DBR_SCHED); - open_dump_file (DFI_dbr, current_function_decl); - - dbr_schedule (get_insns (), dump_file); - - close_dump_file (DFI_dbr, print_rtl, get_insns ()); - - ggc_collect (); - - timevar_pop (TV_DBR_SCHED); -} -#endif + enum tree_dump_index i; + struct dump_file_info *dfi; + char *name; -#ifdef STACK_REGS -/* Convert register usage from flat register file usage to a stack - register file. */ -static void -rest_of_handle_stack_regs (void) -{ -#if defined (HAVE_ATTR_length) - /* If flow2 creates new instructions which need splitting - and scheduling after reload is not done, they might not be - split until final which doesn't allow splitting - if HAVE_ATTR_length. */ -#ifdef INSN_SCHEDULING - if (optimize && !flag_schedule_insns_after_reload) -#else - if (optimize) -#endif + timevar_push (TV_DUMP); + if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) { - timevar_push (TV_SHORTEN_BRANCH); - split_all_insns (1); - timevar_pop (TV_SHORTEN_BRANCH); + dump_file = dump_begin (pass_branch_prob.static_pass_number, NULL); + end_branch_prob (); + if (dump_file) + dump_end (pass_branch_prob.static_pass_number, dump_file); } -#endif - timevar_push (TV_REG_STACK); - open_dump_file (DFI_stack, current_function_decl); - - if (reg_to_stack (dump_file) && optimize) + if (optimize > 0) { - if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK - | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)) - && (flag_reorder_blocks || flag_reorder_blocks_and_partition)) + dump_file = dump_begin (pass_combine.static_pass_number, NULL); + if (dump_file) { - reorder_basic_blocks (0); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); + dump_combine_total_stats (dump_file); + dump_end (pass_combine.static_pass_number, dump_file); } } - close_dump_file (DFI_stack, print_rtl_with_bb, get_insns ()); - - ggc_collect (); - timevar_pop (TV_REG_STACK); -} -#endif - -/* Track the variables, i.e. compute where the variable is stored at each position in function. */ -static void -rest_of_handle_variable_tracking (void) -{ - timevar_push (TV_VAR_TRACKING); - open_dump_file (DFI_vartrack, current_function_decl); - - variable_tracking_main (); - - close_dump_file (DFI_vartrack, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_VAR_TRACKING); -} - -/* Machine dependent reorg pass. */ -static void -rest_of_handle_machine_reorg (void) -{ - timevar_push (TV_MACH_DEP); - open_dump_file (DFI_mach, current_function_decl); - - targetm.machine_dependent_reorg (); - - close_dump_file (DFI_mach, print_rtl, get_insns ()); + /* Do whatever is necessary to finish printing the graphs. */ + if (graph_dump_format != no_graph) + for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i) + if (dump_initialized_p (i) + && (dfi->flags & TDF_RTL) != 0 + && (name = get_dump_file_name (i)) != NULL) + { + finish_graph_dump_file (name); + free (name); + } - ggc_collect (); - timevar_pop (TV_MACH_DEP); + timevar_pop (TV_DUMP); } - -/* Run old register allocator. Return TRUE if we must exit - rest_of_compilation upon return. */ static bool -rest_of_handle_old_regalloc (void) +gate_rest_of_compilation (void) { - int failure; - int rebuild_notes; - - timevar_push (TV_LOCAL_ALLOC); - open_dump_file (DFI_lreg, current_function_decl); - - /* Allocate the reg_renumber array. */ - allocate_reg_info (max_regno, FALSE, TRUE); - - /* And the reg_equiv_memory_loc array. */ - VARRAY_GROW (reg_equiv_memory_loc_varray, max_regno); - reg_equiv_memory_loc = &VARRAY_RTX (reg_equiv_memory_loc_varray, 0); - - allocate_initial_values (reg_equiv_memory_loc); - - regclass (get_insns (), max_reg_num (), dump_file); - rebuild_notes = local_alloc (); - - timevar_pop (TV_LOCAL_ALLOC); - - /* Local allocation may have turned an indirect jump into a direct - jump. If so, we must rebuild the JUMP_LABEL fields of jumping - instructions. */ - if (rebuild_notes) - { - timevar_push (TV_JUMP); - - rebuild_jump_labels (get_insns ()); - purge_all_dead_edges (); - delete_unreachable_blocks (); - - timevar_pop (TV_JUMP); - } - - if (dump_enabled_p (DFI_lreg)) - { - timevar_push (TV_DUMP); - dump_flow_info (dump_file); - dump_local_alloc (dump_file); - timevar_pop (TV_DUMP); - } - - close_dump_file (DFI_lreg, print_rtl_with_bb, get_insns ()); - - ggc_collect (); - - timevar_push (TV_GLOBAL_ALLOC); - open_dump_file (DFI_greg, current_function_decl); - - /* If optimizing, allocate remaining pseudo-regs. Do the reload - pass fixing up any insns that are invalid. */ - - if (optimize) - failure = global_alloc (dump_file); - else - { - build_insn_chain (get_insns ()); - failure = reload (get_insns (), 0); - } - - if (dump_enabled_p (DFI_greg)) - { - timevar_push (TV_DUMP); - dump_global_regs (dump_file); - timevar_pop (TV_DUMP); - - close_dump_file (DFI_greg, print_rtl_with_bb, get_insns ()); - } - - ggc_collect (); - - timevar_pop (TV_GLOBAL_ALLOC); - - return failure; -} - -/* Run the regrename and cprop passes. */ -static void -rest_of_handle_regrename (void) -{ - timevar_push (TV_RENAME_REGISTERS); - open_dump_file (DFI_rnreg, current_function_decl); - - if (flag_rename_registers) - regrename_optimize (); - if (flag_cprop_registers) - copyprop_hardreg_forward (); - - close_dump_file (DFI_rnreg, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_RENAME_REGISTERS); -} - -/* Reorder basic blocks. */ -static void -rest_of_handle_reorder_blocks (void) -{ - bool changed; - unsigned int liveness_flags; - - open_dump_file (DFI_bbro, current_function_decl); - - /* Last attempt to optimize CFG, as scheduling, peepholing and insn - splitting possibly introduced more crossjumping opportunities. */ - liveness_flags = (!HAVE_conditional_execution ? CLEANUP_UPDATE_LIFE : 0); - changed = cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags); - - if (flag_sched2_use_traces && flag_schedule_insns_after_reload) - tracer (liveness_flags); - if (flag_reorder_blocks || flag_reorder_blocks_and_partition) - reorder_basic_blocks (liveness_flags); - if (flag_reorder_blocks || flag_reorder_blocks_and_partition - || (flag_sched2_use_traces && flag_schedule_insns_after_reload)) - changed |= cleanup_cfg (CLEANUP_EXPENSIVE | liveness_flags); - - /* On conditional execution targets we can not update the life cheaply, so - we deffer the updating to after both cleanups. This may lose some cases - but should not be terribly bad. */ - if (changed && HAVE_conditional_execution) - update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, - PROP_DEATH_NOTES); - close_dump_file (DFI_bbro, print_rtl_with_bb, get_insns ()); + /* Early return if there were errors. We can run afoul of our + consistency checks, and there's not really much point in fixing them. */ + return !(rtl_dump_and_exit || flag_syntax_only || errorcount || sorrycount); } -/* Partition hot and cold basic blocks. */ -static void -rest_of_handle_partition_blocks (void) +struct tree_opt_pass pass_rest_of_compilation = { - no_new_pseudos = 0; - partition_hot_cold_basic_blocks (); - allocate_reg_life_data (); - update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, - PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); - no_new_pseudos = 1; -} + NULL, /* name */ + gate_rest_of_compilation, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REST_OF_COMPILATION, /* tv_id */ + PROP_rtl, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_ggc_collect, /* todo_flags_finish */ + 0 /* letter */ +}; -#ifdef INSN_SCHEDULING -/* Run instruction scheduler. */ -/* Perform SMS module scheduling. */ -static void -rest_of_handle_sms (void) +static bool +gate_postreload (void) { - basic_block bb; - sbitmap blocks; - - timevar_push (TV_SMS); - open_dump_file (DFI_sms, current_function_decl); - - /* We want to be able to create new pseudos. */ - no_new_pseudos = 0; - /* Collect loop information to be used in SMS. */ - cfg_layout_initialize (CLEANUP_UPDATE_LIFE); - sms_schedule (dump_file); - close_dump_file (DFI_sms, print_rtl, get_insns ()); - - /* Update the life information, because we add pseudos. */ - max_regno = max_reg_num (); - allocate_reg_info (max_regno, FALSE, FALSE); - blocks = sbitmap_alloc (last_basic_block); - sbitmap_ones (blocks); - update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES, - (PROP_DEATH_NOTES - | PROP_REG_INFO - | PROP_KILL_DEAD_CODE - | PROP_SCAN_DEAD_CODE)); - - no_new_pseudos = 1; - - /* Finalize layout changes. */ - FOR_EACH_BB (bb) - if (bb->next_bb != EXIT_BLOCK_PTR) - bb->aux = bb->next_bb; - cfg_layout_finalize (); - free_dominance_info (CDI_DOMINATORS); - ggc_collect (); - timevar_pop (TV_SMS); + return reload_completed; } -/* Run instruction scheduler. */ -static void -rest_of_handle_sched (void) +struct tree_opt_pass pass_postreload = { - timevar_push (TV_SCHED); - - /* Print function header into sched dump now - because doing the sched analysis makes some of the dump. */ - open_dump_file (DFI_sched, current_function_decl); + NULL, /* name */ + gate_postreload, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + PROP_rtl, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_ggc_collect, /* todo_flags_finish */ + 0 /* letter */ +}; - /* Do control and data sched analysis, - and write some of the results to dump file. */ - schedule_insns (dump_file); - close_dump_file (DFI_sched, print_rtl_with_bb, get_insns ()); +/* The root of the compilation pass tree, once constructed. */ +struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; - ggc_collect (); - timevar_pop (TV_SCHED); -} +/* Iterate over the pass tree allocating dump file numbers. We want + to do this depth first, and independent of whether the pass is + enabled or not. */ -/* Run second scheduling pass after reload. */ static void -rest_of_handle_sched2 (void) +register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n) { - timevar_push (TV_SCHED2); - open_dump_file (DFI_sched2, current_function_decl); + char *dot_name, *flag_name, *glob_name; + char num[10]; - /* Do control and data sched analysis again, - and write some more of the results to dump file. */ + /* See below in next_pass_1. */ + num[0] = '\0'; + if (pass->static_pass_number != -1) + sprintf (num, "%d", ((int) pass->static_pass_number < 0 + ? 1 : pass->static_pass_number)); - split_all_insns (1); - - if (flag_sched2_use_superblocks || flag_sched2_use_traces) + dot_name = concat (".", pass->name, num, NULL); + if (ipa) { - schedule_ebbs (dump_file); - /* No liveness updating code yet, but it should be easy to do. - reg-stack recomputes the liveness when needed for now. */ - count_or_remove_death_notes (NULL, 1); - cleanup_cfg (CLEANUP_EXPENSIVE); + flag_name = concat ("ipa-", pass->name, num, NULL); + glob_name = concat ("ipa-", pass->name, NULL); + /* First IPA dump is cgraph that is dumped via separate channels. */ + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_IPA, n + 1, 0); } - else - schedule_insns (dump_file); - - close_dump_file (DFI_sched2, print_rtl_with_bb, get_insns ()); - - ggc_collect (); - - timevar_pop (TV_SCHED2); -} -#endif - -static void -rest_of_handle_gcse2 (void) -{ - timevar_push (TV_GCSE_AFTER_RELOAD); - open_dump_file (DFI_gcse2, current_function_decl); - - gcse_after_reload_main (get_insns ()); - rebuild_jump_labels (get_insns ()); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - close_dump_file (DFI_gcse2, print_rtl_with_bb, get_insns ()); - - ggc_collect (); - -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif - - timevar_pop (TV_GCSE_AFTER_RELOAD); -} - -/* Register allocation pre-pass, to reduce number of moves necessary - for two-address machines. */ -static void -rest_of_handle_regmove (void) -{ - timevar_push (TV_REGMOVE); - open_dump_file (DFI_regmove, current_function_decl); - - regmove_optimize (get_insns (), max_reg_num (), dump_file); - - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); - close_dump_file (DFI_regmove, print_rtl_with_bb, get_insns ()); - - ggc_collect (); - timevar_pop (TV_REGMOVE); -} - -/* Run tracer. */ -static void -rest_of_handle_tracer (void) -{ - open_dump_file (DFI_tracer, current_function_decl); - if (dump_file) - dump_flow_info (dump_file); - tracer (0); - cleanup_cfg (CLEANUP_EXPENSIVE); - reg_scan (get_insns (), max_reg_num ()); - close_dump_file (DFI_tracer, print_rtl_with_bb, get_insns ()); -} - -/* If-conversion and CFG cleanup. */ -static void -rest_of_handle_if_conversion (void) -{ - timevar_push (TV_IFCVT); - open_dump_file (DFI_ce1, current_function_decl); - - if (flag_if_conversion) + else if (pass->properties_provided & PROP_trees) { - if (dump_file) - dump_flow_info (dump_file); - cleanup_cfg (CLEANUP_EXPENSIVE); - reg_scan (get_insns (), max_reg_num ()); - if_convert (0); + flag_name = concat ("tree-", pass->name, num, NULL); + glob_name = concat ("tree-", pass->name, NULL); + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_TREE, n + TDI_tree_all, 0); } - - timevar_push (TV_JUMP); - cleanup_cfg (CLEANUP_EXPENSIVE); - reg_scan (get_insns (), max_reg_num ()); - timevar_pop (TV_JUMP); - - close_dump_file (DFI_ce1, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_IFCVT); -} - -/* Rerun if-conversion, as combine may have simplified things enough - to now meet sequence length restrictions. */ -static void -rest_of_handle_if_after_combine (void) -{ - timevar_push (TV_IFCVT); - open_dump_file (DFI_ce2, current_function_decl); - - no_new_pseudos = 0; - if_convert (1); - no_new_pseudos = 1; - - close_dump_file (DFI_ce2, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_IFCVT); -} - -static void -rest_of_handle_if_after_reload (void) -{ - timevar_push (TV_IFCVT2); - open_dump_file (DFI_ce3, current_function_decl); - - /* Last attempt to optimize CFG, as scheduling, peepholing and insn - splitting possibly introduced more crossjumping opportunities. */ - cleanup_cfg (CLEANUP_EXPENSIVE - | CLEANUP_UPDATE_LIFE - | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); - if (flag_if_conversion2) - if_convert (1); - close_dump_file (DFI_ce3, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_IFCVT2); -} - -static void -rest_of_handle_web (void) -{ - open_dump_file (DFI_web, current_function_decl); - timevar_push (TV_WEB); - web_main (); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - cleanup_cfg (CLEANUP_EXPENSIVE); - - timevar_pop (TV_WEB); - close_dump_file (DFI_web, print_rtl_with_bb, get_insns ()); - reg_scan (get_insns (), max_reg_num ()); -} - -/* Do branch profiling and static profile estimation passes. */ -static void -rest_of_handle_branch_prob (void) -{ - struct loops loops; - - timevar_push (TV_BRANCH_PROB); - open_dump_file (DFI_bp, current_function_decl); - - if ((profile_arc_flag || flag_test_coverage || flag_branch_probabilities) - && !flag_tree_based_profiling) - branch_prob (); - - /* Discover and record the loop depth at the head of each basic - block. The loop infrastructure does the real job for us. */ - flow_loops_find (&loops); - - if (dump_file) - flow_loops_dump (&loops, dump_file, NULL, 0); - - /* Estimate using heuristics if no profiling info is available. */ - if (flag_guess_branch_prob && profile_status == PROFILE_ABSENT) - estimate_probability (&loops); - - flow_loops_free (&loops); - free_dominance_info (CDI_DOMINATORS); - close_dump_file (DFI_bp, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_BRANCH_PROB); -} - -/* Do optimizations based on expression value profiles. */ -static void -rest_of_handle_value_profile_transformations (void) -{ - open_dump_file (DFI_vpt, current_function_decl); - timevar_push (TV_VPT); - - if (value_profile_transformations ()) - cleanup_cfg (CLEANUP_EXPENSIVE); - - timevar_pop (TV_VPT); - close_dump_file (DFI_vpt, print_rtl_with_bb, get_insns ()); -} - -/* Do control and data flow analysis; write some of the results to the - dump file. */ -static void -rest_of_handle_cfg (void) -{ - open_dump_file (DFI_cfg, current_function_decl); - if (dump_file) - dump_flow_info (dump_file); - if (optimize) - cleanup_cfg (CLEANUP_EXPENSIVE - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); - - /* It may make more sense to mark constant functions after dead code is - eliminated by life_analysis, but we need to do it early, as -fprofile-arcs - may insert code making function non-constant, but we still must consider - it as constant, otherwise -fbranch-probabilities will not read data back. - - life_analysis rarely eliminates modification of external memory. - - FIXME: now with tree based profiling we are in the trap described above - again. It seems to be easiest to disable the optimization for time - being before the problem is either solved by moving the transformation - to the IPA level (we need the CFG for this) or the very early optimization - passes are made to ignore the const/pure flags so code does not change. */ - if (optimize - && (!flag_tree_based_profiling - || (!profile_arc_flag && !flag_branch_probabilities))) + else { - /* Alias analysis depends on this information and mark_constant_function - depends on alias analysis. */ - reg_scan (get_insns (), max_reg_num ()); - mark_constant_function (); + flag_name = concat ("rtl-", pass->name, num, NULL); + glob_name = concat ("rtl-", pass->name, NULL); + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_RTL, n, pass->letter); } - - close_dump_file (DFI_cfg, print_rtl_with_bb, get_insns ()); } -/* Perform jump bypassing and control flow optimizations. */ -static void -rest_of_handle_jump_bypass (void) +static int +register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties) { - timevar_push (TV_BYPASS); - open_dump_file (DFI_bypass, current_function_decl); - - cleanup_cfg (CLEANUP_EXPENSIVE); - reg_scan (get_insns (), max_reg_num ()); - - if (bypass_jumps (dump_file)) + static int n = 0; + do { - rebuild_jump_labels (get_insns ()); - cleanup_cfg (CLEANUP_EXPENSIVE); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - } + int new_properties; + int pass_number; - close_dump_file (DFI_bypass, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_BYPASS); + pass->properties_required = properties; + new_properties = + (properties | pass->properties_provided) & ~pass->properties_destroyed; - ggc_collect (); + /* Reset the counter when we reach RTL-based passes. */ + if ((new_properties ^ pass->properties_required) & PROP_rtl) + n = 0; -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif -} + pass_number = n; + if (pass->name) + n++; -/* Try combining insns through substitution. */ -static void -rest_of_handle_combine (void) -{ - int rebuild_jump_labels_after_combine = 0; + if (pass->sub) + new_properties = register_dump_files (pass->sub, false, new_properties); - timevar_push (TV_COMBINE); - open_dump_file (DFI_combine, current_function_decl); + /* If we have a gate, combine the properties that we could have with + and without the pass being examined. */ + if (pass->gate) + properties &= new_properties; + else + properties = new_properties; - rebuild_jump_labels_after_combine - = combine_instructions (get_insns (), max_reg_num ()); + pass->properties_provided = properties; + if (pass->name) + register_one_dump_file (pass, ipa, pass_number); - /* Combining insns may have turned an indirect jump into a - direct jump. Rebuild the JUMP_LABEL fields of jumping - instructions. */ - if (rebuild_jump_labels_after_combine) - { - timevar_push (TV_JUMP); - rebuild_jump_labels (get_insns ()); - timevar_pop (TV_JUMP); - - delete_dead_jumptables (); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); + pass = pass->next; } + while (pass); - close_dump_file (DFI_combine, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_COMBINE); - - ggc_collect (); + return properties; } -/* Perform life analysis. */ -static void -rest_of_handle_life (void) -{ - open_dump_file (DFI_life, current_function_decl); - regclass_init (); +/* Add a pass to the pass list. Duplicate the pass if it's already + in the list. */ -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif - life_analysis (dump_file, PROP_FINAL); - if (optimize) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE | CLEANUP_LOG_LINKS - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); +static struct tree_opt_pass ** +next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass) +{ - if (extra_warnings) + /* A nonzero static_pass_number indicates that the + pass is already in the list. */ + if (pass->static_pass_number) { - setjmp_vars_warning (DECL_INITIAL (current_function_decl)); - setjmp_args_warning (); - } + struct tree_opt_pass *new; - if (optimize) - { - if (initialize_uninitialized_subregs ()) - { - /* Insns were inserted, and possibly pseudos created, so - things might look a bit different. */ - allocate_reg_life_data (); - update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, - PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES); + new = xmalloc (sizeof (*new)); + memcpy (new, pass, sizeof (*new)); + + /* Indicate to register_dump_files that this pass has duplicates, + and so it should rename the dump file. The first instance will + be -1, and be number of duplicates = -static_pass_number - 1. + Subsequent instances will be > 0 and just the duplicate number. */ + if (pass->name) + { + pass->static_pass_number -= 1; + new->static_pass_number = -pass->static_pass_number; } + + *list = new; } - - no_new_pseudos = 1; - - close_dump_file (DFI_life, print_rtl_with_bb, get_insns ()); - - ggc_collect (); -} - -/* Perform common subexpression elimination. Nonzero value from - `cse_main' means that jumps were simplified and some code may now - be unreachable, so do jump optimization again. */ -static void -rest_of_handle_cse (void) -{ - int tem; - - open_dump_file (DFI_cse, current_function_decl); - if (dump_file) - dump_flow_info (dump_file); - timevar_push (TV_CSE); - - reg_scan (get_insns (), max_reg_num ()); - - tem = cse_main (get_insns (), max_reg_num (), dump_file); - if (tem) - rebuild_jump_labels (get_insns ()); - if (purge_all_dead_edges ()) - delete_unreachable_blocks (); - - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - - /* If we are not running more CSE passes, then we are no longer - expecting CSE to be run. But always rerun it in a cheap mode. */ - cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse; - - if (tem) - delete_dead_jumptables (); - - if (tem || optimize > 1) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - - timevar_pop (TV_CSE); - close_dump_file (DFI_cse, print_rtl_with_bb, get_insns ()); - - ggc_collect (); -} - -/* Run second CSE pass after loop optimizations. */ -static void -rest_of_handle_cse2 (void) -{ - int tem; - - timevar_push (TV_CSE2); - open_dump_file (DFI_cse2, current_function_decl); - if (dump_file) - dump_flow_info (dump_file); - - tem = cse_main (get_insns (), max_reg_num (), dump_file); - - /* Run a pass to eliminate duplicated assignments to condition code - registers. We have to run this after bypass_jumps, because it - makes it harder for that pass to determine whether a jump can be - bypassed safely. */ - cse_condition_code_reg (); - - purge_all_dead_edges (); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - - if (tem) + else { - timevar_push (TV_JUMP); - rebuild_jump_labels (get_insns ()); - delete_dead_jumptables (); - cleanup_cfg (CLEANUP_EXPENSIVE); - timevar_pop (TV_JUMP); - } - reg_scan (get_insns (), max_reg_num ()); - close_dump_file (DFI_cse2, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_CSE2); - - ggc_collect (); + pass->static_pass_number = -1; + *list = pass; + } + + return &(*list)->next; + } -/* Perform global cse. */ -static void -rest_of_handle_gcse (void) -{ - int save_csb, save_cfj; - int tem2 = 0, tem; - - timevar_push (TV_GCSE); - open_dump_file (DFI_gcse, current_function_decl); - - tem = gcse_main (get_insns (), dump_file); - rebuild_jump_labels (get_insns ()); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - - save_csb = flag_cse_skip_blocks; - save_cfj = flag_cse_follow_jumps; - flag_cse_skip_blocks = flag_cse_follow_jumps = 0; +/* Construct the pass tree. */ - /* If -fexpensive-optimizations, re-run CSE to clean up things done - by gcse. */ - if (flag_expensive_optimizations) +void +init_optimization_passes (void) +{ + struct tree_opt_pass **p; + +#define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS)) + /* Interprocedural optimization passes. */ + p = &all_ipa_passes; + NEXT_PASS (pass_early_ipa_inline); + NEXT_PASS (pass_early_local_passes); + NEXT_PASS (pass_ipa_inline); + *p = NULL; + + /* All passes needed to lower the function into shape optimizers can operate + on. These passes are performed before interprocedural passes, unlike rest + of local passes (all_passes). */ + p = &all_lowering_passes; + NEXT_PASS (pass_remove_useless_stmts); + NEXT_PASS (pass_mudflap_1); + NEXT_PASS (pass_lower_cf); + NEXT_PASS (pass_lower_eh); + NEXT_PASS (pass_build_cfg); + NEXT_PASS (pass_lower_complex_O0); + NEXT_PASS (pass_lower_vector); + NEXT_PASS (pass_warn_function_return); + NEXT_PASS (pass_early_tree_profile); + *p = NULL; + + p = &pass_early_local_passes.sub; + NEXT_PASS (pass_tree_profile); + NEXT_PASS (pass_cleanup_cfg); + NEXT_PASS (pass_rebuild_cgraph_edges); + *p = NULL; + + p = &all_passes; + NEXT_PASS (pass_fixup_cfg); + NEXT_PASS (pass_init_datastructures); + NEXT_PASS (pass_all_optimizations); + NEXT_PASS (pass_warn_function_noreturn); + NEXT_PASS (pass_mudflap_2); + NEXT_PASS (pass_free_datastructures); + NEXT_PASS (pass_free_cfg_annotations); + NEXT_PASS (pass_expand); + NEXT_PASS (pass_rest_of_compilation); + NEXT_PASS (pass_clean_state); + *p = NULL; + + p = &pass_all_optimizations.sub; + NEXT_PASS (pass_referenced_vars); + NEXT_PASS (pass_create_structure_vars); + NEXT_PASS (pass_build_ssa); + NEXT_PASS (pass_build_pta); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_return_slot); + NEXT_PASS (pass_del_pta); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_early_warn_uninitialized); + + /* Initial scalar cleanups. */ + NEXT_PASS (pass_ccp); + NEXT_PASS (pass_fre); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_vrp); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_merge_phi); + NEXT_PASS (pass_dominator); + + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_build_pta); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_del_pta); + NEXT_PASS (pass_tail_recursion); + NEXT_PASS (pass_profile); + NEXT_PASS (pass_ch); + NEXT_PASS (pass_stdarg); + NEXT_PASS (pass_lower_complex); + NEXT_PASS (pass_sra); + /* FIXME: SRA may generate arbitrary gimple code, exposing new + aliased and call-clobbered variables. As mentioned below, + pass_may_alias should be a TODO item. */ + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_dominator); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_dse); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_object_sizes); + NEXT_PASS (pass_store_ccp); + NEXT_PASS (pass_store_copy_prop); + NEXT_PASS (pass_fold_builtins); + /* FIXME: May alias should a TODO but for 4.0.0, + we add may_alias right after fold builtins + which can create arbitrary GIMPLE. */ + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_cse_reciprocals); + NEXT_PASS (pass_split_crit_edges); + NEXT_PASS (pass_reassoc); + NEXT_PASS (pass_pre); + NEXT_PASS (pass_sink_code); + NEXT_PASS (pass_loop); + NEXT_PASS (pass_dominator); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_cd_dce); + + /* FIXME: If DCE is not run before checking for uninitialized uses, + we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c). + However, this also causes us to misdiagnose cases that should be + real warnings (e.g., testsuite/gcc.dg/pr18501.c). + + To fix the false positives in uninit-5.c, we would have to + account for the predicates protecting the set and the use of each + variable. Using a representation like Gated Single Assignment + may help. */ + NEXT_PASS (pass_late_warn_uninitialized); + NEXT_PASS (pass_dse); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_tail_calls); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_uncprop); + NEXT_PASS (pass_del_ssa); + NEXT_PASS (pass_nrv); + NEXT_PASS (pass_remove_useless_vars); + NEXT_PASS (pass_mark_used_blocks); + NEXT_PASS (pass_cleanup_cfg_post_optimizing); + *p = NULL; + + p = &pass_loop.sub; + NEXT_PASS (pass_loop_init); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_lim); + NEXT_PASS (pass_unswitch); + NEXT_PASS (pass_scev_cprop); + NEXT_PASS (pass_record_bounds); + NEXT_PASS (pass_linear_transform); + NEXT_PASS (pass_iv_canon); + NEXT_PASS (pass_if_conversion); + NEXT_PASS (pass_vectorize); + /* NEXT_PASS (pass_may_alias) cannot be done again because the + vectorizer creates alias relations that are not supported by + pass_may_alias. */ + NEXT_PASS (pass_lower_vector_ssa); + NEXT_PASS (pass_complete_unroll); + NEXT_PASS (pass_iv_optimize); + NEXT_PASS (pass_loop_done); + *p = NULL; + + p = &pass_rest_of_compilation.sub; + NEXT_PASS (pass_remove_unnecessary_notes); + NEXT_PASS (pass_init_function); + NEXT_PASS (pass_jump); + NEXT_PASS (pass_insn_locators_initialize); + NEXT_PASS (pass_rtl_eh); + NEXT_PASS (pass_initial_value_sets); + NEXT_PASS (pass_unshare_all_rtl); + NEXT_PASS (pass_instantiate_virtual_regs); + NEXT_PASS (pass_jump2); + NEXT_PASS (pass_cse); + NEXT_PASS (pass_gcse); + NEXT_PASS (pass_loop_optimize); + NEXT_PASS (pass_jump_bypass); + NEXT_PASS (pass_cfg); + NEXT_PASS (pass_profiling); + NEXT_PASS (pass_rtl_ifcvt); + NEXT_PASS (pass_tracer); + NEXT_PASS (pass_loop2); + NEXT_PASS (pass_web); + NEXT_PASS (pass_cse2); + NEXT_PASS (pass_life); + NEXT_PASS (pass_combine); + NEXT_PASS (pass_if_after_combine); + NEXT_PASS (pass_partition_blocks); + NEXT_PASS (pass_regmove); + NEXT_PASS (pass_split_all_insns); + NEXT_PASS (pass_mode_switching); + NEXT_PASS (pass_recompute_reg_usage); + NEXT_PASS (pass_sms); + NEXT_PASS (pass_sched); + NEXT_PASS (pass_local_alloc); + NEXT_PASS (pass_global_alloc); + NEXT_PASS (pass_postreload); + *p = NULL; + + p = &pass_profiling.sub; + NEXT_PASS (pass_branch_prob); + NEXT_PASS (pass_value_profile_transformations); + NEXT_PASS (pass_remove_death_notes); + *p = NULL; + + p = &pass_postreload.sub; + NEXT_PASS (pass_postreload_cse); + NEXT_PASS (pass_gcse2); + NEXT_PASS (pass_flow2); + NEXT_PASS (pass_stack_adjustments); + NEXT_PASS (pass_peephole2); + NEXT_PASS (pass_if_after_reload); + NEXT_PASS (pass_regrename); + NEXT_PASS (pass_reorder_blocks); + NEXT_PASS (pass_branch_target_load_optimize); + NEXT_PASS (pass_leaf_regs); + NEXT_PASS (pass_sched2); + NEXT_PASS (pass_split_before_regstack); + NEXT_PASS (pass_stack_regs); + NEXT_PASS (pass_compute_alignments); + NEXT_PASS (pass_duplicate_computed_gotos); + NEXT_PASS (pass_variable_tracking); + NEXT_PASS (pass_free_cfg); + NEXT_PASS (pass_machine_reorg); + NEXT_PASS (pass_purge_lineno_notes); + NEXT_PASS (pass_cleanup_barriers); + NEXT_PASS (pass_delay_slots); + NEXT_PASS (pass_split_for_shorten_branches); + NEXT_PASS (pass_convert_to_eh_region_ranges); + NEXT_PASS (pass_shorten_branches); + NEXT_PASS (pass_set_nothrow_function_flags); + NEXT_PASS (pass_final); + *p = NULL; + +#undef NEXT_PASS + + /* Register the passes with the tree dump code. */ + register_dump_files (all_lowering_passes, false, PROP_gimple_any); + register_dump_files (all_passes, false, PROP_gimple_leh + | PROP_cfg); + register_dump_files (all_ipa_passes, true, PROP_gimple_leh + | PROP_cfg); +} + +static unsigned int last_verified; + +static void +execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) +{ + int properties + = use_required ? pass->properties_required : pass->properties_provided; + +#if defined ENABLE_CHECKING + if (need_ssa_update_p ()) + gcc_assert (flags & TODO_update_ssa_any); +#endif + + if (flags & TODO_update_ssa_any) { - timevar_push (TV_CSE); - reg_scan (get_insns (), max_reg_num ()); - tem2 = cse_main (get_insns (), max_reg_num (), dump_file); - purge_all_dead_edges (); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - timevar_pop (TV_CSE); - cse_not_expected = !flag_rerun_cse_after_loop; + unsigned update_flags = flags & TODO_update_ssa_any; + update_ssa (update_flags); } - /* If gcse or cse altered any jumps, rerun jump optimizations to clean - things up. */ - if (tem || tem2) + if (flags & TODO_cleanup_cfg) { - timevar_push (TV_JUMP); - rebuild_jump_labels (get_insns ()); - delete_dead_jumptables (); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - timevar_pop (TV_JUMP); + if (current_loops) + cleanup_tree_cfg_loop (); + else + cleanup_tree_cfg (); } - close_dump_file (DFI_gcse, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_GCSE); - - ggc_collect (); - flag_cse_skip_blocks = save_csb; - flag_cse_follow_jumps = save_cfj; -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif -} - -/* Move constant computations out of loops. */ -static void -rest_of_handle_loop_optimize (void) -{ - int do_prefetch; - - timevar_push (TV_LOOP); - open_dump_file (DFI_loop, current_function_decl); - - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - profile_status = PROFILE_ABSENT; - - do_prefetch = flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0; - - if (flag_rerun_loop_opt) + if ((flags & TODO_dump_func) + && dump_file && current_function_decl) { - cleanup_barriers (); - - /* We only want to perform unrolling once. */ - loop_optimize (get_insns (), dump_file, 0); - - /* The first call to loop_optimize makes some instructions - trivially dead. We delete those instructions now in the - hope that doing so will make the heuristics in loop work - better and possibly speed up compilation. */ - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - - /* The regscan pass is currently necessary as the alias - analysis code depends on this information. */ - reg_scan (get_insns (), max_reg_num ()); + if (properties & PROP_trees) + dump_function_to_file (current_function_decl, + dump_file, dump_flags); + else if (properties & PROP_cfg) + print_rtl_with_bb (dump_file, get_insns ()); + else + print_rtl (dump_file, get_insns ()); + + /* Flush the file. If verification fails, we won't be able to + close the file before aborting. */ + fflush (dump_file); } - cleanup_barriers (); - loop_optimize (get_insns (), dump_file, do_prefetch); - - /* Loop can create trivially dead instructions. */ - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - find_basic_blocks (get_insns ()); - close_dump_file (DFI_loop, print_rtl, get_insns ()); - timevar_pop (TV_LOOP); - - ggc_collect (); -} - -/* Perform loop optimizations. It might be better to do them a bit - sooner, but we want the profile feedback to work more - efficiently. */ -static void -rest_of_handle_loop2 (void) -{ - struct loops *loops; - basic_block bb; - - if (!flag_move_loop_invariants - && !flag_unswitch_loops - && !flag_peel_loops - && !flag_unroll_loops - && !flag_branch_on_count_reg) - return; - - timevar_push (TV_LOOP); - open_dump_file (DFI_loop2, current_function_decl); - if (dump_file) - dump_flow_info (dump_file); - - /* Initialize structures for layout changes. */ - cfg_layout_initialize (0); - - loops = loop_optimizer_init (dump_file); - - if (loops) + if ((flags & TODO_dump_cgraph) + && dump_file && !current_function_decl) { - /* The optimizations: */ - if (flag_move_loop_invariants) - move_loop_invariants (loops); - - if (flag_unswitch_loops) - unswitch_loops (loops); - - if (flag_peel_loops || flag_unroll_loops) - unroll_and_peel_loops (loops, - (flag_peel_loops ? UAP_PEEL : 0) | - (flag_unroll_loops ? UAP_UNROLL : 0) | - (flag_unroll_all_loops ? UAP_UNROLL_ALL : 0)); - -#ifdef HAVE_doloop_end - if (flag_branch_on_count_reg && HAVE_doloop_end) - doloop_optimize_loops (loops); -#endif /* HAVE_doloop_end */ - - loop_optimizer_finalize (loops, dump_file); + dump_cgraph (dump_file); + /* Flush the file. If verification fails, we won't be able to + close the file before aborting. */ + fflush (dump_file); } - free_dominance_info (CDI_DOMINATORS); - - /* Finalize layout changes. */ - FOR_EACH_BB (bb) - if (bb->next_bb != EXIT_BLOCK_PTR) - bb->aux = bb->next_bb; - cfg_layout_finalize (); - - cleanup_cfg (CLEANUP_EXPENSIVE); - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - reg_scan (get_insns (), max_reg_num ()); - if (dump_file) - dump_flow_info (dump_file); - close_dump_file (DFI_loop2, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_LOOP); - ggc_collect (); -} - -static void -rest_of_handle_branch_target_load_optimize (void) -{ - static int warned = 0; - - /* Leave this a warning for now so that it is possible to experiment - with running this pass twice. In 3.6, we should either make this - an error, or use separate dump files. */ - if (flag_branch_target_load_optimize - && flag_branch_target_load_optimize2 - && !warned) + if (flags & TODO_ggc_collect) { - warning (0, "branch target register load optimization is not intended " - "to be run twice"); - - warned = 1; + ggc_collect (); } - open_dump_file (DFI_branch_target_load, current_function_decl); - branch_target_load_optimize (epilogue_completed); - close_dump_file (DFI_branch_target_load, print_rtl_with_bb, get_insns ()); - ggc_collect (); -} - -#ifdef OPTIMIZE_MODE_SWITCHING -static void -rest_of_handle_mode_switching (void) -{ - timevar_push (TV_MODE_SWITCH); - - no_new_pseudos = 0; - optimize_mode_switching (NULL); - no_new_pseudos = 1; - - timevar_pop (TV_MODE_SWITCH); -} +#if defined ENABLE_CHECKING + if ((pass->properties_required & PROP_ssa) + && !(pass->properties_destroyed & PROP_ssa)) + verify_ssa (true); + if (flags & TODO_verify_flow) + verify_flow_info (); + if (flags & TODO_verify_stmts) + verify_stmts (); + if (flags & TODO_verify_loops) + verify_loop_closed_ssa (); #endif +} -static void -rest_of_handle_jump (void) +static bool +execute_one_pass (struct tree_opt_pass *pass) { - ggc_collect (); - - timevar_push (TV_JUMP); - open_dump_file (DFI_sibling, current_function_decl); + unsigned int todo; - delete_unreachable_blocks (); -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif + /* See if we're supposed to run this pass. */ + if (pass->gate && !pass->gate ()) + return false; - if (cfun->tail_call_emit) - fixup_tail_calls (); + /* Note that the folders should only create gimple expressions. + This is a hack until the new folder is ready. */ + in_gimple_form = (pass->properties_provided & PROP_trees) != 0; - close_dump_file (DFI_sibling, print_rtl, get_insns ()); - timevar_pop (TV_JUMP); -} + /* Run pre-pass verification. */ + todo = pass->todo_flags_start & ~last_verified; + if (todo) + execute_todo (pass, todo, true); -static void -rest_of_handle_eh (void) -{ - insn_locators_initialize (); - /* Complete generation of exception handling code. */ - if (doing_eh (0)) + /* If a dump file name is present, open it if enabled. */ + if (pass->static_pass_number != -1) { - timevar_push (TV_JUMP); - open_dump_file (DFI_eh, current_function_decl); - - cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL); - - finish_eh_generation (); - - cleanup_cfg (CLEANUP_PRE_LOOP | CLEANUP_NO_INSN_DEL); + bool initializing_dump = !dump_initialized_p (pass->static_pass_number); + dump_file_name = get_dump_file_name (pass->static_pass_number); + dump_file = dump_begin (pass->static_pass_number, &dump_flags); + if (dump_file && current_function_decl) + { + const char *dname, *aname; + dname = lang_hooks.decl_printable_name (current_function_decl, 2); + aname = (IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (current_function_decl))); + fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, + cfun->function_frequency == FUNCTION_FREQUENCY_HOT + ? " (hot)" + : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED + ? " (unlikely executed)" + : ""); + } - close_dump_file (DFI_eh, print_rtl, get_insns ()); - timevar_pop (TV_JUMP); + if (initializing_dump + && graph_dump_format != no_graph + && (pass->properties_provided & (PROP_cfg | PROP_rtl)) + == (PROP_cfg | PROP_rtl)) + clean_graph_dump_file (dump_file_name); } -} -static void -rest_of_handle_stack_adjustments (void) -{ - life_analysis (dump_file, PROP_POSTRELOAD); - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE - | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); - - /* This is kind of a heuristic. We need to run combine_stack_adjustments - even for machines with possibly nonzero RETURN_POPS_ARGS - and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having - push instructions will have popping returns. */ -#ifndef PUSH_ROUNDING - if (!ACCUMULATE_OUTGOING_ARGS) -#endif - combine_stack_adjustments (); -} + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); -static void -rest_of_handle_flow2 (void) -{ - timevar_push (TV_FLOW2); - open_dump_file (DFI_flow2, current_function_decl); + /* Do it! */ + if (pass->execute) + pass->execute (); - /* Re-create the death notes which were deleted during reload. */ -#ifdef ENABLE_CHECKING - verify_flow_info (); -#endif + /* Stop timevar. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); - /* If optimizing, then go ahead and split insns now. */ -#ifndef STACK_REGS - if (optimize > 0) -#endif - split_all_insns (0); + /* Run post-pass cleanup and verification. */ + todo = pass->todo_flags_finish; + last_verified = todo & TODO_verify_all; + if (todo) + execute_todo (pass, todo, false); - if (flag_branch_target_load_optimize) + /* Flush and close dump file. */ + if (dump_file_name) { - close_dump_file (DFI_flow2, print_rtl_with_bb, get_insns ()); - rest_of_handle_branch_target_load_optimize (); - open_dump_file (DFI_flow2, current_function_decl); + free ((char *) dump_file_name); + dump_file_name = NULL; } - - if (optimize) - cleanup_cfg (CLEANUP_EXPENSIVE); - - /* On some machines, the prologue and epilogue code, or parts thereof, - can be represented as RTL. Doing so lets us schedule insns between - it and the rest of the code and also allows delayed branch - scheduling to operate in the epilogue. */ - thread_prologue_and_epilogue_insns (get_insns ()); - epilogue_completed = 1; - - if (optimize) - rest_of_handle_stack_adjustments (); - - flow2_completed = 1; - - close_dump_file (DFI_flow2, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_FLOW2); - - ggc_collect (); -} - - -static void -rest_of_handle_jump2 (void) -{ - open_dump_file (DFI_jump, current_function_decl); - - /* Always do one jump optimization pass to ensure that JUMP_LABEL fields - are initialized and to compute whether control can drop off the end - of the function. */ - - timevar_push (TV_JUMP); - /* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this - before jump optimization switches branch directions. */ - if (flag_guess_branch_prob) - expected_value_to_br_prob (); - - delete_trivially_dead_insns (get_insns (), max_reg_num ()); - reg_scan (get_insns (), max_reg_num ()); if (dump_file) - dump_flow_info (dump_file); - cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP - | (flag_thread_jumps ? CLEANUP_THREADING : 0)); - - create_loop_notes (); - - purge_line_number_notes (get_insns ()); - - if (optimize) - cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP); - - /* Jump optimization, and the removal of NULL pointer checks, may - have reduced the number of instructions substantially. CSE, and - future passes, allocate arrays whose dimensions involve the - maximum instruction UID, so if we can reduce the maximum UID - we'll save big on memory. */ - renumber_insns (dump_file); - - close_dump_file (DFI_jump, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_JUMP); - - ggc_collect (); -} - -#ifdef HAVE_peephole2 -static void -rest_of_handle_peephole2 (void) -{ - timevar_push (TV_PEEPHOLE2); - open_dump_file (DFI_peephole2, current_function_decl); - - peephole2_optimize (dump_file); - - close_dump_file (DFI_peephole2, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_PEEPHOLE2); -} -#endif - -static void -rest_of_handle_postreload (void) -{ - timevar_push (TV_RELOAD_CSE_REGS); - open_dump_file (DFI_postreload, current_function_decl); - - /* Do a very simple CSE pass over just the hard registers. */ - reload_cse_regs (get_insns ()); - /* reload_cse_regs can eliminate potentially-trapping MEMs. - Remove any EH edges associated with them. */ - if (flag_non_call_exceptions) - purge_all_dead_edges (); - - close_dump_file (DFI_postreload, print_rtl_with_bb, get_insns ()); - timevar_pop (TV_RELOAD_CSE_REGS); -} - -static void -rest_of_handle_shorten_branches (void) -{ - /* Shorten branches. */ - timevar_push (TV_SHORTEN_BRANCH); - shorten_branches (get_insns ()); - timevar_pop (TV_SHORTEN_BRANCH); -} - -static void -rest_of_clean_state (void) -{ - rtx insn, next; - - /* It is very important to decompose the RTL instruction chain here: - debug information keeps pointing into CODE_LABEL insns inside the function - body. If these remain pointing to the other insns, we end up preserving - whole RTL chain and attached detailed debug info in memory. */ - for (insn = get_insns (); insn; insn = next) { - next = NEXT_INSN (insn); - NEXT_INSN (insn) = NULL; - PREV_INSN (insn) = NULL; + dump_end (pass->static_pass_number, dump_file); + dump_file = NULL; } - /* In case the function was not output, - don't leave any temporary anonymous types - queued up for sdb output. */ -#ifdef SDB_DEBUGGING_INFO - if (write_symbols == SDB_DEBUG) - sdbout_types (NULL_TREE); -#endif - - reload_completed = 0; - epilogue_completed = 0; - flow2_completed = 0; - no_new_pseudos = 0; - - timevar_push (TV_FINAL); - - /* Clear out the insn_length contents now that they are no - longer valid. */ - init_insn_lengths (); - - /* Show no temporary slots allocated. */ - init_temp_slots (); - - free_basic_block_vars (); - free_bb_for_insn (); - - timevar_pop (TV_FINAL); - - if (targetm.binds_local_p (current_function_decl)) - { - int pref = cfun->preferred_stack_boundary; - if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary) - pref = cfun->stack_alignment_needed; - cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary - = pref; - } - - /* Make sure volatile mem refs aren't considered valid operands for - arithmetic insns. We must call this here if this is a nested inline - function, since the above code leaves us in the init_recog state - (from final.c), and the function context push/pop code does not - save/restore volatile_ok. - - ??? Maybe it isn't necessary for expand_start_function to call this - anymore if we do it here? */ - - init_recog_no_volatile (); - - /* We're done with this function. Free up memory if we can. */ - free_after_parsing (cfun); - free_after_compilation (cfun); + return true; } - -/* This function is called from the pass manager in tree-optimize.c - after all tree passes have finished for a single function, and we - have expanded the function body from trees to RTL. - Once we are here, we have decided that we're supposed to output - that function, i.e. that we should write assembler code for it. - - We run a series of low-level passes here on the function's RTL - representation. Each pass is called via a rest_of_* function. */ - -static void -rest_of_compilation (void) +void +execute_pass_list (struct tree_opt_pass *pass) { - /* If we're emitting a nested function, make sure its parent gets - emitted as well. Doing otherwise confuses debug info. */ - { - tree parent; - for (parent = DECL_CONTEXT (current_function_decl); - parent != NULL_TREE; - parent = get_containing_scope (parent)) - if (TREE_CODE (parent) == FUNCTION_DECL) - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1; - } - - /* We are now committed to emitting code for this function. Do any - preparation, such as emitting abstract debug info for the inline - before it gets mangled by optimization. */ - if (cgraph_function_possibly_inlined_p (current_function_decl)) - (*debug_hooks->outlining_inline_function) (current_function_decl); - - /* Remove any notes we don't need. That will make iterating - over the instruction sequence faster, and allow the garbage - collector to reclaim the memory used by the notes. */ - remove_unnecessary_notes (); - - /* Initialize some variables used by the optimizers. */ - init_function_for_compilation (); - - TREE_ASM_WRITTEN (current_function_decl) = 1; - - /* Early return if there were errors. We can run afoul of our - consistency checks, and there's not really much point in fixing them. */ - if (rtl_dump_and_exit || flag_syntax_only || errorcount || sorrycount) - goto exit_rest_of_compilation; - - rest_of_handle_jump (); - - rest_of_handle_eh (); - - /* Delay emitting hard_reg_initial_value sets until after EH landing pad - generation, which might create new sets. */ - emit_initial_value_sets (); - -#ifdef FINALIZE_PIC - /* If we are doing position-independent code generation, now - is the time to output special prologues and epilogues. - We do not want to do this earlier, because it just clutters - up inline functions with meaningless insns. */ - if (flag_pic) - FINALIZE_PIC; -#endif - - /* Copy any shared structure that should not be shared. */ - unshare_all_rtl (); - - /* Instantiate all virtual registers. */ - instantiate_virtual_regs (); - - rest_of_handle_jump2 (); - - if (optimize > 0) - rest_of_handle_cse (); - - if (optimize > 0) + do { - if (flag_gcse) - rest_of_handle_gcse (); - - if (flag_loop_optimize) - rest_of_handle_loop_optimize (); - - if (flag_gcse) - rest_of_handle_jump_bypass (); - } - - timevar_push (TV_FLOW); - rest_of_handle_cfg (); - - if (optimize > 0 - || ((profile_arc_flag || flag_test_coverage || flag_branch_probabilities) - && !flag_tree_based_profiling)) - { - rtl_register_profile_hooks (); - rtl_register_value_prof_hooks (); - rest_of_handle_branch_prob (); - - if (flag_branch_probabilities - && flag_profile_values - && !flag_tree_based_profiling - && (flag_value_profile_transformations - || flag_speculative_prefetching)) - rest_of_handle_value_profile_transformations (); - - /* Remove the death notes created for vpt. */ - if (flag_profile_values) - count_or_remove_death_notes (NULL, 1); + if (execute_one_pass (pass) && pass->sub) + execute_pass_list (pass->sub); + pass = pass->next; } - - if (optimize > 0) - rest_of_handle_if_conversion (); - - if (optimize > 0 && flag_tracer) - rest_of_handle_tracer (); - - if (optimize > 0 - && flag_loop_optimize2) - rest_of_handle_loop2 (); - - if (optimize > 0 && flag_web) - rest_of_handle_web (); - - if (optimize > 0 && flag_rerun_cse_after_loop) - rest_of_handle_cse2 (); - - cse_not_expected = 1; - - rest_of_handle_life (); - timevar_pop (TV_FLOW); - - if (optimize > 0) - rest_of_handle_combine (); - - if (optimize > 0 && flag_if_conversion) - rest_of_handle_if_after_combine (); - - /* The optimization to partition hot/cold basic blocks into separate - sections of the .o file does not work well with linkonce or with - user defined section attributes. Don't call it if either case - arises. */ - - if (flag_reorder_blocks_and_partition - && !DECL_ONE_ONLY (current_function_decl) - && !user_defined_section_attribute) - rest_of_handle_partition_blocks (); - - if (optimize > 0 && flag_regmove) - rest_of_handle_regmove (); - - /* Do unconditional splitting before register allocation to allow machine - description to add extra information not needed previously. */ - split_all_insns (1); - -#ifdef OPTIMIZE_MODE_SWITCHING - rest_of_handle_mode_switching (); -#endif - - /* Any of the several passes since flow1 will have munged register - lifetime data a bit. We need it to be up to date for scheduling - (see handling of reg_known_equiv in init_alias_analysis). */ - recompute_reg_usage (); - -#ifdef INSN_SCHEDULING - if (optimize > 0 && flag_modulo_sched) - rest_of_handle_sms (); - - if (flag_schedule_insns) - rest_of_handle_sched (); -#endif - - /* Determine if the current function is a leaf before running reload - since this can impact optimizations done by the prologue and - epilogue thus changing register elimination offsets. */ - current_function_is_leaf = leaf_function_p (); - - if (rest_of_handle_old_regalloc ()) - goto exit_rest_of_compilation; - - if (optimize > 0) - rest_of_handle_postreload (); - - if (optimize > 0 && flag_gcse_after_reload) - rest_of_handle_gcse2 (); - - rest_of_handle_flow2 (); - -#ifdef HAVE_peephole2 - if (optimize > 0 && flag_peephole2) - rest_of_handle_peephole2 (); -#endif - - if (optimize > 0) - rest_of_handle_if_after_reload (); - - if (optimize > 0) - { - if (flag_rename_registers || flag_cprop_registers) - rest_of_handle_regrename (); - - rest_of_handle_reorder_blocks (); - } - - if (flag_branch_target_load_optimize2) - rest_of_handle_branch_target_load_optimize (); - -#ifdef LEAF_REGISTERS - current_function_uses_only_leaf_regs - = optimize > 0 && only_leaf_regs_used () && leaf_function_p (); -#endif - -#ifdef INSN_SCHEDULING - if (optimize > 0 && flag_schedule_insns_after_reload) - rest_of_handle_sched2 (); -#endif - -#ifdef STACK_REGS - rest_of_handle_stack_regs (); -#endif - - compute_alignments (); - - /* Aggressively duplicate basic blocks ending in computed gotos to the - tails of their predecessors, unless we are optimizing for size. */ - if (flag_expensive_optimizations && !optimize_size) - duplicate_computed_gotos (); - - if (flag_var_tracking) - rest_of_handle_variable_tracking (); - - /* CFG is no longer maintained up-to-date. */ - free_bb_for_insn (); - - if (targetm.machine_dependent_reorg != 0) - rest_of_handle_machine_reorg (); - - purge_line_number_notes (get_insns ()); - cleanup_barriers (); - -#ifdef DELAY_SLOTS - if (flag_delayed_branch) - rest_of_handle_delay_slots (); -#endif - -#if defined (HAVE_ATTR_length) && !defined (STACK_REGS) - timevar_push (TV_SHORTEN_BRANCH); - split_all_insns_noflow (); - timevar_pop (TV_SHORTEN_BRANCH); -#endif - - convert_to_eh_region_ranges (); - - rest_of_handle_shorten_branches (); - - set_nothrow_function_flags (); - - rest_of_handle_final (); - - exit_rest_of_compilation: - - rest_of_clean_state (); + while (pass); } +/* Same as execute_pass_list but assume that subpasses of IPA passes + are local passes. */ void -finish_optimization_passes (void) +execute_ipa_pass_list (struct tree_opt_pass *pass) { - enum tree_dump_index i; - struct dump_file_info *dfi; - char *name; - - timevar_push (TV_DUMP); - if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) + do { - open_dump_file (DFI_bp, NULL); - end_branch_prob (); - close_dump_file (DFI_bp, NULL, NULL_RTX); - } - - if (optimize > 0 && open_dump_file (DFI_combine, NULL)) - { - dump_combine_total_stats (dump_file); - close_dump_file (DFI_combine, NULL, NULL_RTX); + if (execute_one_pass (pass) && pass->sub) + { + struct cgraph_node *node; + for (node = cgraph_nodes; node; node = node->next) + if (node->analyzed) + { + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + current_function_decl = node->decl; + execute_pass_list (pass->sub); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + current_function_decl = NULL; + pop_cfun (); + ggc_collect (); + } + } + pass = pass->next; } - - /* Do whatever is necessary to finish printing the graphs. */ - if (graph_dump_format != no_graph) - for (i = DFI_MIN; (dfi = get_dump_file_info (i)) != NULL; ++i) - if (dump_initialized_p (i) - && (dfi->flags & TDF_RTL) != 0 - && (name = get_dump_file_name (i)) != NULL) - { - finish_graph_dump_file (name); - free (name); - } - - timevar_pop (TV_DUMP); + while (pass); } - -struct tree_opt_pass pass_rest_of_compilation = -{ - NULL, /* name */ - NULL, /* gate */ - rest_of_compilation, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_REST_OF_COMPILATION, /* tv_id */ - PROP_rtl, /* properties_required */ - 0, /* properties_provided */ - PROP_rtl, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_ggc_collect, /* todo_flags_finish */ - 0 /* letter */ -}; - - diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c index 5558e93..cf08c09 100644 --- a/gcc/postreload-gcse.c +++ b/gcc/postreload-gcse.c @@ -44,6 +44,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "hashtab.h" #include "params.h" #include "target.h" +#include "timevar.h" +#include "tree-pass.h" /* The following code implements gcse after reload, the purpose of this pass is to cleanup redundant loads generated by reload and other @@ -1337,3 +1339,37 @@ gcse_after_reload_main (rtx f ATTRIBUTE_UNUSED) free_mem (); } + +static bool +gate_handle_gcse2 (void) +{ + return (optimize > 0 && flag_gcse_after_reload); +} + + +static void +rest_of_handle_gcse2 (void) +{ + gcse_after_reload_main (get_insns ()); + rebuild_jump_labels (get_insns ()); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); +} + +struct tree_opt_pass pass_gcse2 = +{ + "gcse2", /* name */ + gate_handle_gcse2, /* gate */ + rest_of_handle_gcse2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_GCSE_AFTER_RELOAD, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */ + 'J' /* letter */ +}; + diff --git a/gcc/postreload.c b/gcc/postreload.c index 6877cd3..d164ae1 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -44,6 +44,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "toplev.h" #include "except.h" #include "tree.h" +#include "timevar.h" +#include "tree-pass.h" static int reload_cse_noop_set_p (rtx); static void reload_cse_simplify (rtx, rtx); @@ -1561,3 +1563,39 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) reg_set_luid[i] = 0; } } + +static bool +gate_handle_postreload (void) +{ + return (optimize > 0); +} + + +static void +rest_of_handle_postreload (void) +{ + /* Do a very simple CSE pass over just the hard registers. */ + reload_cse_regs (get_insns ()); + /* reload_cse_regs can eliminate potentially-trapping MEMs. + Remove any EH edges associated with them. */ + if (flag_non_call_exceptions) + purge_all_dead_edges (); +} + +struct tree_opt_pass pass_postreload_cse = +{ + "postreload", /* name */ + gate_handle_postreload, /* gate */ + rest_of_handle_postreload, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_RELOAD_CSE_REGS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'o' /* letter */ +}; + diff --git a/gcc/profile.c b/gcc/profile.c index c32003e..054f0771 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -65,6 +65,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree.h" #include "cfghooks.h" #include "tree-flow.h" +#include "timevar.h" +#include "cfgloop.h" +#include "tree-pass.h" /* Hooks for profiling. */ static struct profile_hooks* profile_hooks; @@ -1329,3 +1332,78 @@ rtl_register_profile_hooks (void) gcc_assert (!ir_type ()); profile_hooks = &rtl_profile_hooks; } + +static bool +gate_handle_profiling (void) +{ + return optimize > 0 + || (!flag_tree_based_profiling + && (profile_arc_flag || flag_test_coverage + || flag_branch_probabilities)); +} + +struct tree_opt_pass pass_profiling = +{ + NULL, /* name */ + gate_handle_profiling, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + +/* Do branch profiling and static profile estimation passes. */ +static void +rest_of_handle_branch_prob (void) +{ + struct loops loops; + + rtl_register_profile_hooks (); + rtl_register_value_prof_hooks (); + + if ((profile_arc_flag || flag_test_coverage || flag_branch_probabilities) + && !flag_tree_based_profiling) + branch_prob (); + + /* Discover and record the loop depth at the head of each basic + block. The loop infrastructure does the real job for us. */ + flow_loops_find (&loops); + + if (dump_file) + flow_loops_dump (&loops, dump_file, NULL, 0); + + /* Estimate using heuristics if no profiling info is available. */ + if (flag_guess_branch_prob && profile_status == PROFILE_ABSENT) + estimate_probability (&loops); + + flow_loops_free (&loops); + free_dominance_info (CDI_DOMINATORS); +} + +struct tree_opt_pass pass_branch_prob = +{ + "bp", /* name */ + NULL, /* gate */ + rest_of_handle_branch_prob, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_BRANCH_PROB, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'b' /* letter */ +}; + + + diff --git a/gcc/recog.c b/gcc/recog.c index eb9aeac..8e6a62b 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -39,6 +39,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "basic-block.h" #include "output.h" #include "reload.h" +#include "timevar.h" +#include "tree-pass.h" #ifndef STACK_PUSH_CODE #ifdef STACK_GROWS_DOWNWARD @@ -3418,3 +3420,122 @@ if_test_bypass_p (rtx out_insn, rtx in_insn) return true; } + +static bool +gate_handle_peephole2 (void) +{ + return (optimize > 0 && flag_peephole2); +} + +static void +rest_of_handle_peephole2 (void) +{ +#ifdef HAVE_peephole2 + peephole2_optimize (dump_file); +#endif +} + +struct tree_opt_pass pass_peephole2 = +{ + "peephole2", /* name */ + gate_handle_peephole2, /* gate */ + rest_of_handle_peephole2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_PEEPHOLE2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'z' /* letter */ +}; + +static void +rest_of_handle_split_all_insns (void) +{ + split_all_insns (1); +} + +struct tree_opt_pass pass_split_all_insns = +{ + NULL, /* name */ + NULL, /* gate */ + rest_of_handle_split_all_insns, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + +/* The placement of the splitting that we do for shorten_branches + depends on whether regstack is used by the target or not. */ +static bool +gate_do_final_split (void) +{ +#if defined (HAVE_ATTR_length) && !defined (STACK_REGS) + return 1; +#else + return 0; +#endif +} + +struct tree_opt_pass pass_split_for_shorten_branches = +{ + NULL, /* name */ + gate_do_final_split, /* gate */ + split_all_insns_noflow, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_SHORTEN_BRANCH, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + + +static bool +gate_handle_split_before_regstack (void) +{ +#if defined (HAVE_ATTR_length) && defined (STACK_REGS) + /* If flow2 creates new instructions which need splitting + and scheduling after reload is not done, they might not be + split until final which doesn't allow splitting + if HAVE_ATTR_length. */ +# ifdef INSN_SCHEDULING + return (optimize && !flag_schedule_insns_after_reload); +# else + return (optimize); +# endif +#else + return 0; +#endif +} + +struct tree_opt_pass pass_split_before_regstack = +{ + NULL, /* name */ + gate_handle_split_before_regstack, /* gate */ + rest_of_handle_split_all_insns, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_SHORTEN_BRANCH, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index ba1b0e1..d1d8b98 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -170,6 +170,8 @@ #include "varray.h" #include "reload.h" #include "ggc.h" +#include "timevar.h" +#include "tree-pass.h" /* We use this array to cache info about insns, because otherwise we spend too much time in stack_regs_mentioned_p. @@ -3126,5 +3128,52 @@ reg_to_stack (FILE *file) return true; } #endif /* STACK_REGS */ + +static bool +gate_handle_stack_regs (void) +{ +#ifdef STACK_REGS + return 1; +#else + return 0; +#endif +} + +/* Convert register usage from flat register file usage to a stack + register file. */ +static void +rest_of_handle_stack_regs (void) +{ +#ifdef STACK_REGS + if (reg_to_stack (dump_file) && optimize) + { + if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)) + && (flag_reorder_blocks || flag_reorder_blocks_and_partition)) + { + reorder_basic_blocks (0); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK); + } + } +#endif +} + +struct tree_opt_pass pass_stack_regs = +{ + "stack", /* name */ + gate_handle_stack_regs, /* gate */ + rest_of_handle_stack_regs, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REG_STACK, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'k' /* letter */ +}; #include "gt-reg-stack.h" diff --git a/gcc/regmove.c b/gcc/regmove.c index d93c056..08cacf4 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -43,6 +43,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "except.h" #include "toplev.h" #include "reload.h" +#include "timevar.h" +#include "tree-pass.h" /* Turn STACK_GROWS_DOWNWARD into a boolean. */ @@ -2461,3 +2463,80 @@ combine_stack_adjustments_for_block (basic_block bb) if (memlist) free_csa_memlist (memlist); } + +static bool +gate_handle_regmove (void) +{ + return (optimize > 0 && flag_regmove); +} + + +/* Register allocation pre-pass, to reduce number of moves necessary + for two-address machines. */ +static void +rest_of_handle_regmove (void) +{ + regmove_optimize (get_insns (), max_reg_num (), dump_file); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE); +} + +struct tree_opt_pass pass_regmove = +{ + "regmove", /* name */ + gate_handle_regmove, /* gate */ + rest_of_handle_regmove, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_REGMOVE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'N' /* letter */ +}; + + +static bool +gate_handle_stack_adjustments (void) +{ + return (optimize > 0); +} + +static void +rest_of_handle_stack_adjustments (void) +{ + life_analysis (dump_file, PROP_POSTRELOAD); + cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE + | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0)); + + /* This is kind of a heuristic. We need to run combine_stack_adjustments + even for machines with possibly nonzero RETURN_POPS_ARGS + and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having + push instructions will have popping returns. */ +#ifndef PUSH_ROUNDING + if (!ACCUMULATE_OUTGOING_ARGS) +#endif + combine_stack_adjustments (); +} + +struct tree_opt_pass pass_stack_adjustments = +{ + NULL, /* name */ + gate_handle_stack_adjustments, /* gate */ + rest_of_handle_stack_adjustments, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 0 /* letter */ +}; + diff --git a/gcc/regrename.c b/gcc/regrename.c index 3a596ff..cd448c4 100644 --- a/gcc/regrename.c +++ b/gcc/regrename.c @@ -36,6 +36,8 @@ #include "flags.h" #include "toplev.h" #include "obstack.h" +#include "timevar.h" +#include "tree-pass.h" struct du_chain { @@ -1907,3 +1909,38 @@ validate_value_data (struct value_data *vd) vd->e[i].next_regno); } #endif + +static bool +gate_handle_regrename (void) +{ + return (optimize > 0 && (flag_rename_registers || flag_cprop_registers)); +} + + +/* Run the regrename and cprop passes. */ +static void +rest_of_handle_regrename (void) +{ + if (flag_rename_registers) + regrename_optimize (); + if (flag_cprop_registers) + copyprop_hardreg_forward (); +} + +struct tree_opt_pass pass_regrename = +{ + "rnreg", /* name */ + gate_handle_regrename, /* gate */ + rest_of_handle_regrename, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_RENAME_REGISTERS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'n' /* letter */ +}; + diff --git a/gcc/reorg.c b/gcc/reorg.c index b6f60c7..c32d9bc 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -133,6 +133,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "resource.h" #include "except.h" #include "params.h" +#include "timevar.h" +#include "target.h" +#include "tree-pass.h" #ifdef DELAY_SLOTS @@ -3809,3 +3812,73 @@ dbr_schedule (rtx first, FILE *file) #endif } #endif /* DELAY_SLOTS */ + +static bool +gate_handle_delay_slots (void) +{ +#ifdef DELAY_SLOTS + return flag_delayed_branch; +#else + return 0; +#endif +} + +/* Run delay slot optimization. */ +static void +rest_of_handle_delay_slots (void) +{ +#ifdef DELAY_SLOTS + dbr_schedule (get_insns (), dump_file); +#endif +} + +struct tree_opt_pass pass_delay_slots = +{ + "dbr", /* name */ + gate_handle_delay_slots, /* gate */ + rest_of_handle_delay_slots, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_DBR_SCHED, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'd' /* letter */ +}; + +/* Machine dependent reorg pass. */ +static bool +gate_handle_machine_reorg (void) +{ + return targetm.machine_dependent_reorg != 0; +} + + +static void +rest_of_handle_machine_reorg (void) +{ + targetm.machine_dependent_reorg (); +} + +struct tree_opt_pass pass_machine_reorg = +{ + "mach", /* name */ + gate_handle_machine_reorg, /* gate */ + rest_of_handle_machine_reorg, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_MACH_DEP, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'M' /* letter */ +}; + @@ -1896,7 +1896,7 @@ extern enum rtx_code reversed_comparison_code_parts (enum rtx_code, rtx, rtx, rtx); extern void delete_for_peephole (rtx, rtx); extern int condjump_in_parallel_p (rtx); -extern void purge_line_number_notes (rtx); +extern void purge_line_number_notes (void); /* In emit-rtl.c. */ extern int max_reg_num (void); diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 6aa8224..3be01cc 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -65,6 +65,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "params.h" #include "sched-int.h" #include "target.h" +#include "timevar.h" +#include "tree-pass.h" /* Define when we want to do count REG_DEAD notes before and after scheduling for sanity checking. We can't do that when conditional execution is used, @@ -2588,3 +2590,95 @@ schedule_insns (FILE *dump_file) sbitmap_free (large_region_blocks); } #endif + +static bool +gate_handle_sched (void) +{ +#ifdef INSN_SCHEDULING + return flag_schedule_insns; +#else + return 0; +#endif +} + +/* Run instruction scheduler. */ +static void +rest_of_handle_sched (void) +{ +#ifdef INSN_SCHEDULING + /* Do control and data sched analysis, + and write some of the results to dump file. */ + + schedule_insns (dump_file); +#endif +} + +static bool +gate_handle_sched2 (void) +{ +#ifdef INSN_SCHEDULING + return optimize > 0 && flag_schedule_insns_after_reload; +#else + return 0; +#endif +} + +/* Run second scheduling pass after reload. */ +static void +rest_of_handle_sched2 (void) +{ +#ifdef INSN_SCHEDULING + /* Do control and data sched analysis again, + and write some more of the results to dump file. */ + + split_all_insns (1); + + if (flag_sched2_use_superblocks || flag_sched2_use_traces) + { + schedule_ebbs (dump_file); + /* No liveness updating code yet, but it should be easy to do. + reg-stack recomputes the liveness when needed for now. */ + count_or_remove_death_notes (NULL, 1); + cleanup_cfg (CLEANUP_EXPENSIVE); + } + else + schedule_insns (dump_file); +#endif +} + +struct tree_opt_pass pass_sched = +{ + "sched1", /* name */ + gate_handle_sched, /* gate */ + rest_of_handle_sched, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_SCHED, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'S' /* letter */ +}; + +struct tree_opt_pass pass_sched2 = +{ + "sched2", /* name */ + gate_handle_sched2, /* gate */ + rest_of_handle_sched2, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_SCHED2, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func | + TODO_ggc_collect, /* todo_flags_finish */ + 'R' /* letter */ +}; + diff --git a/gcc/toplev.c b/gcc/toplev.c index f88b761..294e5b7 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1470,7 +1470,7 @@ general_init (const char *argv0) /* This must be done after add_params but before argument processing. */ init_ggc_heuristics(); - init_tree_optimization_passes (); + init_optimization_passes (); } /* Process the options that have been parsed. */ diff --git a/gcc/toplev.h b/gcc/toplev.h index ddd6b61..48339db 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -69,7 +69,7 @@ extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2); extern void rest_of_decl_compilation (tree, int, int); extern void rest_of_type_compilation (tree, int); extern void tree_rest_of_compilation (tree); -extern void init_tree_optimization_passes (void); +extern void init_optimization_passes (void); extern void finish_optimization_passes (void); extern bool enable_rtl_dump_file (int); diff --git a/gcc/tracer.c b/gcc/tracer.c index 5d3aaf4..a92dcbc 100644 --- a/gcc/tracer.c +++ b/gcc/tracer.c @@ -48,6 +48,7 @@ #include "timevar.h" #include "params.h" #include "coverage.h" +#include "tree-pass.h" static int count_insns (basic_block); static bool ignore_bb_p (basic_block); @@ -365,8 +366,6 @@ tracer (unsigned int flags) if (n_basic_blocks <= 1) return; - timevar_push (TV_TRACER); - cfg_layout_initialize (flags); mark_dfs_back_edges (); if (dump_file) @@ -379,6 +378,39 @@ tracer (unsigned int flags) /* Merge basic blocks in duplicated traces. */ cleanup_cfg (CLEANUP_EXPENSIVE); +} + +static bool +gate_handle_tracer (void) +{ + return (optimize > 0 && flag_tracer); +} - timevar_pop (TV_TRACER); +/* Run tracer. */ +static void +rest_of_handle_tracer (void) +{ + if (dump_file) + dump_flow_info (dump_file); + tracer (0); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); } + +struct tree_opt_pass pass_tracer = +{ + "tracer", /* name */ + gate_handle_tracer, /* gate */ + rest_of_handle_tracer, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRACER, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'T' /* letter */ +}; + diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 23fbf07..3f6592b 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -713,43 +713,6 @@ static struct dump_file_info dump_files[TDI_end] = {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0}, { ".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0, 0}, - - { ".sibling", "rtl-sibling", NULL, TDF_RTL, 0, 1, 'i'}, - { ".eh", "rtl-eh", NULL, TDF_RTL, 0, 2, 'h'}, - { ".jump", "rtl-jump", NULL, TDF_RTL, 0, 3, 'j'}, - { ".cse", "rtl-cse", NULL, TDF_RTL, 0, 4, 's'}, - { ".gcse", "rtl-gcse", NULL, TDF_RTL, 0, 5, 'G'}, - { ".loop", "rtl-loop", NULL, TDF_RTL, 0, 6, 'L'}, - { ".bypass", "rtl-bypass", NULL, TDF_RTL, 0, 7, 'G'}, - { ".cfg", "rtl-cfg", NULL, TDF_RTL, 0, 8, 'f'}, - { ".bp", "rtl-bp", NULL, TDF_RTL, 0, 9, 'b'}, - { ".vpt", "rtl-vpt", NULL, TDF_RTL, 0, 10, 'V'}, - { ".ce1", "rtl-ce1", NULL, TDF_RTL, 0, 11, 'C'}, - { ".tracer", "rtl-tracer", NULL, TDF_RTL, 0, 12, 'T'}, - { ".loop2", "rtl-loop2", NULL, TDF_RTL, 0, 13, 'L'}, - { ".web", "rtl-web", NULL, TDF_RTL, 0, 14, 'Z'}, - { ".cse2", "rtl-cse2", NULL, TDF_RTL, 0, 15, 't'}, - { ".life", "rtl-life", NULL, TDF_RTL, 0, 16, 'f'}, - { ".combine", "rtl-combine", NULL, TDF_RTL, 0, 17, 'c'}, - { ".ce2", "rtl-ce2", NULL, TDF_RTL, 0, 18, 'C'}, - { ".regmove", "rtl-regmove", NULL, TDF_RTL, 0, 19, 'N'}, - { ".sms", "rtl-sms", NULL, TDF_RTL, 0, 20, 'm'}, - { ".sched", "rtl-sched", NULL, TDF_RTL, 0, 21, 'S'}, - { ".lreg", "rtl-lreg", NULL, TDF_RTL, 0, 22, 'l'}, - { ".greg", "rtl-greg", NULL, TDF_RTL, 0, 23, 'g'}, - { ".postreload", "rtl-postreload", NULL, TDF_RTL, 0, 24, 'o'}, - { ".gcse2", "rtl-gcse2", NULL, TDF_RTL, 0, 25, 'J'}, - { ".flow2", "rtl-flow2", NULL, TDF_RTL, 0, 26, 'w'}, - { ".peephole2", "rtl-peephole2", NULL, TDF_RTL, 0, 27, 'z'}, - { ".ce3", "rtl-ce3", NULL, TDF_RTL, 0, 28, 'E'}, - { ".rnreg", "rtl-rnreg", NULL, TDF_RTL, 0, 29, 'n'}, - { ".bbro", "rtl-bbro", NULL, TDF_RTL, 0, 30, 'B'}, - { ".btl", "rtl-btl", NULL, TDF_RTL, 0, 31, 'd'}, - { ".sched2", "rtl-sched2", NULL, TDF_RTL, 0, 32, 'R'}, - { ".stack", "rtl-stack", NULL, TDF_RTL, 0, 33, 'k'}, - { ".vartrack", "rtl-vartrack", NULL, TDF_RTL, 0, 34, 'V'}, - { ".mach", "rtl-mach", NULL, TDF_RTL, 0, 35, 'M'}, - { ".dbr", "rtl-dbr", NULL, TDF_RTL, 0, 36, 'd'} }; /* Dynamically registered tree dump files and switches. */ diff --git a/gcc/tree-dump.h b/gcc/tree-dump.h index c4a102a..bc22693 100644 --- a/gcc/tree-dump.h +++ b/gcc/tree-dump.h @@ -23,6 +23,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #define GCC_TREE_DUMP_H #include "splay-tree.h" +#include "tree-pass.h" + +typedef struct dump_info *dump_info_p; /* Flags used with queue functions. */ #define DUMP_NONE 0 @@ -88,6 +91,7 @@ extern void queue_and_dump_index (dump_info_p, const char *, tree, int); extern void queue_and_dump_type (dump_info_p, tree); extern void dump_function (enum tree_dump_index, tree); extern void dump_function_to_file (tree, FILE *, int); +extern int dump_flag (dump_info_p, int, tree); extern unsigned int dump_register (const char *, const char *, const char *, int, unsigned int, int); diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index b8a50c7..4b23a82 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -50,12 +50,6 @@ Boston, MA 02110-1301, USA. */ #include "cfgloop.h" #include "except.h" -/* Global variables used to communicate with passes. */ -int dump_flags; -bool in_gimple_form; - -/* The root of the compilation pass tree, once constructed. */ -static struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; /* Gate: execute, or not, all of the non-trivial optimizations. */ @@ -67,7 +61,7 @@ gate_all_optimizations (void) && !(errorcount || sorrycount)); } -static struct tree_opt_pass pass_all_optimizations = +struct tree_opt_pass pass_all_optimizations = { NULL, /* name */ gate_all_optimizations, /* gate */ @@ -84,7 +78,7 @@ static struct tree_opt_pass pass_all_optimizations = 0 /* letter */ }; -static struct tree_opt_pass pass_early_local_passes = +struct tree_opt_pass pass_early_local_passes = { NULL, /* name */ gate_all_optimizations, /* gate */ @@ -112,7 +106,7 @@ execute_cleanup_cfg_pre_ipa (void) cleanup_tree_cfg (); } -static struct tree_opt_pass pass_cleanup_cfg = +struct tree_opt_pass pass_cleanup_cfg = { "cleanup_cfg", /* name */ NULL, /* gate */ @@ -143,7 +137,7 @@ execute_cleanup_cfg_post_optimizing (void) group_case_labels (); } -static struct tree_opt_pass pass_cleanup_cfg_post_optimizing = +struct tree_opt_pass pass_cleanup_cfg_post_optimizing = { "final_cleanup", /* name */ NULL, /* gate */ @@ -176,7 +170,7 @@ execute_free_datastructures (void) delete_tree_ssa (); } -static struct tree_opt_pass pass_free_datastructures = +struct tree_opt_pass pass_free_datastructures = { NULL, /* name */ NULL, /* gate */ @@ -216,7 +210,7 @@ execute_free_cfg_annotations (void) delete_tree_cfg_annotations (); } -static struct tree_opt_pass pass_free_cfg_annotations = +struct tree_opt_pass pass_free_cfg_annotations = { NULL, /* name */ NULL, /* gate */ @@ -261,7 +255,7 @@ execute_fixup_cfg (void) cleanup_tree_cfg (); } -static struct tree_opt_pass pass_fixup_cfg = +struct tree_opt_pass pass_fixup_cfg = { NULL, /* name */ NULL, /* gate */ @@ -288,7 +282,7 @@ execute_init_datastructures (void) init_tree_ssa (); } -static struct tree_opt_pass pass_init_datastructures = +struct tree_opt_pass pass_init_datastructures = { NULL, /* name */ NULL, /* gate */ @@ -305,484 +299,7 @@ static struct tree_opt_pass pass_init_datastructures = 0 /* letter */ }; -/* Iterate over the pass tree allocating dump file numbers. We want - to do this depth first, and independent of whether the pass is - enabled or not. */ - -static void -register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n) -{ - char *dot_name, *flag_name, *glob_name; - char num[10]; - - /* See below in next_pass_1. */ - num[0] = '\0'; - if (pass->static_pass_number != -1) - sprintf (num, "%d", ((int) pass->static_pass_number < 0 - ? 1 : pass->static_pass_number)); - - dot_name = concat (".", pass->name, num, NULL); - if (ipa) - { - flag_name = concat ("ipa-", pass->name, num, NULL); - glob_name = concat ("ipa-", pass->name, NULL); - /* First IPA dump is cgraph that is dumped via separate channels. */ - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_IPA, n + 1, 0); - } - else if (pass->properties_provided & PROP_trees) - { - flag_name = concat ("tree-", pass->name, num, NULL); - glob_name = concat ("tree-", pass->name, NULL); - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_TREE, n + TDI_tree_all, 0); - } - else - { - flag_name = concat ("rtl-", pass->name, num, NULL); - glob_name = concat ("rtl-", pass->name, NULL); - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_RTL, n, pass->letter); - } -} - -static int -register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties) -{ - static int n = 0; - do - { - int new_properties; - int pass_number; - - pass->properties_required = properties; - new_properties = - (properties | pass->properties_provided) & ~pass->properties_destroyed; - - /* Reset the counter when we reach RTL-based passes. */ - if ((pass->properties_provided ^ pass->properties_required) & PROP_rtl) - n = 0; - - pass_number = n; - if (pass->name) - n++; - - if (pass->sub) - new_properties = register_dump_files (pass->sub, false, new_properties); - - /* If we have a gate, combine the properties that we could have with - and without the pass being examined. */ - if (pass->gate) - properties &= new_properties; - else - properties = new_properties; - - pass->properties_provided = properties; - if (pass->name) - register_one_dump_file (pass, ipa, pass_number); - - pass = pass->next; - } - while (pass); - - return properties; -} - -/* Add a pass to the pass list. Duplicate the pass if it's already - in the list. */ - -static struct tree_opt_pass ** -next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass) -{ - - /* A nonzero static_pass_number indicates that the - pass is already in the list. */ - if (pass->static_pass_number) - { - struct tree_opt_pass *new; - - new = xmalloc (sizeof (*new)); - memcpy (new, pass, sizeof (*new)); - - /* Indicate to register_dump_files that this pass has duplicates, - and so it should rename the dump file. The first instance will - be -1, and be number of duplicates = -static_pass_number - 1. - Subsequent instances will be > 0 and just the duplicate number. */ - if (pass->name) - { - pass->static_pass_number -= 1; - new->static_pass_number = -pass->static_pass_number; - } - - *list = new; - } - else - { - pass->static_pass_number = -1; - *list = pass; - } - - return &(*list)->next; - -} - -/* Construct the pass tree. */ - -void -init_tree_optimization_passes (void) -{ - struct tree_opt_pass **p; - -#define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS)) - /* Interprocedural optimization passes. */ - p = &all_ipa_passes; - NEXT_PASS (pass_early_ipa_inline); - NEXT_PASS (pass_early_local_passes); - NEXT_PASS (pass_ipa_inline); - *p = NULL; - - /* All passes needed to lower the function into shape optimizers can operate - on. These passes are performed before interprocedural passes, unlike rest - of local passes (all_passes). */ - p = &all_lowering_passes; - NEXT_PASS (pass_remove_useless_stmts); - NEXT_PASS (pass_mudflap_1); - NEXT_PASS (pass_lower_cf); - NEXT_PASS (pass_lower_eh); - NEXT_PASS (pass_build_cfg); - NEXT_PASS (pass_lower_complex_O0); - NEXT_PASS (pass_lower_vector); - NEXT_PASS (pass_warn_function_return); - NEXT_PASS (pass_early_tree_profile); - *p = NULL; - - p = &pass_early_local_passes.sub; - NEXT_PASS (pass_tree_profile); - NEXT_PASS (pass_cleanup_cfg); - NEXT_PASS (pass_rebuild_cgraph_edges); - *p = NULL; - - p = &all_passes; - NEXT_PASS (pass_fixup_cfg); - NEXT_PASS (pass_init_datastructures); - NEXT_PASS (pass_all_optimizations); - NEXT_PASS (pass_warn_function_noreturn); - NEXT_PASS (pass_mudflap_2); - NEXT_PASS (pass_free_datastructures); - NEXT_PASS (pass_free_cfg_annotations); - NEXT_PASS (pass_expand); - NEXT_PASS (pass_rest_of_compilation); - *p = NULL; - - p = &pass_all_optimizations.sub; - NEXT_PASS (pass_referenced_vars); - NEXT_PASS (pass_create_structure_vars); - NEXT_PASS (pass_build_ssa); - NEXT_PASS (pass_build_pta); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_return_slot); - NEXT_PASS (pass_del_pta); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_early_warn_uninitialized); - - /* Initial scalar cleanups. */ - NEXT_PASS (pass_ccp); - NEXT_PASS (pass_fre); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_vrp); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_merge_phi); - NEXT_PASS (pass_dominator); - - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_build_pta); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_del_pta); - NEXT_PASS (pass_tail_recursion); - NEXT_PASS (pass_profile); - NEXT_PASS (pass_ch); - NEXT_PASS (pass_stdarg); - NEXT_PASS (pass_lower_complex); - NEXT_PASS (pass_sra); - /* FIXME: SRA may generate arbitrary gimple code, exposing new - aliased and call-clobbered variables. As mentioned below, - pass_may_alias should be a TODO item. */ - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_dse); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_object_sizes); - NEXT_PASS (pass_store_ccp); - NEXT_PASS (pass_store_copy_prop); - NEXT_PASS (pass_fold_builtins); - /* FIXME: May alias should a TODO but for 4.0.0, - we add may_alias right after fold builtins - which can create arbitrary GIMPLE. */ - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_cse_reciprocals); - NEXT_PASS (pass_split_crit_edges); - NEXT_PASS (pass_reassoc); - NEXT_PASS (pass_pre); - NEXT_PASS (pass_sink_code); - NEXT_PASS (pass_loop); - NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_cd_dce); - /* FIXME: If DCE is not run before checking for uninitialized uses, - we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c). - However, this also causes us to misdiagnose cases that should be - real warnings (e.g., testsuite/gcc.dg/pr18501.c). - - To fix the false positives in uninit-5.c, we would have to - account for the predicates protecting the set and the use of each - variable. Using a representation like Gated Single Assignment - may help. */ - NEXT_PASS (pass_late_warn_uninitialized); - NEXT_PASS (pass_dse); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_tail_calls); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_uncprop); - NEXT_PASS (pass_del_ssa); - NEXT_PASS (pass_nrv); - NEXT_PASS (pass_remove_useless_vars); - NEXT_PASS (pass_mark_used_blocks); - NEXT_PASS (pass_cleanup_cfg_post_optimizing); - *p = NULL; - - p = &pass_loop.sub; - NEXT_PASS (pass_loop_init); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_lim); - NEXT_PASS (pass_unswitch); - NEXT_PASS (pass_scev_cprop); - NEXT_PASS (pass_record_bounds); - NEXT_PASS (pass_linear_transform); - NEXT_PASS (pass_iv_canon); - NEXT_PASS (pass_if_conversion); - NEXT_PASS (pass_vectorize); - /* NEXT_PASS (pass_may_alias) cannot be done again because the - vectorizer creates alias relations that are not supported by - pass_may_alias. */ - NEXT_PASS (pass_lower_vector_ssa); - NEXT_PASS (pass_complete_unroll); - NEXT_PASS (pass_iv_optimize); - NEXT_PASS (pass_loop_done); - *p = NULL; - -#undef NEXT_PASS - - register_dump_files (all_lowering_passes, false, PROP_gimple_any); - register_dump_files (all_passes, false, PROP_gimple_any - | PROP_gimple_lcf - | PROP_gimple_leh - | PROP_cfg); - register_dump_files (all_ipa_passes, true, PROP_gimple_any - | PROP_gimple_lcf - | PROP_gimple_leh - | PROP_cfg); -} - -static unsigned int last_verified; - -static void -execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) -{ - int properties - = use_required ? pass->properties_required : pass->properties_provided; - -#if defined ENABLE_CHECKING - if (need_ssa_update_p ()) - gcc_assert (flags & TODO_update_ssa_any); -#endif - - if (flags & TODO_update_ssa_any) - { - unsigned update_flags = flags & TODO_update_ssa_any; - update_ssa (update_flags); - } - - if (flags & TODO_cleanup_cfg) - { - if (current_loops) - cleanup_tree_cfg_loop (); - else - cleanup_tree_cfg (); - } - - if ((flags & TODO_dump_func) - && dump_file && current_function_decl) - { - if (properties & PROP_trees) - dump_function_to_file (current_function_decl, - dump_file, dump_flags); - else if (properties & PROP_cfg) - print_rtl_with_bb (dump_file, get_insns ()); - else - print_rtl (dump_file, get_insns ()); - - /* Flush the file. If verification fails, we won't be able to - close the file before dieing. */ - fflush (dump_file); - } - if ((flags & TODO_dump_cgraph) - && dump_file && !current_function_decl) - { - dump_cgraph (dump_file); - /* Flush the file. If verification fails, we won't be able to - close the file before aborting. */ - fflush (dump_file); - } - - if (flags & TODO_ggc_collect) - { - ggc_collect (); - } - -#if defined ENABLE_CHECKING - if ((pass->properties_required & PROP_ssa) - && !(pass->properties_destroyed & PROP_ssa)) - verify_ssa (true); - if (flags & TODO_verify_flow) - verify_flow_info (); - if (flags & TODO_verify_stmts) - verify_stmts (); - if (flags & TODO_verify_loops) - verify_loop_closed_ssa (); -#endif -} - -static bool -execute_one_pass (struct tree_opt_pass *pass) -{ - unsigned int todo; - - /* See if we're supposed to run this pass. */ - if (pass->gate && !pass->gate ()) - return false; - - /* Note that the folders should only create gimple expressions. - This is a hack until the new folder is ready. */ - in_gimple_form = (pass->properties_provided & PROP_trees) != 0; - - /* Run pre-pass verification. */ - todo = pass->todo_flags_start & ~last_verified; - if (todo) - execute_todo (pass, todo, true); - - /* If a dump file name is present, open it if enabled. */ - if (pass->static_pass_number != -1) - { - bool initializing_dump = !dump_initialized_p (pass->static_pass_number); - dump_file_name = get_dump_file_name (pass->static_pass_number); - dump_file = dump_begin (pass->static_pass_number, &dump_flags); - if (dump_file && current_function_decl) - { - const char *dname, *aname; - dname = lang_hooks.decl_printable_name (current_function_decl, 2); - aname = (IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (current_function_decl))); - fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, - cfun->function_frequency == FUNCTION_FREQUENCY_HOT - ? " (hot)" - : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED - ? " (unlikely executed)" - : ""); - } - - if (initializing_dump - && graph_dump_format != no_graph - && (pass->properties_provided & (PROP_cfg | PROP_rtl)) - == (PROP_cfg | PROP_rtl)) - clean_graph_dump_file (dump_file_name); - } - - /* If a timevar is present, start it. */ - if (pass->tv_id) - timevar_push (pass->tv_id); - - /* Do it! */ - if (pass->execute) - pass->execute (); - - /* Stop timevar. */ - if (pass->tv_id) - timevar_pop (pass->tv_id); - - if (dump_file - && (pass->properties_provided & (PROP_cfg | PROP_rtl)) - == (PROP_cfg | PROP_rtl)) - print_rtl_with_bb (dump_file, get_insns ()); - - /* Run post-pass cleanup and verification. */ - todo = pass->todo_flags_finish; - last_verified = todo & TODO_verify_all; - if (todo) - execute_todo (pass, todo, false); - - /* Flush and close dump file. */ - if (dump_file_name) - { - free ((char *) dump_file_name); - dump_file_name = NULL; - } - if (dump_file) - { - dump_end (pass->static_pass_number, dump_file); - dump_file = NULL; - } - - return true; -} - -static void -execute_pass_list (struct tree_opt_pass *pass) -{ - do - { - if (execute_one_pass (pass) && pass->sub) - execute_pass_list (pass->sub); - pass = pass->next; - } - while (pass); -} - -/* Same as execute_pass_list but assume that subpasses of IPA passes - are local passes. */ -static void -execute_ipa_pass_list (struct tree_opt_pass *pass) -{ - do - { - if (execute_one_pass (pass) && pass->sub) - { - struct cgraph_node *node; - for (node = cgraph_nodes; node; node = node->next) - if (node->analyzed) - { - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - current_function_decl = node->decl; - execute_pass_list (pass->sub); - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - current_function_decl = NULL; - pop_cfun (); - ggc_collect (); - } - } - pass = pass->next; - } - while (pass); -} - + void tree_lowering_passes (tree fn) { @@ -800,18 +317,6 @@ tree_lowering_passes (tree fn) pop_cfun (); } -/* Execute all IPA passes. */ -void -ipa_passes (void) -{ - cfun = NULL; - tree_register_cfg_hooks (); - bitmap_obstack_initialize (NULL); - execute_ipa_pass_list (all_ipa_passes); - bitmap_obstack_release (NULL); -} - - /* Update recursively all inlined_to pointers of functions inlined into NODE to INLINED_TO. */ static void diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index e6acea4..80f4a05 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -23,6 +23,59 @@ Boston, MA 02110-1301, USA. */ #ifndef GCC_TREE_PASS_H #define GCC_TREE_PASS_H 1 +/* In tree-dump.c */ + +/* Different tree dump places. When you add new tree dump places, + extend the DUMP_FILES array in tree-dump.c. */ +enum tree_dump_index +{ + TDI_none, /* No dump */ + TDI_tu, /* dump the whole translation unit. */ + TDI_class, /* dump class hierarchy. */ + TDI_original, /* dump each function before optimizing it */ + TDI_generic, /* dump each function after genericizing it */ + TDI_nested, /* dump each function after unnesting it */ + TDI_inlined, /* dump each function after inlining + within it. */ + TDI_vcg, /* create a VCG graph file for each + function's flowgraph. */ + TDI_tree_all, /* enable all the GENERIC/GIMPLE dumps. */ + TDI_rtl_all, /* enable all the RTL dumps. */ + TDI_ipa_all, /* enable all the IPA dumps. */ + + TDI_cgraph, /* dump function call graph. */ + TDI_end +}; + +/* Bit masks to control dumping. Not all values are applicable to + all dumps. Add new ones at the end. When you define new + values, extend the DUMP_OPTIONS array in tree-dump.c */ +#define TDF_ADDRESS (1 << 0) /* dump node addresses */ +#define TDF_SLIM (1 << 1) /* don't go wild following links */ +#define TDF_RAW (1 << 2) /* don't unparse the function */ +#define TDF_DETAILS (1 << 3) /* show more detailed info about + each pass */ +#define TDF_STATS (1 << 4) /* dump various statistics about + each pass */ +#define TDF_BLOCKS (1 << 5) /* display basic block boundaries */ +#define TDF_VOPS (1 << 6) /* display virtual operands */ +#define TDF_LINENO (1 << 7) /* display statement line numbers */ +#define TDF_UID (1 << 8) /* display decl UIDs */ + +#define TDF_TREE (1 << 9) /* is a tree dump */ +#define TDF_RTL (1 << 10) /* is a RTL dump */ +#define TDF_IPA (1 << 11) /* is an IPA dump */ +#define TDF_STMTADDR (1 << 12) /* Address of stmt. */ + +extern char *get_dump_file_name (enum tree_dump_index); +extern int dump_enabled_p (enum tree_dump_index); +extern int dump_initialized_p (enum tree_dump_index); +extern FILE *dump_begin (enum tree_dump_index, int *); +extern void dump_end (enum tree_dump_index, FILE *); +extern void dump_node (tree, int, FILE *); +extern int dump_switch_p (const char *); +extern const char *dump_flag_name (enum tree_dump_index); + /* Global variables used to communicate with passes. */ extern FILE *dump_file; extern int dump_flags; @@ -154,7 +207,6 @@ struct dump_file_info #define TODO_verify_all \ (TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts) -extern void ipa_passes (void); extern void tree_lowering_passes (tree decl); extern struct tree_opt_pass pass_mudflap_1; @@ -165,6 +217,7 @@ extern struct tree_opt_pass pass_lower_eh; extern struct tree_opt_pass pass_build_cfg; extern struct tree_opt_pass pass_tree_profile; extern struct tree_opt_pass pass_early_tree_profile; +extern struct tree_opt_pass pass_cleanup_cfg; extern struct tree_opt_pass pass_referenced_vars; extern struct tree_opt_pass pass_sra; extern struct tree_opt_pass pass_tail_recursion; @@ -233,5 +286,84 @@ extern struct tree_opt_pass pass_rebuild_cgraph_edges; /* IPA Passes */ extern struct tree_opt_pass pass_ipa_inline; extern struct tree_opt_pass pass_early_ipa_inline; +extern struct tree_opt_pass pass_early_local_passes; + +extern struct tree_opt_pass pass_all_optimizations; +extern struct tree_opt_pass pass_cleanup_cfg_post_optimizing; +extern struct tree_opt_pass pass_free_cfg_annotations; +extern struct tree_opt_pass pass_free_datastructures; +extern struct tree_opt_pass pass_init_datastructures; +extern struct tree_opt_pass pass_fixup_cfg; + +extern struct tree_opt_pass pass_remove_unnecessary_notes; +extern struct tree_opt_pass pass_init_function; +extern struct tree_opt_pass pass_jump; +extern struct tree_opt_pass pass_insn_locators_initialize; +extern struct tree_opt_pass pass_rtl_eh; +extern struct tree_opt_pass pass_initial_value_sets; +extern struct tree_opt_pass pass_unshare_all_rtl; +extern struct tree_opt_pass pass_instantiate_virtual_regs; +extern struct tree_opt_pass pass_jump2; +extern struct tree_opt_pass pass_cse; +extern struct tree_opt_pass pass_gcse; +extern struct tree_opt_pass pass_loop_optimize; +extern struct tree_opt_pass pass_jump_bypass; +extern struct tree_opt_pass pass_cfg; +extern struct tree_opt_pass pass_profiling; +extern struct tree_opt_pass pass_rtl_ifcvt; +extern struct tree_opt_pass pass_tracer; +extern struct tree_opt_pass pass_loop2; +extern struct tree_opt_pass pass_web; +extern struct tree_opt_pass pass_cse2; +extern struct tree_opt_pass pass_life; +extern struct tree_opt_pass pass_combine; +extern struct tree_opt_pass pass_if_after_combine; +extern struct tree_opt_pass pass_partition_blocks; +extern struct tree_opt_pass pass_partition_blocks; +extern struct tree_opt_pass pass_regmove; +extern struct tree_opt_pass pass_split_all_insns; +extern struct tree_opt_pass pass_mode_switching; +extern struct tree_opt_pass pass_recompute_reg_usage; +extern struct tree_opt_pass pass_sms; +extern struct tree_opt_pass pass_sched; +extern struct tree_opt_pass pass_local_alloc; +extern struct tree_opt_pass pass_global_alloc; +extern struct tree_opt_pass pass_postreload; +extern struct tree_opt_pass pass_clean_state; +extern struct tree_opt_pass pass_branch_prob; +extern struct tree_opt_pass pass_value_profile_transformations; +extern struct tree_opt_pass pass_remove_death_notes; +extern struct tree_opt_pass pass_postreload_cse; +extern struct tree_opt_pass pass_gcse2; +extern struct tree_opt_pass pass_flow2; +extern struct tree_opt_pass pass_stack_adjustments; +extern struct tree_opt_pass pass_peephole2; +extern struct tree_opt_pass pass_if_after_reload; +extern struct tree_opt_pass pass_regrename; +extern struct tree_opt_pass pass_reorder_blocks; +extern struct tree_opt_pass pass_branch_target_load_optimize; +extern struct tree_opt_pass pass_leaf_regs; +extern struct tree_opt_pass pass_sched2; +extern struct tree_opt_pass pass_stack_regs; +extern struct tree_opt_pass pass_compute_alignments; +extern struct tree_opt_pass pass_duplicate_computed_gotos; +extern struct tree_opt_pass pass_variable_tracking; +extern struct tree_opt_pass pass_free_cfg; +extern struct tree_opt_pass pass_machine_reorg; +extern struct tree_opt_pass pass_purge_lineno_notes; +extern struct tree_opt_pass pass_cleanup_barriers; +extern struct tree_opt_pass pass_delay_slots; +extern struct tree_opt_pass pass_split_for_shorten_branches; +extern struct tree_opt_pass pass_split_before_regstack; +extern struct tree_opt_pass pass_convert_to_eh_region_ranges; +extern struct tree_opt_pass pass_shorten_branches; +extern struct tree_opt_pass pass_set_nothrow_function_flags; +extern struct tree_opt_pass pass_final; + +/* The root of the compilation pass tree, once constructed. */ +extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; + +extern void execute_pass_list (struct tree_opt_pass *); +extern void execute_ipa_pass_list (struct tree_opt_pass *); #endif /* GCC_TREE_PASS_H */ diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 4d3719b..17de6f3 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "langhooks.h" #include "tree-iterator.h" #include "tree-chrec.h" +#include "tree-pass.h" /* Local functions, macros and variables. */ static int op_prio (tree); @@ -3890,100 +3890,6 @@ typedef tree (*walk_tree_fn) (tree *, int *, void *); extern tree walk_tree (tree*, walk_tree_fn, void*, struct pointer_set_t*); extern tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*); -/* In tree-dump.c */ - -/* Different tree dump places. When you add new tree dump places, - extend the DUMP_FILES array in tree-dump.c. */ -enum tree_dump_index -{ - TDI_none, /* No dump */ - TDI_tu, /* dump the whole translation unit. */ - TDI_class, /* dump class hierarchy. */ - TDI_original, /* dump each function before optimizing it */ - TDI_generic, /* dump each function after genericizing it */ - TDI_nested, /* dump each function after unnesting it */ - TDI_inlined, /* dump each function after inlining - within it. */ - TDI_vcg, /* create a VCG graph file for each - function's flowgraph. */ - TDI_tree_all, /* enable all the GENERIC/GIMPLE dumps. */ - TDI_rtl_all, /* enable all the RTL dumps. */ - TDI_ipa_all, /* enable all the IPA dumps. */ - - TDI_cgraph, /* dump function call graph. */ - - DFI_MIN, /* For now, RTL dumps are placed here. */ - DFI_sibling = DFI_MIN, - DFI_eh, - DFI_jump, - DFI_cse, - DFI_gcse, - DFI_loop, - DFI_bypass, - DFI_cfg, - DFI_bp, - DFI_vpt, - DFI_ce1, - DFI_tracer, - DFI_loop2, - DFI_web, - DFI_cse2, - DFI_life, - DFI_combine, - DFI_ce2, - DFI_regmove, - DFI_sms, - DFI_sched, - DFI_lreg, - DFI_greg, - DFI_postreload, - DFI_gcse2, - DFI_flow2, - DFI_peephole2, - DFI_ce3, - DFI_rnreg, - DFI_bbro, - DFI_branch_target_load, - DFI_sched2, - DFI_stack, - DFI_vartrack, - DFI_mach, - DFI_dbr, - - TDI_end -}; - -/* Bit masks to control dumping. Not all values are applicable to - all dumps. Add new ones at the end. When you define new - values, extend the DUMP_OPTIONS array in tree-dump.c */ -#define TDF_ADDRESS (1 << 0) /* dump node addresses */ -#define TDF_SLIM (1 << 1) /* don't go wild following links */ -#define TDF_RAW (1 << 2) /* don't unparse the function */ -#define TDF_DETAILS (1 << 3) /* show more detailed info about - each pass */ -#define TDF_STATS (1 << 4) /* dump various statistics about - each pass */ -#define TDF_BLOCKS (1 << 5) /* display basic block boundaries */ -#define TDF_VOPS (1 << 6) /* display virtual operands */ -#define TDF_LINENO (1 << 7) /* display statement line numbers */ -#define TDF_UID (1 << 8) /* display decl UIDs */ - -#define TDF_TREE (1 << 9) /* is a tree dump */ -#define TDF_RTL (1 << 10) /* is a RTL dump */ -#define TDF_IPA (1 << 11) /* is an IPA dump */ -#define TDF_STMTADDR (1 << 12) /* Address of stmt. */ - -typedef struct dump_info *dump_info_p; - -extern char *get_dump_file_name (enum tree_dump_index); -extern int dump_flag (dump_info_p, int, tree); -extern int dump_enabled_p (enum tree_dump_index); -extern int dump_initialized_p (enum tree_dump_index); -extern FILE *dump_begin (enum tree_dump_index, int *); -extern void dump_end (enum tree_dump_index, FILE *); -extern void dump_node (tree, int, FILE *); -extern int dump_switch_p (const char *); -extern const char *dump_flag_name (enum tree_dump_index); /* Assign the RTX to declaration. */ extern void set_decl_rtl (tree, rtx); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 5c06c15..f436b4a 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -40,6 +40,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "coverage.h" #include "tree.h" #include "gcov-io.h" +#include "timevar.h" +#include "tree-pass.h" static struct value_prof_hooks *value_prof_hooks; @@ -1798,3 +1800,40 @@ value_profile_transformations (void) VEC_free (histogram_value, heap, static_values); return retval; } + +static bool +gate_handle_value_profile_transformations (void) +{ + return flag_branch_probabilities + && flag_profile_values + && !flag_tree_based_profiling + && (flag_value_profile_transformations + || flag_speculative_prefetching); +} + + +/* Do optimizations based on expression value profiles. */ +static void +rest_of_handle_value_profile_transformations (void) +{ + if (value_profile_transformations ()) + cleanup_cfg (CLEANUP_EXPENSIVE); +} + +struct tree_opt_pass pass_value_profile_transformations = +{ + "vpt", /* name */ + gate_handle_value_profile_transformations, /* gate */ + rest_of_handle_value_profile_transformations, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_VPT, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'V' /* letter */ +}; + diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 83bfdb1..92976dc 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -104,6 +104,8 @@ #include "hashtab.h" #include "regs.h" #include "expr.h" +#include "timevar.h" +#include "tree-pass.h" /* Type of micro operation. */ enum micro_operation_type @@ -2809,3 +2811,29 @@ variable_tracking_main (void) vt_finalize (); } + +static bool +gate_handle_var_tracking (void) +{ + return (flag_var_tracking); +} + + + +struct tree_opt_pass pass_variable_tracking = +{ + "vartrack", /* name */ + gate_handle_var_tracking, /* gate */ + variable_tracking_main, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_VAR_TRACKING, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'V' /* letter */ +}; + @@ -56,6 +56,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "output.h" #include "df.h" #include "function.h" +#include "timevar.h" +#include "tree-pass.h" /* This entry is allocated for each reference in the insn stream. */ @@ -271,3 +273,36 @@ web_main (void) free (used); df_finish (df); } + +static bool +gate_handle_web (void) +{ + return (optimize > 0 && flag_web); +} + +static void +rest_of_handle_web (void) +{ + web_main (); + delete_trivially_dead_insns (get_insns (), max_reg_num ()); + cleanup_cfg (CLEANUP_EXPENSIVE); + reg_scan (get_insns (), max_reg_num ()); +} + +struct tree_opt_pass pass_web = +{ + "web", /* name */ + gate_handle_web, /* gate */ + rest_of_handle_web, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_WEB, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + 'Z' /* letter */ +}; + |