OSDN Git Service

* cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Mar 2005 13:44:46 +0000 (13:44 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Mar 2005 13:44:46 +0000 (13:44 +0000)
flow_loop_pre_header_scan, flow_loop_pre_header_find,
flow_loop_scan): Removed.
(flow_loop_dump): Do not dump removed fields.
(flow_loop_free): Do not free removed fields.
(flow_loops_find): Flags argument removed.  Do not call flow_loop_scan.
(loop_exit_edge_p): New function.
* cfgloop.h (struct loop): Removed fields pre_header, pre_header_edges,
num_pre_header_edges, entry_edges, num_entries, exit_edges,
num_exits, exits_doms.
(LOOP_TREE, LOOP_PRE_HEADER, LOOP_ENTRY_EDGES, LOOP_EXIT_EDGES,
LOOP_EDGES, LOOP_ALL): Removed.
(flow_loop_scan): Declaration removed.
(loop_exit_edge_p, mark_loop_exit_edges): Declare.
* cfgloopmanip.c (create_loop_notes): Do not pass flags to
flow_loops_find.
* ifcvt.c (mark_loop_exit_edges): Moved to cfgloopanal.c.
(if_convert): Call flow_loops_find and flow_loops_free
when calling mark_loop_exit_edges.
* cfgloopanal.c (mark_loop_exit_edges): Moved from
ifcvt.c.  Removed the flow_loops_find, flow_loops_free and
free_dominance_info calls.
* loop-init.c (flow_loops_find): Ditto.
* passes.c (rest_of_handle_branch_prob): Ditto.
* lambda-code.c (perfect_nestify): Do not call flow_loops_find.
* loop-unroll.c (analyze_insns_in_loop): Do not use
EDGE_LOOP_EXIT.
* predict.c (predict_loops): Do not call flow_loop_scan.
Use get_loop_exit_edges.
(tree_estimate_probability): Do not pass flags to flow_loops_find.
* tree-if-conv.c (bb_with_exit_edge_p): Take loop as argument.
Do not use EDGE_LOOP_EXIT.
(tree_if_convert_cond_expr, if_convertible_modify_expr_p): Pass loop
to bb_with_exit_edge_p.
(if_convertible_loop_p): Do not call flow_loop_scan.  Use
loop->single_exit.  Do not use EDGE_LOOP_EXIT.  Pass loop
to bb_with_exit_edge_p.
(combine_blocks): Pass loop to bb_with_exit_edge_p.  Do not use
EDGE_LOOP_EXIT.
* tree-loop-linear.c (linear_transform_loops): Do not call
flow_loop_scan.  Use loop->single_exit.
* tree-vect-analyze.c (vect_analyze_operations): Use loop->single_exit.
(vect_analyze_loop_form): Do not call flow_loop_scan.
* tree-vect-transform.c (vect_update_ivs_after_vectorizer): Use
loop->single_exit.
(vect_do_peeling_for_loop_bound): Use loop_preheader_edge and
loop->single_exit.
* tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
slpeel_make_loop_iterate_ntimes, slpeel_can_duplicate_loop_p,
slpeel_tree_duplicate_loop_to_edge_cfg,
slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
Use loop_preheader_edge and loop->single_exit.  Do not call
flow_loop_scan.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95738 138bc75d-0d04-0410-961f-82ee72b054a4

16 files changed:
gcc/ChangeLog
gcc/cfgloop.c
gcc/cfgloop.h
gcc/cfgloopanal.c
gcc/cfgloopmanip.c
gcc/ifcvt.c
gcc/lambda-code.c
gcc/loop-init.c
gcc/loop-unroll.c
gcc/passes.c
gcc/predict.c
gcc/tree-if-conv.c
gcc/tree-loop-linear.c
gcc/tree-vect-analyze.c
gcc/tree-vect-transform.c
gcc/tree-vectorizer.c

