OSDN Git Service

Fix clearing ZERO_REG
[pf3gnuchains/gcc-fork.git] / gcc / loop-init.c
index dd8eec1..9184a14 100644 (file)
@@ -1,11 +1,12 @@
 /* Loop optimizer initialization routines and RTL loop optimization passes.
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -14,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -31,6 +31,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tree-pass.h"
 #include "timevar.h"
 #include "flags.h"
+#include "df.h"
+#include "ggc.h"
 
 \f
 /* Initialize loop structures.  This is used by the tree and RTL loop
@@ -40,62 +42,57 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 void
 loop_optimizer_init (unsigned flags)
 {
-  edge e;
-  edge_iterator ei;
-  static bool first_time = true;
   struct loops *loops;
 
-  if (first_time)
-    {
-      first_time = false;
-      init_set_costs ();
-    }
-
   gcc_assert (!current_loops);
-  loops = XCNEW (struct loops);
-
-  /* Avoid annoying special cases of edges going to exit
-     block.  */
-
-  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);
+  loops = ggc_alloc_cleared_loops ();
 
   /* Find the loops.  */
 
   flow_loops_find (loops);
   current_loops = loops;
 
-  if (current_loops->num <= 1)
+  if (flags & LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
     {
-      /* No loops.  */
-      loop_optimizer_finalize ();
-      return;
+      /* If the loops may have multiple latches, we cannot canonicalize
+        them further (and most of the loop manipulation functions will
+        not work).  However, we avoid modifying cfg, which some
+        passes may want.  */
+      gcc_assert ((flags & ~(LOOPS_MAY_HAVE_MULTIPLE_LATCHES
+                            | LOOPS_HAVE_RECORDED_EXITS)) == 0);
+      loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
     }
+  else
+    disambiguate_loops_with_multiple_latches ();
 
   /* Create pre-headers.  */
   if (flags & LOOPS_HAVE_PREHEADERS)
-    create_preheaders (current_loops, CP_SIMPLE_PREHEADERS);
+    {
+      int cp_flags = CP_SIMPLE_PREHEADERS;
+
+      if (flags & LOOPS_HAVE_FALLTHRU_PREHEADERS)
+        cp_flags |= CP_FALLTHRU_PREHEADERS;
+
+      create_preheaders (cp_flags);
+    }
 
   /* Force all latches to have only single successor.  */
   if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
-    force_single_succ_latches (current_loops);
+    force_single_succ_latches ();
 
   /* Mark irreducible loops.  */
   if (flags & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
-    mark_irreducible_loops (current_loops);
+    mark_irreducible_loops ();
 
-  if (flags & LOOPS_HAVE_MARKED_SINGLE_EXITS)
-    mark_single_exit_loops (current_loops);
+  if (flags & LOOPS_HAVE_RECORDED_EXITS)
+    record_loop_exits ();
 
   /* Dump loops.  */
-  flow_loops_dump (current_loops, dump_file, NULL, 1);
+  flow_loops_dump (dump_file, NULL, 1);
 
 #ifdef ENABLE_CHECKING
   verify_dominators (CDI_DOMINATORS);
-  verify_loop_structure (current_loops);
+  verify_loop_structure ();
 #endif
 }
 
@@ -104,30 +101,28 @@ loop_optimizer_init (unsigned flags)
 void
 loop_optimizer_finalize (void)
 {
-  unsigned i;
+  loop_iterator li;
+  struct loop *loop;
   basic_block bb;
 
-  if (!current_loops)
-    return;
+  gcc_assert (current_loops != NULL);
 
-  for (i = 1; i < current_loops->num; i++)
-    if (current_loops->parray[i])
-      free_simple_loop_desc (current_loops->parray[i]);
+  FOR_EACH_LOOP (li, loop, 0)
+    {
+      free_simple_loop_desc (loop);
+    }
 
   /* Clean up.  */
+  if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS))
+    release_recorded_exits ();
   flow_loops_free (current_loops);
-  free (current_loops);
+  ggc_free (current_loops);
   current_loops = NULL;
 
   FOR_ALL_BB (bb)
     {
       bb->loop_father = NULL;
     }
-
-  /* Checking.  */
-#ifdef ENABLE_CHECKING
-  verify_flow_info ();
-#endif
 }
 
 \f
@@ -148,8 +143,10 @@ gate_handle_loop2 (void)
              ));
 }
 
-struct tree_opt_pass pass_loop2 =
+struct rtl_opt_pass pass_loop2 =
 {
+ {
+  RTL_PASS,
   "loop2",                              /* name */
   gate_handle_loop2,                   /* gate */
   NULL,                                 /* execute */
@@ -161,9 +158,8 @@ struct tree_opt_pass pass_loop2 =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func |
-  TODO_ggc_collect,                     /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_ggc_collect                      /* todo_flags_finish */
+ }
 };
 
 \f
