OSDN Git Service

* config/darwin.c (machopic_symbol_defined_p): In addition to
[pf3gnuchains/gcc-fork.git] / gcc / cfgloopmanip.c
index e380780..4d4005d 100644 (file)
@@ -821,6 +821,31 @@ can_duplicate_loop_p (struct loop *loop)
   return ret;
 }
 
+/* The NBBS blocks in BBS will get duplicated and the copies will be placed
+   to LOOP.  Update the single_exit information in superloops of LOOP.  */
+
+static void
+update_single_exits_after_duplication (basic_block *bbs, unsigned nbbs,
+                                      struct loop *loop)
+{
+  unsigned i;
+
+  for (i = 0; i < nbbs; i++)
+    bbs[i]->rbi->duplicated = 1;
+
+  for (; loop->outer; loop = loop->outer)
+    {
+      if (!loop->single_exit)
+       continue;
+
+      if (loop->single_exit->src->rbi->duplicated)
+       loop->single_exit = NULL;
+    }
+
+  for (i = 0; i < nbbs; i++)
+    bbs[i]->rbi->duplicated = 0;
+}
+
 
 /* Duplicates body of LOOP to given edge E NDUPL times.  Takes care of updating
    LOOPS structure and dominators.  E's destination must be LOOP header for
@@ -964,6 +989,10 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
       first_active_latch = latch;
     }
 
+  /* Update the information about single exits.  */
+  if (loops->state & LOOPS_HAVE_MARKED_SINGLE_EXITS)
+    update_single_exits_after_duplication (bbs, n, target);
+
   /* Record exit edge in original loop body.  */
   if (orig && TEST_BIT (wont_exit, 0))
     to_remove[(*n_to_remove)++] = orig;
@@ -1242,3 +1271,99 @@ loop_split_edge_with (edge e, rtx insns)
 
   return new_bb;
 }
+
+/* Uses the natural loop discovery to recreate loop notes.  */
+void
+create_loop_notes (void)
+{
+  rtx insn, head, end;
+  struct loops loops;
+  struct loop *loop;
+  basic_block *first, *last, bb, pbb;
+  struct loop **stack, **top;
+
+#ifdef ENABLE_CHECKING
+  /* Verify that there really are no loop notes.  */
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    if (NOTE_P (insn)
+       && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+      abort ();
+#endif
+
+  flow_loops_find (&loops, LOOP_TREE);
+  free_dominance_info (CDI_DOMINATORS);
+  if (loops.num > 1)
+    {
+      last = xcalloc (loops.num, sizeof (basic_block));
+
+      FOR_EACH_BB (bb)
+       {
+         for (loop = bb->loop_father; loop->outer; loop = loop->outer)
+           last[loop->num] = bb;
+       }
+
+      first = xcalloc (loops.num, sizeof (basic_block));
+      stack = xcalloc (loops.num, sizeof (struct loop *));
+      top = stack;
+
+      FOR_EACH_BB (bb)
+       {
+         for (loop = bb->loop_father; loop->outer; loop = loop->outer)
+           {
+             if (!first[loop->num])
+               {
+                 *top++ = loop;
+                 first[loop->num] = bb;
+               }
+
+             if (bb == last[loop->num])
+               {
+                 /* Prevent loops from overlapping.  */
+                 while (*--top != loop)
+                   last[(*top)->num] = EXIT_BLOCK_PTR;
+
+                 /* If loop starts with jump into it, place the note in
+                    front of the jump.  */
+                 insn = PREV_INSN (BB_HEAD (first[loop->num]));
+                 if (insn
+                     && BARRIER_P (insn))
+                   insn = PREV_INSN (insn);
+                 
+                 if (insn
+                     && JUMP_P (insn)
+                     && any_uncondjump_p (insn)
+                     && onlyjump_p (insn))
+                   {
+                     pbb = BLOCK_FOR_INSN (insn);
+                     if (!pbb || !pbb->succ || pbb->succ->succ_next)
+                       abort ();
+
+                     if (!flow_bb_inside_loop_p (loop, pbb->succ->dest))
+                       insn = BB_HEAD (first[loop->num]);
+                   }
+                 else
+                   insn = BB_HEAD (first[loop->num]);
+                   
+                 head = BB_HEAD (first[loop->num]);
+                 emit_note_before (NOTE_INSN_LOOP_BEG, insn);
+                 BB_HEAD (first[loop->num]) = head;
+
+                 /* Position the note correctly wrto barrier.  */
+                 insn = BB_END (last[loop->num]);
+                 if (NEXT_INSN (insn)
+                     && BARRIER_P (NEXT_INSN (insn)))
+                   insn = NEXT_INSN (insn);
+                 
+                 end = BB_END (last[loop->num]);
+                 emit_note_after (NOTE_INSN_LOOP_END, insn);
+                 BB_END (last[loop->num]) = end;
+               }
+           }
+       }
+
+      free (first);
+      free (last);
+      free (stack);
+    }
+  flow_loops_free (&loops);
+}