index fb3aa1b..c5f2f22 100644 (file)
@@ -1,3 +1,59 @@
+2005-03-01  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       * cfgloop.c (flow_loop_entry_edges_find, flow_loop_exit_edges_find,
+       flow_loop_pre_header_scan, flow_loop_pre_header_find,
+       flow_loop_scan): Removed.
+       (flow_loop_dump): Do not dump removed fields.
+       (flow_loop_free): Do not free removed fields.
+       (flow_loops_find): Flags argument removed.  Do not call flow_loop_scan.
+       (loop_exit_edge_p): New function.
+       * cfgloop.h (struct loop): Removed fields pre_header, pre_header_edges,
+       num_pre_header_edges, entry_edges, num_entries, exit_edges,
+       num_exits, exits_doms.
+       (LOOP_TREE, LOOP_PRE_HEADER, LOOP_ENTRY_EDGES, LOOP_EXIT_EDGES,
+       LOOP_EDGES, LOOP_ALL): Removed.
+       (flow_loop_scan): Declaration removed.
+       (loop_exit_edge_p, mark_loop_exit_edges): Declare.
+       * cfgloopmanip.c (create_loop_notes): Do not pass flags to
+       flow_loops_find.
+       * ifcvt.c (mark_loop_exit_edges): Moved to cfgloopanal.c.
+       (if_convert): Call flow_loops_find and flow_loops_free
+       when calling mark_loop_exit_edges.
+       * cfgloopanal.c (mark_loop_exit_edges): Moved from
+       ifcvt.c.  Removed the flow_loops_find, flow_loops_free and
+       free_dominance_info calls.
+       * loop-init.c (flow_loops_find): Ditto.
+       * passes.c (rest_of_handle_branch_prob): Ditto.
+       * lambda-code.c (perfect_nestify): Do not call flow_loops_find.
+       * loop-unroll.c (analyze_insns_in_loop): Do not use
+       EDGE_LOOP_EXIT.
+       * predict.c (predict_loops): Do not call flow_loop_scan.
+       Use get_loop_exit_edges.
+       (tree_estimate_probability): Do not pass flags to flow_loops_find.
+       * tree-if-conv.c (bb_with_exit_edge_p): Take loop as argument.
+       Do not use EDGE_LOOP_EXIT.
+       (tree_if_convert_cond_expr, if_convertible_modify_expr_p): Pass loop
+       to bb_with_exit_edge_p.
+       (if_convertible_loop_p): Do not call flow_loop_scan.  Use
+       loop->single_exit.  Do not use EDGE_LOOP_EXIT.  Pass loop
+       to bb_with_exit_edge_p.
+       (combine_blocks): Pass loop to bb_with_exit_edge_p.  Do not use
+       EDGE_LOOP_EXIT.
+       * tree-loop-linear.c (linear_transform_loops): Do not call
+       flow_loop_scan.  Use loop->single_exit.
+       * tree-vect-analyze.c (vect_analyze_operations): Use loop->single_exit.
+       (vect_analyze_loop_form): Do not call flow_loop_scan.
+       * tree-vect-transform.c (vect_update_ivs_after_vectorizer): Use
+       loop->single_exit.
+       (vect_do_peeling_for_loop_bound): Use loop_preheader_edge and
+       loop->single_exit.
+       * tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
+       slpeel_make_loop_iterate_ntimes, slpeel_can_duplicate_loop_p,
+       slpeel_tree_duplicate_loop_to_edge_cfg,
+       slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
+       Use loop_preheader_edge and loop->single_exit.  Do not call
+       flow_loop_scan.
+
 2005-03-01  Nick Clifton  <nickc@redhat.com>
 
        * config/arm/arm.c (thumb_find_work_register): Check all of the
index 40a6de4..96175a8 100644 (file)
@@ -41,11 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define LATCH_EDGE(E) (*(int *) (E)->aux)
 
 static void flow_loops_cfg_dump (const struct loops *, FILE *);
-static void flow_loop_entry_edges_find (struct loop *);
-static void flow_loop_exit_edges_find (struct loop *);
 static int flow_loop_nodes_find (basic_block, struct loop *);
-static void flow_loop_pre_header_scan (struct loop *);
-static basic_block flow_loop_pre_header_find (basic_block);
 static int flow_loop_level_compute (struct loop *);
 static void flow_loops_level_compute (struct loops *);
 static void establish_preds (struct loop *);
