OSDN Git Service

2003-06-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / cfgloop.c
index 0a2829f..92d9055 100644 (file)
@@ -20,10 +20,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "toplev.h"
+#include "cfgloop.h"
+#include "flags.h"
 
 /* Ratio of frequencies of edges so that one of more latch edges is
    considered to belong to inner loop with same header.  */
@@ -39,12 +43,12 @@ static basic_block flow_loop_pre_header_find PARAMS ((basic_block,
                                                      dominance_info));
 static int flow_loop_level_compute     PARAMS ((struct loop *));
 static int flow_loops_level_compute    PARAMS ((struct loops *));
+static void establish_preds            PARAMS ((struct loop *));
 static basic_block make_forwarder_block PARAMS ((basic_block, int, int,
                                                 edge, int));
 static void canonicalize_loop_headers   PARAMS ((void));
 static bool glb_enum_p PARAMS ((basic_block, void *));
 static void redirect_edge_with_latch_update PARAMS ((edge, basic_block));
-static void flow_loop_free PARAMS ((struct loop *));
 \f
 /* Dump loop related CFG information.  */
 
@@ -112,7 +116,7 @@ flow_loop_dump (loop, file, loop_dump_aux, verbose)
      int verbose;
 {
   basic_block *bbs;
-  int i;
+  unsigned i;
 
   if (! loop || ! loop->header)
     return;
@@ -181,7 +185,7 @@ flow_loops_dump (loops, file, loop_dump_aux, verbose)
 }
 
 /* Free data allocated for LOOP.  */