@@ -171,18 +167,19 @@ struct tree_opt_pass pass_loop2 =
 static unsigned int
 rtl_loop_init (void)
 {
+  gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT);
+
   if (dump_file)
     dump_flow_info (dump_file, dump_flags);
 
-  /* Initialize structures for layout changes.  */
-  cfg_layout_initialize (0);
-
   loop_optimizer_init (LOOPS_NORMAL);
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_loop_init =
+struct rtl_opt_pass pass_rtl_loop_init =
 {
+ {
+  RTL_PASS,
   "loop2_init",                           /* name */
   NULL,                                 /* gate */
   rtl_loop_init,                        /* execute */
@@ -194,8 +191,8 @@ struct tree_opt_pass pass_rtl_loop_init =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_verify_rtl_sharing               /* todo_flags_finish */
+ }
 };
 
 \f
@@ -204,28 +201,20 @@ struct tree_opt_pass pass_rtl_loop_init =
 static unsigned int
 rtl_loop_done (void)
 {
-  basic_block bb;
-
   loop_optimizer_finalize ();
   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 ());
+  cleanup_cfg (0);
   if (dump_file)
     dump_flow_info (dump_file, dump_flags);
 
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_loop_done =
+struct rtl_opt_pass pass_rtl_loop_done =
 {
+ {
+  RTL_PASS,
   "loop2_done",                          /* name */
   NULL,                                 /* gate */
   rtl_loop_done,                        /* execute */
@@ -237,8 +226,9 @@ struct tree_opt_pass pass_rtl_loop_done =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_verify_flow
+    | TODO_verify_rtl_sharing           /* todo_flags_finish */
+ }
 };
 
 \f
@@ -252,26 +242,29 @@ gate_rtl_move_loop_invariants (void)
 static unsigned int
 rtl_move_loop_invariants (void)
 {
-  if (current_loops)
-    move_loop_invariants (current_loops);
+  if (number_of_loops () > 1)
+    move_loop_invariants ();
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_move_loop_invariants =
+struct rtl_opt_pass pass_rtl_move_loop_invariants =
 {
-  "loop2_invariant",                     /* name */
+ {
+  RTL_PASS,
+  "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 */
+  TV_LOOP_MOVE_INVARIANTS,              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_df_verify |
+  TODO_df_finish | TODO_verify_rtl_sharing  /* todo_flags_finish */
+ }
 };
 
 \f
@@ -285,26 +278,28 @@ gate_rtl_unswitch (void)
 static unsigned int
 rtl_unswitch (void)
 {
-  if (current_loops)
-    unswitch_loops (current_loops);
+  if (number_of_loops () > 1)
+    unswitch_loops ();
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_unswitch =
+struct rtl_opt_pass pass_rtl_unswitch =
 {
+ {
+  RTL_PASS,
   "loop2_unswitch",                      /* name */
   gate_rtl_unswitch,                    /* gate */
   rtl_unswitch,                         /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_LOOP,                              /* tv_id */
+  TV_LOOP_UNSWITCH,                     /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_verify_rtl_sharing,              /* todo_flags_finish */
+ }
 };
 
 \f
@@ -318,9 +313,11 @@ gate_rtl_unroll_and_peel_loops (void)
 static unsigned int
 rtl_unroll_and_peel_loops (void)
 {
-  if (current_loops)
+  if (number_of_loops () > 1)
     {
       int flags = 0;
+      if (dump_file)
+       df_dump (dump_file);
 
       if (flag_peel_loops)
        flags |= UAP_PEEL;
@@ -329,26 +326,28 @@ rtl_unroll_and_peel_loops (void)
       if (flag_unroll_all_loops)
        flags |= UAP_UNROLL_ALL;
 
-      unroll_and_peel_loops (current_loops, flags);
+      unroll_and_peel_loops (flags);
     }
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_unroll_and_peel_loops =
+struct rtl_opt_pass pass_rtl_unroll_and_peel_loops =
 {
+ {
+  RTL_PASS,
   "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 */
+  TV_LOOP_UNROLL,                       /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_verify_rtl_sharing,              /* todo_flags_finish */
+ }
 };
 
 \f
@@ -367,26 +366,27 @@ static unsigned int
 rtl_doloop (void)
 {
 #ifdef HAVE_doloop_end
-  if (current_loops)
-    doloop_optimize_loops (current_loops);
+  if (number_of_loops () > 1)
+    doloop_optimize_loops ();
 #endif
   return 0;
 }
 
-struct tree_opt_pass pass_rtl_doloop =
+struct rtl_opt_pass pass_rtl_doloop =
 {
+ {
+  RTL_PASS,
   "loop2_doloop",                        /* name */
   gate_rtl_doloop,                      /* gate */
   rtl_doloop,                           /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_LOOP,                              /* tv_id */
+  TV_LOOP_DOLOOP,                       /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'L'                                   /* letter */
+  TODO_verify_rtl_sharing               /* todo_flags_finish */
+ }
 };
-