@@ -135,27 +131,18 @@ flow_loop_dump (const struct loop *loop, FILE *file,
   fprintf (file, ";;\n;; Loop %d:%s\n", loop->num,
             loop->invalid ? " invalid" : "");
 
-  fprintf (file, ";;  header %d, latch %d, pre-header %d\n",
-          loop->header->index, loop->latch->index,
-          loop->pre_header ? loop->pre_header->index : -1);
+  fprintf (file, ";;  header %d, latch %d\n",
+          loop->header->index, loop->latch->index);
   fprintf (file, ";;  depth %d, level %d, outer %ld\n",
           loop->depth, loop->level,
           (long) (loop->outer ? loop->outer->num : -1));
 
-  if (loop->pre_header_edges)
-    flow_edge_list_print (";;  pre-header edges", loop->pre_header_edges,
-                         loop->num_pre_header_edges, file);
-
-  flow_edge_list_print (";;  entry edges", loop->entry_edges,
-                       loop->num_entries, file);
   fprintf (file, ";;  nodes:");
   bbs = get_loop_body (loop);
   for (i = 0; i < loop->num_nodes; i++)
     fprintf (file, " %d", bbs[i]->index);
   free (bbs);
   fprintf (file, "\n");
-  flow_edge_list_print (";;  exit edges", loop->exit_edges,
-                       loop->num_exits, file);
 
   if (loop_dump_aux)
     loop_dump_aux (loop, file, verbose);
@@ -194,12 +181,6 @@ flow_loops_dump (const struct loops *loops, FILE *file, void (*loop_dump_aux) (c
 void
 flow_loop_free (struct loop *loop)
 {
-  if (loop->pre_header_edges)
-    free (loop->pre_header_edges);
-  if (loop->entry_edges)
-    free (loop->entry_edges);
-  if (loop->exit_edges)
-    free (loop->exit_edges);
   if (loop->pred)
     free (loop->pred);
   free (loop);
@@ -238,95 +219,6 @@ flow_loops_free (struct loops *loops)
     }
 }
 
-/* Find the entry edges into the LOOP.  */
-
-static void
-flow_loop_entry_edges_find (struct loop *loop)
-{
-  edge e;
-  edge_iterator ei;
-  int num_entries;
-
-  num_entries = 0;
-  FOR_EACH_EDGE (e, ei, loop->header->preds)
-    {
-      if (flow_loop_outside_edge_p (loop, e))
-       num_entries++;
-    }
-
-  gcc_assert (num_entries);
-
-  loop->entry_edges = xmalloc (num_entries * sizeof (edge *));
-
-  num_entries = 0;
-  FOR_EACH_EDGE (e, ei, loop->header->preds)
-    {
-      if (flow_loop_outside_edge_p (loop, e))
-       loop->entry_edges[num_entries++] = e;
-    }
-
-  loop->num_entries = num_entries;
-}
-
-/* Find the exit edges from the LOOP.  */
-
-static void
-flow_loop_exit_edges_find (struct loop *loop)
-{
-  edge e;
-  basic_block node, *bbs;
-  unsigned num_exits, i;
-
-  loop->exit_edges = NULL;
-  loop->num_exits = 0;
-
-  /* Check all nodes within the loop to see if there are any
-     successors not in the loop.  Note that a node may have multiple
-     exiting edges.  */
-  num_exits = 0;
-  bbs = get_loop_body (loop);
-  for (i = 0; i < loop->num_nodes; i++)
-    {
-      edge_iterator ei;
-      node = bbs[i];
-      FOR_EACH_EDGE (e, ei, node->succs)
-       {
-         basic_block dest = e->dest;
-
-         if (!flow_bb_inside_loop_p (loop, dest))
-           num_exits++;
-       }
-    }
-
-  if (! num_exits)
-    {
-      free (bbs);
-      return;
-    }
-
-  loop->exit_edges = xmalloc (num_exits * sizeof (edge *));
-
-  /* Store all exiting edges into an array.  */
-  num_exits = 0;
-  for (i = 0; i < loop->num_nodes; i++)
-    {
-      edge_iterator ei;
-      node = bbs[i];
-      FOR_EACH_EDGE (e, ei, node->succs)
-       {
-         basic_block dest = e->dest;
-
-         if (!flow_bb_inside_loop_p (loop, dest))
-           {
-             e->flags |= EDGE_LOOP_EXIT;
-             loop->exit_edges[num_exits++] = e;
-           }
-      }
-    }
-  free (bbs);
-  loop->num_exits = num_exits;
-}
-
 /* Find the nodes contained within the LOOP with header HEADER.
    Return the number of nodes within the loop.  */
 
@@ -434,77 +326,6 @@ mark_single_exit_loops (struct loops *loops)
   loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS;
 }
 
-/* Find the root node of the loop pre-header extended basic block and
-   the edges along the trace from the root node to the loop header.  */
-
-static void
-flow_loop_pre_header_scan (struct loop *loop)
-{
-  int num;
-  basic_block ebb;
-  edge e;
-
-  loop->num_pre_header_edges = 0;
-  if (loop->num_entries != 1)
-    return;
-
-  ebb = loop->entry_edges[0]->src;
-  if (ebb == ENTRY_BLOCK_PTR)
-    return;
-
-  /* Count number of edges along trace from loop header to
-     root of pre-header extended basic block.  Usually this is
-     only one or two edges.  */
-  for (num = 1;
-       EDGE_PRED (ebb, 0)->src != ENTRY_BLOCK_PTR && EDGE_COUNT (ebb->preds) == 1;
-       num++)
-    ebb = EDGE_PRED (ebb, 0)->src;
-
-  loop->pre_header_edges = xmalloc (num * sizeof (edge));
-  loop->num_pre_header_edges = num;
-
-  /* Store edges in order that they are followed.  The source of the first edge
-     is the root node of the pre-header extended basic block and the
-     destination of the last last edge is the loop header.  */
-  for (e = loop->entry_edges[0]; num; e = EDGE_PRED (e->src, 0))
-    loop->pre_header_edges[--num] = e;
-}
-
-/* Return the block for the pre-header of the loop with header
-   HEADER.  Return NULL if there is no pre-header.  */
-
-static basic_block
-flow_loop_pre_header_find (basic_block header)
-{
-  basic_block pre_header;
-  edge e;
-  edge_iterator ei;
-
-  /* If block p is a predecessor of the header and is the only block
-     that the header does not dominate, then it is the pre-header.  */
-  pre_header = NULL;
-  FOR_EACH_EDGE (e, ei, header->preds)
-    {
-      basic_block node = e->src;
-
-      if (node != ENTRY_BLOCK_PTR
-         && ! dominated_by_p (CDI_DOMINATORS, node, header))
-       {
-         if (pre_header == NULL)
-           pre_header = node;
-         else
-           {
-             /* There are multiple edges into the header from outside
-                the loop so there is no pre-header block.  */
-             pre_header = NULL;
-             break;
-           }
-       }
-    }
-
-  return pre_header;
-}
-
 static void
 establish_preds (struct loop *loop)
 {
@@ -602,39 +423,6 @@ flow_loops_level_compute (struct loops *loops)
   flow_loop_level_compute (loops->tree_root);
 }
 
-/* Scan a single natural loop specified by LOOP collecting information
-   about it specified by FLAGS.  */
-
-int
-flow_loop_scan (struct loop *loop, int flags)
-{
-  if (flags & LOOP_ENTRY_EDGES)
-    {
-      /* Find edges which enter the loop header.
-        Note that the entry edges should only
-        enter the header of a natural loop.  */
-      flow_loop_entry_edges_find (loop);
-    }
-
-  if (flags & LOOP_EXIT_EDGES)
-    {
-      /* Find edges which exit the loop.  */
-      flow_loop_exit_edges_find (loop);
-    }
-
-  if (flags & LOOP_PRE_HEADER)
-    {
-      /* Look to see if the loop has a pre-header node.  */
-      loop->pre_header = flow_loop_pre_header_find (loop->header);
-
-      /* Find the blocks within the extended basic block of
-        the loop pre-header.  */
-      flow_loop_pre_header_scan (loop);
-    }
-
-  return 1;
-}
-
 /* A callback to update latch and header info for basic block JUMP created
    by redirecting an edge.  */
 
@@ -800,14 +588,12 @@ initialize_loops_parallel_p (struct loops *loops)
 }
 
 /* Find all the natural loops in the function and save in LOOPS structure and
-   recalculate loop_depth information in basic block structures.  FLAGS
-   controls which loop information is collected.  Return the number of natural
-   loops found.  */
+   recalculate loop_depth information in basic block structures.
+   Return the number of natural loops found.  */
 
 int