-static void
+void
 flow_loop_free (loop)
      struct loop *loop;
 {
@@ -204,7 +208,7 @@ flow_loops_free (loops)
 {
   if (loops->parray)
     {
-      int i;
+      unsigned i;
 
       if (! loops->num)
        abort ();
@@ -273,7 +277,7 @@ flow_loop_exit_edges_find (loop)
 {
   edge e;
   basic_block node, *bbs;
-  int num_exits, i;
+  unsigned num_exits, i;
 
   loop->exit_edges = NULL;
   loop->num_exits = 0;
@@ -331,11 +335,9 @@ flow_loop_nodes_find (header, loop)
   basic_block *stack;
   int sp;
   int num_nodes = 1;
-  int findex, lindex;
 
   header->loop_father = loop;
   header->loop_depth = loop->depth;
-  findex = lindex = header->index;
 
   if (loop->latch->loop_father != loop)
     {
@@ -445,8 +447,26 @@ flow_loop_pre_header_find (header, dom)
   return pre_header;
 }
 
+static void
+establish_preds (loop)
+     struct loop *loop;
+{
+  struct loop *ploop, *father = loop->outer;
+
+  loop->depth = father->depth + 1;
+  if (loop->pred)
+    free (loop->pred);
+  loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
+  memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
+  loop->pred[father->depth] = father;
+
+  for (ploop = loop->inner; ploop; ploop = ploop->next)
+    establish_preds (ploop);
+}
+
 /* Add LOOP to the loop hierarchy tree where FATHER is father of the
-   added loop.  */
+   added loop.  If LOOP has some children, take care of that their
+   pred field will be initialized correctly.  */
 
 void
 flow_loop_tree_node_add (father, loop)
@@ -457,10 +477,7 @@ flow_loop_tree_node_add (father, loop)
   father->inner = loop;
   loop->outer = father;
 
-  loop->depth = father->depth + 1;
-  loop->pred = xmalloc (sizeof (struct loop *) * loop->depth);
-  memcpy (loop->pred, father->pred, sizeof (struct loop *) * father->depth);
-  loop->pred[father->depth] = father;
+  establish_preds (loop);
 }
 
 /* Remove LOOP from the loop hierarchy tree.  */
@@ -609,6 +626,10 @@ make_forwarder_block (bb, redirect_latch, redirect_nonlatch, except,
 
   insn = PREV_INSN (first_insn_after_basic_block_note (bb));
 
+  /* For empty block split_block will return NULL.  */
+  if (bb->end == insn)
+    emit_note_after (NOTE_INSN_DELETED, insn);
+
   fallthru = split_block (bb, insn);
   dummy = fallthru->src;
   bb = fallthru->dest;
@@ -804,19 +825,20 @@ flow_loops_find (loops, flags)
      
       header->loop_depth = 0;
 
+      /* If we have an abnormal predecessor, do not consider the
+        loop (not worth the problems).  */
+      for (e = header->pred; e; e = e->pred_next)
+       if (e->flags & EDGE_ABNORMAL)
+         break;
+      if (e)
+       continue;
+
       for (e = header->pred; e; e = e->pred_next)
        {
          basic_block latch = e->src;
 
          if (e->flags & EDGE_ABNORMAL)
-           {
-             if (more_latches)
-               {
-                 RESET_BIT (headers, header->index);
-                 num_loops--;
-               }
-             break;
-           }
+           abort ();
 
          /* Look for back edges where a predecessor is dominated
             by this block.  A natural loop has a single entry
@@ -925,9 +947,11 @@ flow_loops_find (loops, flags)
       loops->cfg.dom = NULL;
       free_dominance_info (dom);
     }
+
+  loops->state = 0;
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
-  verify_loop_structure (loops, 0);
+  verify_loop_structure (loops);
 #endif
 
   return loops->num;
@@ -991,7 +1015,7 @@ get_loop_body (loop)
      const struct loop *loop;
 {
   basic_block *tovisit, bb;
-  int tv = 0;
+  unsigned tv = 0;
 
   if (!loop->num_nodes)
     abort ();
@@ -1002,7 +1026,7 @@ get_loop_body (loop)
   if (loop->latch == EXIT_BLOCK_PTR)
     {
       /* There may be blocks unreachable from EXIT_BLOCK.  */
-      if (loop->num_nodes != n_basic_blocks + 2)
+      if (loop->num_nodes != (unsigned) n_basic_blocks + 2)
        abort ();
       FOR_EACH_BB (bb)
        tovisit[tv++] = bb;
@@ -1020,6 +1044,37 @@ get_loop_body (loop)
   return tovisit;
 }
 
+/* Gets exit edges of a LOOP, returning their number in N_EDGES.  */
+edge *
+get_loop_exit_edges (loop, n_edges)
+     const struct loop *loop;
+     unsigned *n_edges;
+{
+  edge *edges, e;
+  unsigned i, n;
+  basic_block * body;
+
+  if (loop->latch == EXIT_BLOCK_PTR)
+    abort ();
+
+  body = get_loop_body (loop);
+  n = 0;
+  for (i = 0; i < loop->num_nodes; i++)
+    for (e = body[i]->succ; e; e = e->succ_next)
+      if (!flow_bb_inside_loop_p (loop, e->dest))
+       n++;
+  edges = xmalloc (n * sizeof (edge));
+  *n_edges = n;
+  n = 0;
+  for (i = 0; i < loop->num_nodes; i++)
+    for (e = body[i]->succ; e; e = e->succ_next)
+      if (!flow_bb_inside_loop_p (loop, e->dest))
+       edges[n++] = e;
+  free (body);
+
+  return edges;
+}
+
 /* Adds basic block BB to LOOP.  */
 void
 add_bb_to_loop (bb, loop)
@@ -1072,21 +1127,61 @@ find_common_loop (loop_s, loop_d)
   return loop_s;
 }
 
+/* Cancels the LOOP; it must be innermost one.  */
+void
+cancel_loop (loops, loop)
+     struct loops *loops;
+     struct loop *loop;
+{
+  basic_block *bbs;
+  unsigned i;
+
+  if (loop->inner)
+    abort ();
+
+  /* Move blocks up one level (they should be removed as soon as possible).  */
+  bbs = get_loop_body (loop);
+  for (i = 0; i < loop->num_nodes; i++)
+    bbs[i]->loop_father = loop->outer;
+
+  /* Remove the loop from structure.  */
+  flow_loop_tree_node_remove (loop);
+
+  /* Remove loop from loops array.  */
+  loops->parray[loop->num] = NULL;
+
+  /* Free loop data.  */
+  flow_loop_free (loop);
+}
+
+/* Cancels LOOP and all its subloops.  */
+void
+cancel_loop_tree (loops, loop)
+     struct loops *loops;
+     struct loop *loop;
+{
+  while (loop->inner)
+    cancel_loop_tree (loops, loop->inner);
+  cancel_loop (loops, loop);
+}
+
 /* Checks that LOOPS are allright:
      -- sizes of loops are allright
      -- results of get_loop_body really belong to the loop
      -- loop header have just single entry edge and single latch edge
      -- loop latches have only single successor that is header of their loop
+     -- irreducible loops are correctly marked
   */
 void
-verify_loop_structure (loops, flags)
+verify_loop_structure (loops)
      struct loops *loops;
-     int flags;
 {
-  int *sizes, i, j;
+  unsigned *sizes, i, j;
+  sbitmap irreds;
   basic_block *bbs, bb;
   struct loop *loop;
   int err = 0;
+  edge e;
 
   /* Check sizes.  */
   sizes = xcalloc (loops->num, sizeof (int));
@@ -1136,14 +1231,14 @@ verify_loop_structure (loops, flags)
       if (!loop)
        continue;
 
-      if ((flags & VLS_EXPECT_PREHEADERS)
+      if ((loops->state & LOOPS_HAVE_PREHEADERS)
          && (!loop->header->pred->pred_next
              || loop->header->pred->pred_next->pred_next))
        {
          error ("Loop %d's header does not have exactly 2 entries.", i);
          err = 1;
        }
-      if (flags & VLS_EXPECT_SIMPLE_LATCHES)
+      if (loops->state & LOOPS_HAVE_SIMPLE_LATCHES)
        {
          if (!loop->latch->succ
              || loop->latch->succ->succ_next)
@@ -1167,6 +1262,68 @@ verify_loop_structure (loops, flags)
          error ("Loop %d's header does not belong directly to it.", i);
          err = 1;
        }
+      if ((loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+         && (loop_latch_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP))
+       {
+         error ("Loop %d's latch is marked as part of irreducible region.", i);
+         err = 1;
+       }
+    }
+
+  /* Check irreducible loops.  */
+  if (loops->state & LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+    {
+      /* Record old info.  */
+      irreds = sbitmap_alloc (last_basic_block);
+      FOR_EACH_BB (bb)
+       {
+         if (bb->flags & BB_IRREDUCIBLE_LOOP)
+           SET_BIT (irreds, bb->index);
+         else
+           RESET_BIT (irreds, bb->index);
+         for (e = bb->succ; e; e = e->succ_next)
+           if (e->flags & EDGE_IRREDUCIBLE_LOOP)
+             e->flags |= EDGE_ALL_FLAGS + 1;
+       }
+
+      /* Recount it.  */
+      mark_irreducible_loops (loops);
+
+      /* Compare.  */
+      FOR_EACH_BB (bb)
+       {
+         if ((bb->flags & BB_IRREDUCIBLE_LOOP)
+             && !TEST_BIT (irreds, bb->index))
+           {
+             error ("Basic block %d should be marked irreducible.", bb->index);
+             err = 1;
+           }
+         else if (!(bb->flags & BB_IRREDUCIBLE_LOOP)
+             && TEST_BIT (irreds, bb->index))
+           {
+             error ("Basic block %d should not be marked irreducible.", bb->index);
+             err = 1;
+           }
+         for (e = bb->succ; e; e = e->succ_next)
+           {
+             if ((e->flags & EDGE_IRREDUCIBLE_LOOP)
+                 && !(e->flags & (EDGE_ALL_FLAGS + 1)))
+               {
+                 error ("Edge from %d to %d should be marked irreducible.",
+                        e->src->index, e->dest->index);
+                 err = 1;
+               }
+             else if (!(e->flags & EDGE_IRREDUCIBLE_LOOP)
+                      && (e->flags & (EDGE_ALL_FLAGS + 1)))
+               {
+                 error ("Edge from %d to %d should not be marked irreducible.",
+                        e->src->index, e->dest->index);
+                 err = 1;
+               }
+             e->flags &= ~(EDGE_ALL_FLAGS + 1);
+           }
+       }
+      free (irreds);
     }
 
   if (err)
@@ -1176,7 +1333,7 @@ verify_loop_structure (loops, flags)
 /* Returns latch edge of LOOP.  */
 edge
 loop_latch_edge (loop)
-     struct loop *loop;
+     const struct loop *loop;
 {
   edge e;
 
@@ -1189,7 +1346,7 @@ loop_latch_edge (loop)
 /* Returns preheader edge of LOOP.  */
 edge
 loop_preheader_edge (loop)
-     struct loop *loop;
+     const struct loop *loop;
 {
   edge e;