aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcc/loop-init.c
diff options
context:
space:
mode:
authorAlexander Kabaev <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
committerAlexander Kabaev <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
commit6b834ef156bcf24dcf0e281f57ee5bde03ca07cf (patch)
tree0cb530c9c38af219e6dda2994c078b6b2b9ad853 /contrib/gcc/loop-init.c
parent9ba78bf6b1135ae200742b2a97ae5bc71c9fd265 (diff)
downloadsrc-6b834ef156bcf24dcf0e281f57ee5bde03ca07cf.tar.gz
src-6b834ef156bcf24dcf0e281f57ee5bde03ca07cf.zip
GCC 4.2.0 release.
Notes
Notes: svn path=/vendor/gcc/dist/; revision=169689
Diffstat (limited to 'contrib/gcc/loop-init.c')
-rw-r--r--contrib/gcc/loop-init.c424
1 files changed, 297 insertions, 127 deletions
diff --git a/contrib/gcc/loop-init.c b/contrib/gcc/loop-init.c
index 6dd146f99113..d2c63404516a 100644
--- a/contrib/gcc/loop-init.c
+++ b/contrib/gcc/loop-init.c
@@ -1,5 +1,5 @@
-/* Loop optimizer initialization routines.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Loop optimizer initialization routines and RTL loop optimization passes.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -24,45 +24,50 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm.h"
#include "rtl.h"
#include "hard-reg-set.h"
+#include "obstack.h"
#include "basic-block.h"
#include "cfgloop.h"
#include "cfglayout.h"
+#include "tree-pass.h"
+#include "timevar.h"
+#include "flags.h"
-static void fixup_loop_exit_succesor (basic_block, basic_block);
-
-/* Initialize loop optimizer. */
+
+/* Initialize loop optimizer. This is used by the tree and RTL loop
+ optimizers. FLAGS specify what properties to compute and/or ensure for
+ loops. */
struct loops *
-loop_optimizer_init (FILE *dumpfile)
+loop_optimizer_init (unsigned flags)
{
- struct loops *loops = xcalloc (1, sizeof (struct loops));
+ struct loops *loops = XCNEW (struct loops);
edge e;
+ edge_iterator ei;
+ static bool first_time = true;
- /* Initialize structures for layout changes. */
- cfg_layout_initialize (0);
+ if (first_time)
+ {
+ first_time = false;
+ init_set_costs ();
+ }
/* Avoid annoying special cases of edges going to exit
block. */
- for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
- if ((e->flags & EDGE_FALLTHRU) && e->src->succ->succ_next)
+
+ for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
+ if ((e->flags & EDGE_FALLTHRU) && !single_succ_p (e->src))
split_edge (e);
+ else
+ ei_next (&ei);
/* Find the loops. */
- if (flow_loops_find (loops, LOOP_TREE) <= 1)
+ if (flow_loops_find (loops) <= 1)
{
- basic_block bb;
-
/* No loops. */
flow_loops_free (loops);
- free_dominance_info (CDI_DOMINATORS);
free (loops);
- /* Make chain. */
- FOR_EACH_BB (bb)
- if (bb->next_bb != EXIT_BLOCK_PTR)
- bb->rbi->next = bb->next_bb;
- cfg_layout_finalize ();
return NULL;
}
@@ -73,16 +78,22 @@ loop_optimizer_init (FILE *dumpfile)
loops->cfg.dfs_order = NULL;
/* Create pre-headers. */
- create_preheaders (loops, CP_SIMPLE_PREHEADERS);
+ if (flags & LOOPS_HAVE_PREHEADERS)
+ create_preheaders (loops, CP_SIMPLE_PREHEADERS);
/* Force all latches to have only single successor. */
- force_single_succ_latches (loops);
+ if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
+ force_single_succ_latches (loops);
/* Mark irreducible loops. */
- mark_irreducible_loops (loops);
+ if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+ mark_irreducible_loops (loops);
+
+ if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
+ mark_single_exit_loops (loops);
/* Dump loops. */
- flow_loops_dump (loops, dumpfile, NULL, 1);
+ flow_loops_dump (loops, dump_file, NULL, 1);
#ifdef ENABLE_CHECKING
verify_dominators (CDI_DOMINATORS);
@@ -92,129 +103,288 @@ loop_optimizer_init (FILE *dumpfile)
return loops;
}
-/* The first basic block is moved after the second in the reorder chain. */
-static void
-fixup_loop_exit_succesor (basic_block exit_succ, basic_block latch)
+/* Finalize loop optimizer. */
+void
+loop_optimizer_finalize (struct loops *loops)
{
- basic_block bb = exit_succ;
- basic_block bb1 = latch;
+ unsigned i;
- if (!(bb && bb->rbi->next))
+ if (!loops)
return;
- if (!bb1)
- return;
-
+ for (i = 1; i < loops->num; i++)
+ if (loops->parray[i])
+ free_simple_loop_desc (loops->parray[i]);
- if (bb && bb->rbi->next)
- {
- basic_block c = ENTRY_BLOCK_PTR->next_bb;
+ /* Clean up. */
+ flow_loops_free (loops);
+ free (loops);
+
+ /* Checking. */
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
+}
- while (c->rbi->next != bb)
- c = c->rbi->next;
+
+/* Gate for the RTL loop superpass. The actual passes are subpasses.
+ See passes.c for more on that. */
- c->rbi->next = bb->rbi->next;
- }
+static bool
+gate_handle_loop2 (void)
+{
+ return (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
+ ));
+}
- if(bb1->rbi->next == NULL)
- {
- bb1->rbi->next=bb;
- bb->rbi->next=NULL;
- }
- else
-
- {
- basic_block tmp;
+struct tree_opt_pass pass_loop2 =
+{
+ "loop2", /* name */
+ gate_handle_loop2, /* gate */
+ NULL, /* 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 */
+};
+
+
+/* Initialization of the RTL loop passes. */
+static unsigned int
+rtl_loop_init (void)
+{
+ if (dump_file)
+ dump_flow_info (dump_file, dump_flags);
- tmp = bb1->rbi->next;
- bb1->rbi->next = bb;
- bb->rbi->next = tmp;
- }
+ /* Initialize structures for layout changes. */
+ cfg_layout_initialize (0);
+
+ current_loops = loop_optimizer_init (LOOPS_NORMAL);
+ return 0;
}
-/* Finalize loop optimizer. */
-void
-loop_optimizer_finalize (struct loops *loops, FILE *dumpfile)
+struct tree_opt_pass pass_rtl_loop_init =
+{
+ "loop2_init", /* name */
+ NULL, /* gate */
+ rtl_loop_init, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Finalization of the RTL loop passes. */
+static unsigned int
+rtl_loop_done (void)
{
basic_block bb;
- unsigned int i;
+
+ if (current_loops)
+ loop_optimizer_finalize (current_loops);
+
+ free_dominance_info (CDI_DOMINATORS);
/* Finalize layout changes. */
- /* Make chain. */
FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR)
- bb->rbi->next = bb->next_bb;
+ bb->aux = bb->next_bb;
+ cfg_layout_finalize ();
- /* Another dump. */
- flow_loops_dump (loops, dumpfile, NULL, 1);
+ 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, dump_flags);
- /* For loops ending with a branch and count instruction, move the basic
- block found before the unrolling on the fallthru path of this branch,
- after the unrolled code. This will allow branch simplification. */
- for (i = 1; i < loops->num; i++)
+ current_loops = NULL;
+ return 0;
+}
+
+struct tree_opt_pass pass_rtl_loop_done =
+{
+ "loop2_done", /* name */
+ NULL, /* gate */
+ rtl_loop_done, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* 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 (current_loops)
+ move_loop_invariants (current_loops);
+ return 0;
+}
+
+struct tree_opt_pass pass_rtl_move_loop_invariants =
+{
+ "loop2_invariant", /* name */
+ gate_rtl_move_loop_invariants, /* gate */
+ rtl_move_loop_invariants, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Loop unswitching for RTL. */
+static bool
+gate_rtl_unswitch (void)
+{
+ return flag_unswitch_loops;
+}
+
+static unsigned int
+rtl_unswitch (void)
+{
+ if (current_loops)
+ unswitch_loops (current_loops);
+ return 0;
+}
+
+struct tree_opt_pass pass_rtl_unswitch =
+{
+ "loop2_unswitch", /* name */
+ gate_rtl_unswitch, /* gate */
+ rtl_unswitch, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* Loop unswitching for RTL. */
+static bool
+gate_rtl_unroll_and_peel_loops (void)
+{
+ return (flag_peel_loops || flag_unroll_loops || flag_unroll_all_loops);
+}
+
+static unsigned int
+rtl_unroll_and_peel_loops (void)
+{
+ if (current_loops)
{
- struct loop *loop = loops->parray[i];
- struct loop_desc *desc;
- basic_block loop_real_latch, bb, bb_exit;
- edge e;
-
- if (loop == NULL)
- continue;
- if (!loop->simple)
- continue;
- if (!loop->has_desc)
- continue;
-
- if (loop->lpt_decision.decision != LPT_UNROLL_RUNTIME)
- continue;
-
- desc = &loop->desc;
- if (desc == NULL)
- continue;
- if (loop->latch->pred == NULL)
- continue;
-
- loop_real_latch = loop->latch->pred->src;
-
-
- if (desc->postincr)
- continue;
- if (!is_bct_cond (BB_END (loop_real_latch)))
- continue;
-
- for (e = loop_real_latch->succ; e ; e = e->succ_next)
- if (e->flags & EDGE_FALLTHRU)
- break;
-
- if (e == NULL)
- continue;
-
- bb_exit = e->dest;
-
- bb = NULL;
-
- /* Leave the case of the bb_exit falling through to exit to
- fixed_fallthru_exit_predecessor */
- for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
- if (e->flags & EDGE_FALLTHRU)
- bb = e->src;
-
- if (bb_exit == bb)
- continue;
-
- fixup_loop_exit_succesor (bb_exit, loop->latch);
- }
+ int flags = 0;
- /* Clean up. */
- flow_loops_free (loops);
- free_dominance_info (CDI_DOMINATORS);
- free (loops);
+ if (flag_peel_loops)
+ flags |= UAP_PEEL;
+ if (flag_unroll_loops)
+ flags |= UAP_UNROLL;
+ if (flag_unroll_all_loops)
+ flags |= UAP_UNROLL_ALL;
- /* Finalize changes. */
- cfg_layout_finalize ();
+ unroll_and_peel_loops (current_loops, flags);
+ }
+ return 0;
+}
- /* Checking. */
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
+struct tree_opt_pass pass_rtl_unroll_and_peel_loops =
+{
+ "loop2_unroll", /* name */
+ gate_rtl_unroll_and_peel_loops, /* gate */
+ rtl_unroll_and_peel_loops, /* 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_flags_finish */
+ 'L' /* letter */
+};
+
+
+/* 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 (current_loops)
+ doloop_optimize_loops (current_loops);
#endif
+ return 0;
}
+
+struct tree_opt_pass pass_rtl_doloop =
+{
+ "loop2_doloop", /* name */
+ gate_rtl_doloop, /* gate */
+ rtl_doloop, /* 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_flags_finish */
+ 'L' /* letter */
+};
+