-flow_loops_find (struct loops *loops, int flags)
+flow_loops_find (struct loops *loops)
 {
-  int i;
   int b;
   int num_loops;
   edge e;
@@ -817,11 +603,6 @@ flow_loops_find (struct loops *loops, int flags)
   basic_block header;
   basic_block bb;
 
-  /* This function cannot be repeatedly called with different
-     flags to build up the loop information.  The loop tree
-     must always be built if this function is called.  */
-  gcc_assert (flags & LOOP_TREE);
-
   memset (loops, 0, sizeof *loops);
 
   /* We are going to recount the maximum loop depth,
@@ -963,10 +744,6 @@ flow_loops_find (struct loops *loops, int flags)
         loop.  */
       flow_loops_level_compute (loops);
 
-      /* Scan the loops.  */
-      for (i = 1; i < num_loops; i++)
-       flow_loop_scan (loops->parray[i], flags);
-
       loops->num = num_loops;
       initialize_loops_parallel_p (loops);
     }
@@ -1523,3 +1300,12 @@ loop_preheader_edge (const struct loop *loop)
 
   return e;
 }
+
+/* Returns true if E is an exit of LOOP.  */
+
+bool
+loop_exit_edge_p (const struct loop *loop, edge e)
+{
+  return (flow_bb_inside_loop_p (loop, e->src)
+         && !flow_bb_inside_loop_p (loop, e->dest));
+}
index 1562736..224d6cf 100644 (file)
@@ -69,9 +69,6 @@ struct loop
   /* Basic block of loop latch.  */
   basic_block latch;
 
-  /* Basic block of loop preheader or NULL if it does not exist.  */
-  basic_block pre_header;
-
   /* For loop unrolling/peeling decision.  */
   struct lpt_decision lpt_decision;
 
@@ -81,14 +78,6 @@ struct loop
   /* Average number of executed insns per iteration.  */
   unsigned av_ninsns;
 
-  /* Array of edges along the preheader extended basic block trace.
-     The source of the first edge is the root node of preheader
-     extended basic block, if it exists.  */
-  edge *pre_header_edges;
-
-  /* Number of edges along the pre_header extended basic block trace.  */
-  int num_pre_header_edges;
-
   /* The first block in the loop.  This is not necessarily the same as
      the loop header.  */
   basic_block first;
@@ -100,21 +89,6 @@ struct loop
   /* Number of blocks contained within the loop.  */
   unsigned num_nodes;
 
-  /* Array of edges that enter the loop.  */
-  edge *entry_edges;
-
-  /* Number of edges that enter the loop.  */
-  int num_entries;
-
-  /* Array of edges that exit the loop.  */
-  edge *exit_edges;
-
-  /* Number of edges that exit the loop.  */
-  int num_exits;
-
-  /* Bitmap of blocks that dominate all exits of the loop.  */
-  sbitmap exits_doms;
-
   /* The loop nesting depth.  */
   int depth;
 
@@ -254,23 +228,13 @@ struct loops
 
 extern struct loops *current_loops;
 
-/* Flags for loop discovery.  */
-
-#define LOOP_TREE              1       /* Build loop hierarchy tree.  */
-#define LOOP_PRE_HEADER                2       /* Analyze loop preheader.  */
-#define LOOP_ENTRY_EDGES       4       /* Find entry edges.  */
-#define LOOP_EXIT_EDGES                8       /* Find exit edges.  */
-#define LOOP_EDGES             (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES)
-#define LOOP_ALL              15       /* All of the above  */
-
 /* Loop recognition.  */
-extern int flow_loops_find (struct loops *, int flags);
+extern int flow_loops_find (struct loops *);
 extern void flow_loops_free (struct loops *);
 extern void flow_loops_dump (const struct loops *, FILE *,
                             void (*)(const struct loop *, FILE *, int), int);
 extern void flow_loop_dump (const struct loop *, FILE *,
                            void (*)(const struct loop *, FILE *, int), int);
-extern int flow_loop_scan (struct loop *, int);
 extern void flow_loop_free (struct loop *);
 void mark_irreducible_loops (struct loops *);
 void mark_single_exit_loops (struct loops *);
@@ -288,6 +252,8 @@ extern unsigned tree_num_loop_insns (struct loop *);
 extern int num_loop_insns (struct loop *);
 extern int average_num_loop_insns (struct loop *);
 extern unsigned get_loop_level (const struct loop *);
+extern bool loop_exit_edge_p (const struct loop *, edge);
+extern void mark_loop_exit_edges (struct loops *);
 
 /* Loops & cfg manipulation.  */
 extern basic_block *get_loop_body (const struct loop *);
index 6c625d6..f40a48f 100644 (file)
@@ -565,3 +565,32 @@ global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses)
   return cost;
 }
 
