OSDN Git Service

i386: Rewrite ix86_expand_vshuffle.
[pf3gnuchains/gcc-fork.git] / gcc / cfgloopmanip.c
index 69ed980..1824421 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;
            }
 
@@ -1271,7 +1280,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 +1547,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.  */