OSDN Git Service

* config/epiphany/epiphany.c (epiphany_function_value_regno_p):
[pf3gnuchains/gcc-fork.git] / gcc / cfgloopmanip.c
index 69ed980..33bcf4b 100644 (file)
@@ -1,6 +1,6 @@
 /* Loop manipulation code for GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software
-   Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -130,7 +130,7 @@ fix_loop_placement (struct loop *loop)
   struct loop *father = current_loops->tree_root, *act;
   bool ret = false;
 
-  for (i = 0; VEC_iterate (edge, exits, i, e); i++)
+  FOR_EACH_VEC_ELT (edge, exits, i, e)
     {
       act = find_common_loop (loop, e->dest->loop_father);
       if (flow_loop_nested_p (father, act))
@@ -146,7 +146,7 @@ fix_loop_placement (struct loop *loop)
 
       /* The exit edges of LOOP no longer exits its original immediate
         superloops; remove them from the appropriate exit lists.  */
-      for (i = 0; VEC_iterate (edge, exits, i, e); i++)
+      FOR_EACH_VEC_ELT (edge, exits, i, e)
        rescan_loop_exit (e, false, false);
 
       ret = true;
@@ -174,7 +174,7 @@ fix_bb_placements (basic_block from,
 {
   sbitmap in_queue;
   basic_block *queue, *qtop, *qbeg, *qend;
-  struct loop *base_loop;
+  struct loop *base_loop, *target_loop;
   edge e;
 
   /* We pass through blocks back-reachable from FROM, testing whether some
@@ -185,7 +185,11 @@ fix_bb_placements (basic_block from,
      fix_loop_placement.  */
 
   base_loop = from->loop_father;
-  if (base_loop == current_loops->tree_root)
+  /* If we are already in the outermost loop, the basic blocks cannot be moved
+     outside of it.  If FROM is the header of the base loop, it cannot be moved
+     outside of it, either.  In both cases, we can end now.  */
+  if (base_loop == current_loops->tree_root
+      || from == base_loop->header)
     return;
 
   in_queue = sbitmap_alloc (last_basic_block);
@@ -214,12 +218,14 @@ fix_bb_placements (basic_block from,
          /* Subloop header, maybe move the loop upward.  */
          if (!fix_loop_placement (from->loop_father))
            continue;
+         target_loop = loop_outer (from->loop_father);
        }
       else
        {
          /* Ordinary basic block.  */
          if (!fix_bb_placement (from))
            continue;
+         target_loop = from->loop_father;
        }
 
       FOR_EACH_EDGE (e, ei, from->succs)
@@ -248,9 +254,12 @@ fix_bb_placements (basic_block from,
              && (nca == base_loop
                  || nca != pred->loop_father))
            pred = pred->loop_father->header;
-         else if (!flow_loop_nested_p (from->loop_father, pred->loop_father))
+         else if (!flow_loop_nested_p (target_loop, pred->loop_father))
            {
-             /* No point in processing it.  */
+             /* If PRED is already higher in the loop hierarchy than the
+                TARGET_LOOP to that we moved FROM, the change of the position
+                of FROM does not affect the position of PRED, so there is no
+                point in processing it.  */
              continue;
            }
 
@@ -281,6 +290,8 @@ remove_path (edge e)
   int i, nrem, n_bord_bbs;
   sbitmap seen;
   bool irred_invalidated = false;
+  edge_iterator ei;
+  struct loop *l, *f;
 
   if (!can_remove_branch_p (e))
     return false;
@@ -304,10 +315,12 @@ remove_path (edge e)
      we belong to.  In this case first unloop the loops, then proceed
      normally.   We may assume that e->dest is not a header of any loop,
      as it now has exactly one predecessor.  */
-  while (loop_outer (e->src->loop_father)
-        && dominated_by_p (CDI_DOMINATORS,
-                           e->src->loop_father->latch, e->dest))
-    unloop (e->src->loop_father, &irred_invalidated);
+  for (l = e->src->loop_father; loop_outer (l); l = f)
+    {
+      f = loop_outer (l);
+      if (dominated_by_p (CDI_DOMINATORS, l->latch, e->dest))
+        unloop (l, &irred_invalidated);
+    }
 
   /* Identify the path.  */
   nrem = find_path (e, &rem_bbs);
@@ -320,9 +333,13 @@ remove_path (edge e)
   /* Find "border" hexes -- i.e. those with predecessor in removed path.  */
   for (i = 0; i < nrem; i++)
     SET_BIT (seen, rem_bbs[i]->index);
+  if (!irred_invalidated)
+    FOR_EACH_EDGE (ae, ei, e->src->succs)
+      if (ae != e && ae->dest != EXIT_BLOCK_PTR && !TEST_BIT (seen, ae->dest->index)
+         && ae->flags & EDGE_IRREDUCIBLE_LOOP)
+       irred_invalidated = true;
   for (i = 0; i < nrem; i++)
     {
-      edge_iterator ei;
       bb = rem_bbs[i];
       FOR_EACH_EDGE (ae, ei, rem_bbs[i]->succs)
        if (ae->dest != EXIT_BLOCK_PTR && !TEST_BIT (seen, ae->dest->index))
@@ -1271,7 +1288,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
       bb->aux = 0;
 
       dom_bbs = get_dominated_by (CDI_DOMINATORS, bb);
-      for (j = 0; VEC_iterate (basic_block, dom_bbs, j, dominated); j++)
+      FOR_EACH_VEC_ELT (basic_block, dom_bbs, j, dominated)
        {
          if (flow_bb_inside_loop_p (loop, dominated))
            continue;
@@ -1538,7 +1555,10 @@ loop_version (struct loop *loop,
   /* Duplicate loop.  */
   if (!cfg_hook_duplicate_loop_to_header_edge (loop, entry, 1,
                                               NULL, NULL, NULL, 0))
-    return NULL;
+    {
+      entry->flags |= irred_flag;
+      return NULL;
+    }
 
   /* After duplication entry edge now points to new loop head block.
      Note down new head as second_head.  */