+/* Sets EDGE_LOOP_EXIT flag for all exits of LOOPS.  */
+
+void
+mark_loop_exit_edges (struct loops *loops)
+{
+  basic_block bb;
+  edge e;
+  if (loops->num <= 1)
+    return;
+
+  FOR_EACH_BB (bb)
+    {
+      edge_iterator ei;
+
+      /* Do not mark exits from the fake outermost loop.  */
+      if (!bb->loop_father->outer)
+       continue;
+
+      FOR_EACH_EDGE (e, ei, bb->succs)
+       {
+         if (loop_exit_edge_p (bb->loop_father, e))
+           e->flags |= EDGE_LOOP_EXIT;
+         else
+           e->flags &= ~EDGE_LOOP_EXIT;
+       }
+    }
+}
+
index c075710..022624f 100644 (file)
@@ -1296,7 +1296,7 @@ create_loop_notes (void)
                NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
 #endif
 
-  flow_loops_find (&loops, LOOP_TREE);
+  flow_loops_find (&loops);
   free_dominance_info (CDI_DOMINATORS);
   if (loops.num > 1)
     {
index 39fced4..eb597d1 100644 (file)
@@ -110,38 +110,7 @@ static int dead_or_predicable (basic_block, basic_block, basic_block,
                               basic_block, int);
 static void noce_emit_move_insn (rtx, rtx);
 static rtx block_has_only_trap (basic_block);
-static void mark_loop_exit_edges (void);
 \f
-/* Sets EDGE_LOOP_EXIT flag for all loop exits.  */
-static void
-mark_loop_exit_edges (void)
-{
-  struct loops loops;
-  basic_block bb;
-  edge e;
-  
-  flow_loops_find (&loops, LOOP_TREE);
-  free_dominance_info (CDI_DOMINATORS);
-  
-  if (loops.num > 1)
-    {
-      FOR_EACH_BB (bb)
-       {
-         edge_iterator ei;
-         FOR_EACH_EDGE (e, ei, bb->succs)
-           {
-             if (find_common_loop (bb->loop_father, e->dest->loop_father)
-                 != bb->loop_father)
-               e->flags |= EDGE_LOOP_EXIT;
-             else
-               e->flags &= ~EDGE_LOOP_EXIT;
-           }
-       }
-    }
-
-  flow_loops_free (&loops);
-}
-
 /* Count the number of non-jump active insns in BB.  */
 
 static int
@@ -3356,7 +3325,14 @@ if_convert (int x_life_data_ok)
   if ((! targetm.cannot_modify_jumps_p ())
       && (!flag_reorder_blocks_and_partition || !no_new_pseudos
          || !targetm.have_named_sections))
-    mark_loop_exit_edges ();
+    {
+      struct loops loops;
+
+      flow_loops_find (&loops);
+      mark_loop_exit_edges (&loops);
+      flow_loops_free (&loops);
+      free_dominance_info (CDI_DOMINATORS);
+    }
 
   /* Compute postdominators if we think we'll use them.  */
   if (HAVE_conditional_execution || life_data_ok)
index 037be93..909c28d 100644 (file)
@@ -2430,7 +2430,6 @@ perfect_nestify (struct loops *loops,
        }
     }
   free (bbs);
-  flow_loops_find (loops, LOOP_ALL);
   return perfect_nest_p (loop);
 }
 
index 5aa0db1..b6a827c 100644 (file)
@@ -56,7 +56,7 @@ loop_optimizer_init (FILE *dumpfile)
 
   /* Find the loops.  */
 
-  if (flow_loops_find (loops, LOOP_TREE) <= 1)
+  if (flow_loops_find (loops) <= 1)
     {
       /* No loops.  */
       flow_loops_free (loops);
index 4c7f6e2..c4f49d5 100644 (file)
@@ -1669,8 +1669,7 @@ analyze_insns_in_loop (struct loop *loop)
     opt_info->loop_preheader = loop_preheader_edge (loop)->src;
   
   if (n_edges == 1
-      && !(edges[0]->flags & EDGE_COMPLEX)
-      && (edges[0]->flags & EDGE_LOOP_EXIT))
+      && !(edges[0]->flags & EDGE_COMPLEX))
     {
       opt_info->loop_exit = loop_split_edge_with (edges[0], NULL_RTX);
       can_apply = true;
index 956885a..65c183d 100644 (file)
@@ -781,7 +781,7 @@ rest_of_handle_branch_prob (void)
 
   /* 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, LOOP_TREE);
+  flow_loops_find (&loops);
 
   if (dump_file)
     flow_loops_dump (&loops, dump_file, NULL, 0);
index 9ecf1e3..bf594ac 100644 (file)
@@ -583,13 +583,13 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
     {
       basic_block bb, *bbs;
       unsigned j;
-      int exits;
+      unsigned n_exits;
       struct loop *loop = loops_info->parray[i];
       struct niter_desc desc;
       unsigned HOST_WIDE_INT niter;
+      edge *exits;
 
-      flow_loop_scan (loop, LOOP_EXIT_EDGES);
-      exits = loop->num_exits;
+      exits = get_loop_exit_edges (loop, &n_exits);
 
       if (rtlsimpleloops)
        {
@@ -615,11 +615,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
        }
       else
        {
-         edge *exits;
-         unsigned j, n_exits;
          struct tree_niter_desc niter_desc;
 
-         exits = get_loop_exit_edges (loop, &n_exits);
          for (j = 0; j < n_exits; j++)
            {
              tree niter = NULL;
@@ -647,8 +644,8 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
                }
            }
 
-         free (exits);
        }
+      free (exits);
 
       bbs = get_loop_body (loop);
 
@@ -690,7 +687,7 @@ predict_loops (struct loops *loops_info, bool rtlsimpleloops)
                  (e, PRED_LOOP_EXIT,
                   (REG_BR_PROB_BASE
                    - predictor_info [(int) PRED_LOOP_EXIT].hitrate)
-                  / exits);
+                  / n_exits);
        }
       
       /* Free basic blocks from get_loop_body.  */
@@ -1293,7 +1290,7 @@ tree_estimate_probability (void)
   basic_block bb;
   struct loops loops_info;
 
-  flow_loops_find (&loops_info, LOOP_TREE);
+  flow_loops_find (&loops_info);
   if (dump_file && (dump_flags & TDF_DETAILS))
     flow_loops_dump (&loops_info, dump_file, NULL, 0);
 
index 52bcfba..bb832d2 100644 (file)
@@ -126,7 +126,7 @@ static void combine_blocks (struct loop *);
 static tree ifc_temp_var (tree, tree);
 static bool pred_blocks_visited_p (basic_block, bitmap *);
 static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop);
