diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-04-22 10:21:45 +0000 |
---|---|---|
committer | <> | 2015-04-25 21:44:09 +0000 |
commit | f80b5ea1605c9f9408c5aa386ba71c16d918ebbf (patch) | |
tree | bb7eafaa81fc4b8c5c215bc08d517fd158db234a /gcc/loop-init.c | |
parent | c27a97d04853380f1e80525391b3f0d156ed4c84 (diff) | |
download | gcc-tarball-f80b5ea1605c9f9408c5aa386ba71c16d918ebbf.tar.gz |
Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-5.1.0.tar.bz2.gcc-5.1.0
Diffstat (limited to 'gcc/loop-init.c')
-rw-r--r-- | gcc/loop-init.c | 326 |
1 files changed, 146 insertions, 180 deletions
diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 4cc561c2e7..c13d360fb5 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -1,5 +1,5 @@ /* Loop optimizer initialization routines and RTL loop optimization passes. - Copyright (C) 2002-2014 Free Software Foundation, Inc. + Copyright (C) 2002-2015 Free Software Foundation, Inc. This file is part of GCC. @@ -22,9 +22,25 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" +#include "hash-set.h" +#include "machmode.h" +#include "vec.h" +#include "double-int.h" +#include "input.h" +#include "alias.h" +#include "symtab.h" +#include "wide-int.h" +#include "inchash.h" #include "tree.h" #include "regs.h" #include "obstack.h" +#include "predict.h" +#include "hard-reg-set.h" +#include "input.h" +#include "function.h" +#include "dominance.h" +#include "cfg.h" +#include "cfgcleanup.h" #include "basic-block.h" #include "cfgloop.h" #include "tree-pass.h" @@ -32,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "ggc.h" #include "tree-ssa-loop-niter.h" +#include "loop-unroll.h" /* Apply FLAGS to the loop state. */ @@ -245,6 +262,10 @@ fix_loop_structure (bitmap changed_bbs) } /* Remove the loop. */ + if (loop->header) + loop->former_header = loop->header; + else + gcc_assert (loop->former_header != NULL); loop->header = NULL; flow_loop_tree_node_remove (loop); } @@ -272,6 +293,33 @@ fix_loop_structure (bitmap changed_bbs) FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop) if (loop && loop->header == NULL) { + if (dump_file + && ((unsigned) loop->former_header->index + < basic_block_info_for_fn (cfun)->length ())) + { + basic_block former_header + = BASIC_BLOCK_FOR_FN (cfun, loop->former_header->index); + /* If the old header still exists we want to check if the + original loop is re-discovered or the old header is now + part of a newly discovered loop. + In both cases we should have avoided removing the loop. */ + if (former_header == loop->former_header) + { + if (former_header->loop_father->header == former_header) + fprintf (dump_file, "fix_loop_structure: rediscovered " + "removed loop %d as loop %d with old header %d\n", + loop->num, former_header->loop_father->num, + former_header->index); + else if ((unsigned) former_header->loop_father->num + >= old_nloops) + fprintf (dump_file, "fix_loop_structure: header %d of " + "removed loop %d is part of the newly " + "discovered loop %d with header %d\n", + former_header->index, loop->num, + former_header->loop_father->num, + former_header->loop_father->header->index); + } + } (*get_loops (cfun))[i] = NULL; flow_loop_free (loop); } @@ -290,31 +338,8 @@ fix_loop_structure (bitmap changed_bbs) return number_of_loops (cfun) - old_nloops; } -/* Gate for the RTL loop superpass. The actual passes are subpasses. - See passes.c for more on that. */ - -static bool -gate_handle_loop2 (void) -{ - if (optimize > 0 - && (flag_move_loop_invariants - || flag_unswitch_loops - || flag_peel_loops - || flag_unroll_loops -#ifdef HAVE_doloop_end - || (flag_branch_on_count_reg && HAVE_doloop_end) -#endif - )) - return true; - else - { - /* No longer preserve loops, remove them now. */ - cfun->curr_properties &= ~PROP_loops; - if (current_loops) - loop_optimizer_finalize (); - return false; - } -} +/* The RTL loop superpass. The actual passes are subpasses. See passes.c for + more on that. */ namespace { @@ -323,8 +348,6 @@ const pass_data pass_data_loop2 = RTL_PASS, /* type */ "loop2", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - true, /* has_gate */ - false, /* has_execute */ TV_LOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ @@ -341,10 +364,32 @@ public: {} /* opt_pass methods: */ - bool gate () { return gate_handle_loop2 (); } + virtual bool gate (function *); }; // class pass_loop2 +bool +pass_loop2::gate (function *fun) +{ + if (optimize > 0 + && (flag_move_loop_invariants + || flag_unswitch_loops + || flag_unroll_loops +#ifdef HAVE_doloop_end + || (flag_branch_on_count_reg && HAVE_doloop_end) +#endif + )) + return true; + else + { + /* No longer preserve loops, remove them now. */ + fun->curr_properties &= ~PROP_loops; + if (current_loops) + loop_optimizer_finalize (); + return false; + } +} + } // anon namespace rtl_opt_pass * @@ -377,14 +422,12 @@ const pass_data pass_data_rtl_loop_init = RTL_PASS, /* type */ "loop2_init", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - false, /* has_gate */ - true, /* has_execute */ TV_LOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_verify_rtl_sharing, /* todo_flags_finish */ + 0, /* todo_flags_finish */ }; class pass_rtl_loop_init : public rtl_opt_pass @@ -395,7 +438,7 @@ public: {} /* opt_pass methods: */ - unsigned int execute () { return rtl_loop_init (); } + virtual unsigned int execute (function *) { return rtl_loop_init (); } }; // class pass_rtl_loop_init @@ -410,24 +453,6 @@ make_pass_rtl_loop_init (gcc::context *ctxt) /* Finalization of the RTL loop passes. */ -static unsigned int -rtl_loop_done (void) -{ - /* No longer preserve loops, remove them now. */ - cfun->curr_properties &= ~PROP_loops; - loop_optimizer_finalize (); - free_dominance_info (CDI_DOMINATORS); - - cleanup_cfg (0); - if (dump_file) - { - dump_reg_info (dump_file); - dump_flow_info (dump_file, dump_flags); - } - - return 0; -} - namespace { const pass_data pass_data_rtl_loop_done = @@ -435,14 +460,12 @@ const pass_data pass_data_rtl_loop_done = RTL_PASS, /* type */ "loop2_done", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - false, /* has_gate */ - true, /* has_execute */ TV_LOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ PROP_loops, /* properties_destroyed */ 0, /* todo_flags_start */ - ( TODO_verify_flow | TODO_verify_rtl_sharing ), /* todo_flags_finish */ + 0, /* todo_flags_finish */ }; class pass_rtl_loop_done : public rtl_opt_pass @@ -453,10 +476,28 @@ public: {} /* opt_pass methods: */ - unsigned int execute () { return rtl_loop_done (); } + virtual unsigned int execute (function *); }; // class pass_rtl_loop_done +unsigned int +pass_rtl_loop_done::execute (function *fun) +{ + /* No longer preserve loops, remove them now. */ + fun->curr_properties &= ~PROP_loops; + loop_optimizer_finalize (); + free_dominance_info (CDI_DOMINATORS); + + cleanup_cfg (0); + if (dump_file) + { + dump_reg_info (dump_file); + dump_flow_info (dump_file, dump_flags); + } + + return 0; +} + } // anon namespace rtl_opt_pass * @@ -467,19 +508,6 @@ make_pass_rtl_loop_done (gcc::context *ctxt) /* Loop invariant code motion. */ -static bool -gate_rtl_move_loop_invariants (void) -{ - return flag_move_loop_invariants; -} - -static unsigned int -rtl_move_loop_invariants (void) -{ - if (number_of_loops (cfun) > 1) - move_loop_invariants (); - return 0; -} namespace { @@ -488,15 +516,12 @@ const pass_data pass_data_rtl_move_loop_invariants = RTL_PASS, /* type */ "loop2_invariant", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ TV_LOOP_MOVE_INVARIANTS, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - ( TODO_df_verify | TODO_df_finish - | TODO_verify_rtl_sharing ), /* todo_flags_finish */ + ( TODO_df_verify | TODO_df_finish ), /* todo_flags_finish */ }; class pass_rtl_move_loop_invariants : public rtl_opt_pass @@ -507,8 +532,13 @@ public: {} /* opt_pass methods: */ - bool gate () { return gate_rtl_move_loop_invariants (); } - unsigned int execute () { return rtl_move_loop_invariants (); } + virtual bool gate (function *) { return flag_move_loop_invariants; } + virtual unsigned int execute (function *fun) + { + if (number_of_loops (fun) > 1) + move_loop_invariants (); + return 0; + } }; // class pass_rtl_move_loop_invariants @@ -521,148 +551,66 @@ make_pass_rtl_move_loop_invariants (gcc::context *ctxt) } -/* Loop unswitching for RTL. */ -static bool -gate_rtl_unswitch (void) -{ - return flag_unswitch_loops; -} - -static unsigned int -rtl_unswitch (void) -{ - if (number_of_loops (cfun) > 1) - unswitch_loops (); - return 0; -} - namespace { -const pass_data pass_data_rtl_unswitch = +const pass_data pass_data_rtl_unroll_loops = { RTL_PASS, /* type */ - "loop2_unswitch", /* name */ + "loop2_unroll", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ - TV_LOOP_UNSWITCH, /* tv_id */ + TV_LOOP_UNROLL, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_verify_rtl_sharing, /* todo_flags_finish */ + 0, /* todo_flags_finish */ }; -class pass_rtl_unswitch : public rtl_opt_pass +class pass_rtl_unroll_loops : public rtl_opt_pass { public: - pass_rtl_unswitch (gcc::context *ctxt) - : rtl_opt_pass (pass_data_rtl_unswitch, ctxt) + pass_rtl_unroll_loops (gcc::context *ctxt) + : rtl_opt_pass (pass_data_rtl_unroll_loops, ctxt) {} /* opt_pass methods: */ - bool gate () { return gate_rtl_unswitch (); } - unsigned int execute () { return rtl_unswitch (); } - -}; // class pass_rtl_unswitch - -} // anon namespace + virtual bool gate (function *) + { + return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops); + } -rtl_opt_pass * -make_pass_rtl_unswitch (gcc::context *ctxt) -{ - return new pass_rtl_unswitch (ctxt); -} + virtual unsigned int execute (function *); - -/* Loop unswitching for RTL. */ -static bool -gate_rtl_unroll_and_peel_loops (void) -{ - return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops); -} +}; // class pass_rtl_unroll_loops -static unsigned int -rtl_unroll_and_peel_loops (void) +unsigned int +pass_rtl_unroll_loops::execute (function *fun) { - if (number_of_loops (cfun) > 1) + if (number_of_loops (fun) > 1) { int flags = 0; if (dump_file) df_dump (dump_file); - if (flag_peel_loops) - flags |= UAP_PEEL; if (flag_unroll_loops) flags |= UAP_UNROLL; if (flag_unroll_all_loops) flags |= UAP_UNROLL_ALL; - unroll_and_peel_loops (flags); + unroll_loops (flags); } return 0; } -namespace { - -const pass_data pass_data_rtl_unroll_and_peel_loops = -{ - RTL_PASS, /* type */ - "loop2_unroll", /* name */ - OPTGROUP_LOOP, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ - TV_LOOP_UNROLL, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_verify_rtl_sharing, /* todo_flags_finish */ -}; - -class pass_rtl_unroll_and_peel_loops : public rtl_opt_pass -{ -public: - pass_rtl_unroll_and_peel_loops (gcc::context *ctxt) - : rtl_opt_pass (pass_data_rtl_unroll_and_peel_loops, ctxt) - {} - - /* opt_pass methods: */ - bool gate () { return gate_rtl_unroll_and_peel_loops (); } - unsigned int execute () { return rtl_unroll_and_peel_loops (); } - -}; // class pass_rtl_unroll_and_peel_loops - } // anon namespace rtl_opt_pass * -make_pass_rtl_unroll_and_peel_loops (gcc::context *ctxt) +make_pass_rtl_unroll_loops (gcc::context *ctxt) { - return new pass_rtl_unroll_and_peel_loops (ctxt); + return new pass_rtl_unroll_loops (ctxt); } -/* The doloop optimization. */ -static bool -gate_rtl_doloop (void) -{ -#ifdef HAVE_doloop_end - return (flag_branch_on_count_reg && HAVE_doloop_end); -#else - return 0; -#endif -} - -static unsigned int -rtl_doloop (void) -{ -#ifdef HAVE_doloop_end - if (number_of_loops (cfun) > 1) - doloop_optimize_loops (); -#endif - return 0; -} - namespace { const pass_data pass_data_rtl_doloop = @@ -670,14 +618,12 @@ const pass_data pass_data_rtl_doloop = RTL_PASS, /* type */ "loop2_doloop", /* name */ OPTGROUP_LOOP, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ TV_LOOP_DOLOOP, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_verify_rtl_sharing, /* todo_flags_finish */ + 0, /* todo_flags_finish */ }; class pass_rtl_doloop : public rtl_opt_pass @@ -688,11 +634,31 @@ public: {} /* opt_pass methods: */ - bool gate () { return gate_rtl_doloop (); } - unsigned int execute () { return rtl_doloop (); } + virtual bool gate (function *); + virtual unsigned int execute (function *); }; // class pass_rtl_doloop +bool +pass_rtl_doloop::gate (function *) +{ +#ifdef HAVE_doloop_end + return (flag_branch_on_count_reg && HAVE_doloop_end); +#else + return false; +#endif +} + +unsigned int +pass_rtl_doloop::execute (function *fun ATTRIBUTE_UNUSED) +{ +#ifdef HAVE_doloop_end + if (number_of_loops (fun) > 1) + doloop_optimize_loops (); +#endif + return 0; +} + } // anon namespace rtl_opt_pass * |