-static bool bb_with_exit_edge_p (basic_block);
+static bool bb_with_exit_edge_p (struct loop *, basic_block);
 
 /* List of basic blocks in if-conversion-suitable order.  */
 static basic_block *ifc_bbs;
@@ -312,7 +312,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
   /* Now this conditional statement is redundant. Remove it.
      But, do not remove exit condition! Update exit condition
      using new condition.  */
-  if (!bb_with_exit_edge_p (bb_for_stmt (stmt)))
+  if (!bb_with_exit_edge_p (loop, bb_for_stmt (stmt)))
     {
       bsi_remove (bsi);
       cond = NULL_TREE;
@@ -405,7 +405,7 @@ if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr)
 
   if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME
       && bb != loop->header
-      && !bb_with_exit_edge_p (bb))
+      && !bb_with_exit_edge_p (loop, bb))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
@@ -534,8 +534,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
       return false;
     }
 
-  flow_loop_scan (loop, LOOP_ALL);
-
   /* If only one block, no need for if-conversion.  */
   if (loop->num_nodes <= 2)
     {
@@ -545,7 +543,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
     }
 
   /* More than one loop exit is too much to handle.  */
-  if (loop->num_exits > 1)
+  if (!loop->single_exit)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "multiple exits\n");
@@ -557,8 +555,10 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
   /* If one of the loop header's edge is exit edge then do not apply
      if-conversion.  */
   FOR_EACH_EDGE (e, ei, loop->header->succs)
-    if ( e->flags & EDGE_LOOP_EXIT)
-      return false;
+    {
+      if (loop_exit_edge_p (loop, e))
+       return false;
+    }
 
   compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL);
 
@@ -593,7 +593,7 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
        if (!if_convertible_phi_p (loop, bb, phi))
          return false;
 
-      if (bb_with_exit_edge_p (bb))
+      if (bb_with_exit_edge_p (loop, bb))
        exit_bb_seen = true;
     }
 
@@ -874,7 +874,7 @@ combine_blocks (struct loop *loop)
 
       bb = ifc_bbs[i];
 
-      if (!exit_bb && bb_with_exit_edge_p (bb))
+      if (!exit_bb && bb_with_exit_edge_p (loop, bb))
          exit_bb = bb;
 
       if (bb == exit_bb)
@@ -890,11 +890,13 @@ combine_blocks (struct loop *loop)
            {
              /* Redirect non-exit edge to loop->latch.  */
              FOR_EACH_EDGE (e, ei, bb->succs)
-               if (!(e->flags & EDGE_LOOP_EXIT))
-                 {
-                   redirect_edge_and_branch (e, loop->latch);
-                   set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
-                 }
+               {
+                 if (!loop_exit_edge_p (loop, e))
+                   {
+                     redirect_edge_and_branch (e, loop->latch);
+                     set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
+                   }
+               }
            }
          continue;
        }
@@ -1056,17 +1058,17 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
   return blocks;
 }
 
-/* Return true if one of the basic block BB edge is loop exit.  */
+/* Return true if one of the basic block BB edge is exit of LOOP.  */
 
 static bool
-bb_with_exit_edge_p (basic_block bb)
+bb_with_exit_edge_p (struct loop *loop, basic_block bb)
 {
   edge e;
   edge_iterator ei;
   bool exit_edge_found = false;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->flags & EDGE_LOOP_EXIT)
+    if (loop_exit_edge_p (loop, e))
       {
        exit_edge_found = true;
        break;
index b8c6201..0333304 100644 (file)
@@ -277,9 +277,8 @@ linear_transform_loops (struct loops *loops)
       depth = 1;
       for (temp = loop_nest->inner; temp; temp = temp->inner)
        {
-         flow_loop_scan (temp, LOOP_ALL);
          /* If we have a sibling loop or multiple exit edges, jump ship.  */
-         if (temp->next || temp->num_exits != 1)
+         if (temp->next || !temp->single_exit)
            {
              problem = true;
              break;
index fd26c90..4736f1b 100644 (file)
@@ -462,7 +462,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
                      "not vectorized: can't create epilog loop 1.");
           return false;
         }
-      if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0]))
+      if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
         {
           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                                      LOOP_LOC (loop_vinfo)))
@@ -2265,7 +2265,6 @@ vect_analyze_loop_form (struct loop *loop)
   loop_vec_info loop_vinfo;
   tree loop_cond;
   tree number_of_iterations = NULL;
-  bool rescan = false;
   LOC loop_loc;
 
   loop_loc = find_loop_location (loop);
@@ -2282,8 +2281,7 @@ vect_analyze_loop_form (struct loop *loop)
   
   if (!loop->single_exit 
       || loop->num_nodes != 2
-      || EDGE_COUNT (loop->header->preds) != 2
-      || loop->num_entries != 1)
+      || EDGE_COUNT (loop->header->preds) != 2)
     {
       if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
         {
@@ -2293,8 +2291,6 @@ vect_analyze_loop_form (struct loop *loop)
             fprintf (vect_dump, "not vectorized: too many BBs in loop.");
           else if (EDGE_COUNT (loop->header->preds) != 2)
             fprintf (vect_dump, "not vectorized: too many incoming edges.");
-          else if (loop->num_entries != 1)
-            fprintf (vect_dump, "not vectorized: too many entries.");
         }
 
       return NULL;
@@ -2311,16 +2307,6 @@ vect_analyze_loop_form (struct loop *loop)
       return NULL;
     }
 
-  /* Make sure we have a preheader basic block.  */
-  if (!loop->pre_header || EDGE_COUNT (loop->pre_header->succs) != 1)
-    {
-      edge e = loop_preheader_edge (loop);
-      loop_split_edge_with (e, NULL);
-      if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
-       fprintf (vect_dump, "split preheader edge.");
-      rescan = true;
-    }
-    
   /* Make sure there exists a single-predecessor exit bb:  */
   if (EDGE_COUNT (loop->single_exit->dest->preds) != 1)
     {
@@ -2330,7 +2316,6 @@ vect_analyze_loop_form (struct loop *loop)
          loop_split_edge_with (e, NULL);
          if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
            fprintf (vect_dump, "split exit edge.");
-         rescan = true;
        }
       else
        {
@@ -2339,13 +2324,6 @@ vect_analyze_loop_form (struct loop *loop)
          return NULL;
        }
     }
-    
-  if (rescan)
-    {
-      flow_loop_scan (loop, LOOP_ALL);
-      /* Flow loop scan does not update loop->single_exit field.  */
-      loop->single_exit = loop->exit_edges[0];
-    }
 
   if (empty_block_p (loop->header))
     {
index 5f71256..1935a73 100644 (file)
@@ -1315,7 +1315,7 @@ vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
                                  edge update_e)
 {
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
-  basic_block exit_bb = loop->exit_edges[0]->dest;
+  basic_block exit_bb = loop->single_exit->dest;
   tree phi, phi1;
   basic_block update_bb = update_e->dest;
 
@@ -1398,6 +1398,7 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   struct loop *new_loop;
   edge update_e;
+  basic_block preheader;
 #ifdef ENABLE_CHECKING
   int loop_num;
 #endif
@@ -1413,14 +1414,10 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
   vect_generate_tmps_on_preheader (loop_vinfo, &ni_name,
                                   &ratio_mult_vf_name, ratio);
 
-  /* Update loop info.  */
-  loop->pre_header = loop_preheader_edge (loop)->src;
-  loop->pre_header_edges[0] = loop_preheader_edge (loop);
-
 #ifdef ENABLE_CHECKING
   loop_num  = loop->num; 
 #endif
-  new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->exit_edges[0],
+  new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
                                            ratio_mult_vf_name, ni_name, false);
 #ifdef ENABLE_CHECKING
   gcc_assert (new_loop);
@@ -1434,10 +1431,11 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
      is a bb after NEW_LOOP, where these IVs are not used.  Find the edge that
      is on the path where the LOOP IVs are used and need to be updated.  */
 
-  if (EDGE_PRED (new_loop->pre_header, 0)->src == loop->exit_edges[0]->dest)
-    update_e = EDGE_PRED (new_loop->pre_header, 0);
+  preheader = loop_preheader_edge (new_loop)->src;
+  if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
+    update_e = EDGE_PRED (preheader, 0);
   else
-    update_e = EDGE_PRED (new_loop->pre_header, 1);
+    update_e = EDGE_PRED (preheader, 1);
 
   /* Update IVs of original loop as if they were advanced 
      by ratio_mult_vf_name steps.  */
index 8c44742..7f8d84a 100644 (file)
@@ -373,7 +373,7 @@ slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop,
   tree def;
   edge orig_loop_latch = loop_latch_edge (orig_loop);
   edge orig_entry_e = loop_preheader_edge (orig_loop);
-  edge new_loop_exit_e = new_loop->exit_edges[0];
+  edge new_loop_exit_e = new_loop->single_exit;
   edge new_loop_entry_e = loop_preheader_edge (new_loop);
   edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e);
 
@@ -518,8 +518,9 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge,
       if (entry_phis)
         {
           loop_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi,
-                                            EDGE_SUCC (loop->latch, 0));
-          guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, loop->entry_edges[0]);
+                                            loop_latch_edge (loop));
+          guard_arg = PHI_ARG_DEF_FROM_EDGE (orig_phi,
+                                            loop_preheader_edge (loop));
         }
       else /* exit phis */
         {
@@ -544,7 +545,7 @@ slpeel_update_phi_nodes_for_guard (edge guard_edge,
               loop_arg = orig_def;
             }
         }
-      add_phi_arg (new_phi, loop_arg, loop->exit_edges[0]);
+      add_phi_arg (new_phi, loop_arg, loop->single_exit);
       add_phi_arg (new_phi, guard_arg, guard_edge);
 
       /* 3. Update phi in successor block.  */
@@ -567,7 +568,7 @@ slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
 {
   tree indx_before_incr, indx_after_incr, cond_stmt, cond;
   tree orig_cond;
-  edge exit_edge = loop->exit_edges[0];
+  edge exit_edge = loop->single_exit;
   block_stmt_iterator loop_cond_bsi;
   block_stmt_iterator incr_bsi;
   bool insert_after;
@@ -636,7 +637,7 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
   basic_block exit_dest; 
   tree phi, phi_arg;
 
-  at_exit = (e == loop->exit_edges[0]); 
+  at_exit = (e == loop->single_exit); 
   if (!at_exit && e != loop_preheader_edge (loop))
     return NULL;
 
@@ -657,20 +658,21 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
       return NULL;
     }
 
-  exit_dest = loop->exit_edges[0]->dest;
+  exit_dest = loop->single_exit->dest;
   was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS, 
                                          exit_dest) == loop->header ? 
                 true : false);
 
   new_bbs = xmalloc (sizeof (basic_block) * loop->num_nodes);
 
-  copy_bbs (bbs, loop->num_nodes, new_bbs, NULL, 0, NULL, NULL);
+  copy_bbs (bbs, loop->num_nodes, new_bbs,
+           &loop->single_exit, 1, &new_loop->single_exit, NULL);
 
   /* Duplicating phi args at exit bbs as coming 
      also from exit of duplicated loop.  */
   for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi))
     {
-      phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->exit_edges[0]);
+      phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->single_exit);
       if (phi_arg)
        {
          edge new_loop_exit_edge;
@@ -720,8 +722,6 @@ slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *loop, struct loops *loops,
       set_immediate_dominator (CDI_DOMINATORS, new_loop->header, preheader);
     }
 
-  flow_loop_scan (new_loop, LOOP_ALL);
-  flow_loop_scan (loop, LOOP_ALL);  
   free (new_bbs);
   free (bbs);
 
@@ -772,7 +772,7 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb,
 bool
 slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
 {
-  edge exit_e = loop->exit_edges [0];
+  edge exit_e = loop->single_exit;
   edge entry_e = loop_preheader_edge (loop);
   tree orig_cond = get_loop_exit_condition (loop);
   block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
@@ -786,8 +786,7 @@ slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
       || !loop->outer
       || loop->num_nodes != 2
       || !empty_block_p (loop->latch)
-      || loop->num_exits != 1
-      || loop->num_entries != 1
+      || !loop->single_exit
       /* Verify that new loop exit condition can be trivially modified.  */
       || (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi))
       || (e != exit_e && e != entry_e))
@@ -801,8 +800,8 @@ void
 slpeel_verify_cfg_after_peeling (struct loop *first_loop,
                                  struct loop *second_loop)
 {
-  basic_block loop1_exit_bb = first_loop->exit_edges[0]->dest;
-  basic_block loop2_entry_bb = second_loop->pre_header;
+  basic_block loop1_exit_bb = first_loop->single_exit->dest;
+  basic_block loop2_entry_bb = loop_preheader_edge (second_loop)->src;
   basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src;
 
   /* A guard that controls whether the second_loop is to be executed or skipped
@@ -812,7 +811,6 @@ slpeel_verify_cfg_after_peeling (struct loop *first_loop,
    */
   gcc_assert (EDGE_COUNT (loop1_exit_bb->succs) == 2);
    
-   
   /* 1. Verify that one of the successors of first_loopt->exit is the preheader
         of second_loop.  */
    
@@ -880,7 +878,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
   basic_block bb_before_second_loop, bb_after_second_loop;
   basic_block bb_before_first_loop;
   basic_block bb_between_loops;
-  edge exit_e = loop->exit_edges [0];
+  edge exit_e = loop->single_exit;
   LOC loop_loc;
   
   if (!slpeel_can_duplicate_loop_p (loop, e))
@@ -961,10 +959,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
 
   bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
   add_bb_to_loop (bb_before_first_loop, first_loop->outer);
-  bb_before_second_loop = split_edge (first_loop->exit_edges[0]);
+  bb_before_second_loop = split_edge (first_loop->single_exit);
   add_bb_to_loop (bb_before_second_loop, first_loop->outer);
-  flow_loop_scan (first_loop, LOOP_ALL);
-  flow_loop_scan (second_loop, LOOP_ALL);
 
   pre_condition =
         build2 (LE_EXPR, boolean_type_node, first_niters, integer_zero_node);
@@ -1000,12 +996,10 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
         orig_exit_bb:
    */
 
-  bb_between_loops = split_edge (first_loop->exit_edges[0]);
+  bb_between_loops = split_edge (first_loop->single_exit);
   add_bb_to_loop (bb_between_loops, first_loop->outer);
-  bb_after_second_loop = split_edge (second_loop->exit_edges[0]);
+  bb_after_second_loop = split_edge (second_loop->single_exit);
   add_bb_to_loop (bb_after_second_loop, second_loop->outer);
-  flow_loop_scan (first_loop, LOOP_ALL);
-  flow_loop_scan (second_loop, LOOP_ALL);
 
   pre_condition = build2 (EQ_EXPR, boolean_type_node, first_niters, niters);
   skip_e = slpeel_add_loop_guard (bb_between_loops, pre_condition,
@@ -1014,8 +1008,8 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
                                      second_loop == new_loop);
 
   /* Flow loop scan does not update loop->single_exit field.  */
-  first_loop->single_exit = first_loop->exit_edges[0];
-  second_loop->single_exit = second_loop->exit_edges[0];
+  first_loop->single_exit = first_loop->single_exit;
+  second_loop->single_exit = second_loop->single_exit;
 
   /* 4. Make first-loop iterate FIRST_NITERS times, if requested.
    */