OSDN Git Service

2011-04-05 Tom de Vries <tom@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / cfgcleanup.c
index 881a4f3..112cb49 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow optimization code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -44,7 +44,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "recog.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "cselib.h"
 #include "params.h"
 #include "tm_p.h"
@@ -209,13 +208,11 @@ mark_effect (rtx exp, regset nonequal)
        {
          dest = XEXP (exp, 0);
          regno = REGNO (dest);
-         CLEAR_REGNO_REG_SET (nonequal, regno);
-         if (regno < FIRST_PSEUDO_REGISTER)
-           {
-             int n = hard_regno_nregs[regno][GET_MODE (dest)];
-             while (--n > 0)
-               CLEAR_REGNO_REG_SET (nonequal, regno + n);
-           }
+         if (HARD_REGISTER_NUM_P (regno))
+           bitmap_clear_range (nonequal, regno,
+                               hard_regno_nregs[regno][GET_MODE (dest)]);
+         else
+           bitmap_clear_bit (nonequal, regno);
        }
       return false;
 
@@ -228,13 +225,11 @@ mark_effect (rtx exp, regset nonequal)
       if (!REG_P (dest))
        return true;
       regno = REGNO (dest);
-      SET_REGNO_REG_SET (nonequal, regno);
-      if (regno < FIRST_PSEUDO_REGISTER)
-       {
-         int n = hard_regno_nregs[regno][GET_MODE (dest)];
-         while (--n > 0)
-           SET_REGNO_REG_SET (nonequal, regno + n);
-       }
+      if (HARD_REGISTER_NUM_P (regno))
+       bitmap_set_range (nonequal, regno,
+                         hard_regno_nregs[regno][GET_MODE (dest)]);
+      else
+       bitmap_set_bit (nonequal, regno);
       return false;
 
     default:
@@ -492,11 +487,17 @@ try_forward_edges (int mode, basic_block b)
                    new_target = NULL;
                  else
                    {
+                     rtx last;
+
                      if (new_locus)
                        locus = new_locus;
 
-                     new_locus = INSN_P (BB_END (target))
-                                 ? INSN_LOCATOR (BB_END (target)) : 0;
+                     last = BB_END (target);
+                     if (DEBUG_INSN_P (last))
+                       last = prev_nondebug_insn (last);
+
+                     new_locus = last && INSN_P (last)
+                                 ? INSN_LOCATOR (last) : 0;
 
                      if (new_locus && locus && !locator_eq (new_locus, locus))
                        new_target = NULL;
@@ -1069,6 +1070,7 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2)
 {
   rtx i1, i2, last1, last2, afterlast1, afterlast2;
   int ninsns = 0;
+  rtx p1;
 
   /* Skip simple jumps at the end of the blocks.  Complex jumps still
      need to be compared for equivalence, which we'll do below.  */
@@ -1117,7 +1119,9 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2)
 
          afterlast1 = last1, afterlast2 = last2;
          last1 = i1, last2 = i2;
-         ninsns++;
+         p1 = PATTERN (i1);
+         if (!(GET_CODE (p1) == USE || GET_CODE (p1) == CLOBBER))
+           ninsns++;
        }
 
       i1 = PREV_INSN (i1);
@@ -1183,12 +1187,20 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1,
 
   while (true)
     {
-      /* Ignore notes.  */
+      /* Ignore notes, except NOTE_INSN_EPILOGUE_BEG.  */
       while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1))
-       i1 = NEXT_INSN (i1);
+       {
+         if (NOTE_P (i1) && NOTE_KIND (i1) == NOTE_INSN_EPILOGUE_BEG)
+           break;
+         i1 = NEXT_INSN (i1);
+       }
 
       while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2))
-       i2 = NEXT_INSN (i2);
+       {
+         if (NOTE_P (i2) && NOTE_KIND (i2) == NOTE_INSN_EPILOGUE_BEG)
+           break;
+         i2 = NEXT_INSN (i2);
+       }
 
       if ((i1 == BB_END (bb1) && !NONDEBUG_INSN_P (i1))
          || (i2 == BB_END (bb2) && !NONDEBUG_INSN_P (i2)))
@@ -1799,7 +1811,6 @@ try_crossjump_bb (int mode, basic_block bb)
   edge e, e2, fallthru;
   bool changed;
   unsigned max, ix, ix2;
-  basic_block ev, ev2;
 
   /* Nothing to do if there is not at least two incoming edges.  */
   if (EDGE_COUNT (bb->preds) < 2)
@@ -1839,9 +1850,9 @@ try_crossjump_bb (int mode, basic_block bb)
   fallthru = find_fallthru_edge (bb->preds);
 
   changed = false;
-  for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); )
+  for (ix = 0; ix < EDGE_COUNT (bb->preds);)
     {
-      e = EDGE_PRED (ev, ix);
+      e = EDGE_PRED (bb, ix);
       ix++;
 
       /* As noted above, first try with the fallthru predecessor (or, a
@@ -1863,7 +1874,6 @@ try_crossjump_bb (int mode, basic_block bb)
            {
              changed = true;
              ix = 0;
-             ev = bb;
              continue;
            }
        }
@@ -1883,10 +1893,9 @@ try_crossjump_bb (int mode, basic_block bb)
       if (EDGE_SUCC (e->src, 0) != e)
        continue;
 
-      for (ix2 = 0, ev2 = bb; ix2 < EDGE_COUNT (ev2->preds); )
+      for (ix2 = 0; ix2 < EDGE_COUNT (bb->preds); ix2++)
        {
-         e2 = EDGE_PRED (ev2, ix2);
-         ix2++;
+         e2 = EDGE_PRED (bb, ix2);
 
          if (e2 == e)
            continue;
@@ -1912,7 +1921,6 @@ try_crossjump_bb (int mode, basic_block bb)
          if (try_crossjump_to_edge (mode, e, e2))
            {
              changed = true;
-             ev2 = bb;
              ix = 0;
              break;
            }
@@ -2101,7 +2109,17 @@ try_head_merge_bb (basic_block bb)
                                       jump, e0->dest, live_union,
                                       NULL, &move_upto);
       if (!moveall)
-       e0_last_head = move_upto;
+       {
+         if (move_upto == NULL_RTX)
+           goto out;
+
+         while (e0_last_head != move_upto)
+           {
+             df_simulate_one_insn_backwards (e0->dest, e0_last_head,
+                                             live_union);
+             e0_last_head = PREV_INSN (e0_last_head);
+           }
+       }
       if (e0_last_head == NULL_RTX)
        goto out;
 
@@ -2318,8 +2336,7 @@ try_optimize_cfg (int mode)
                        }
                    }
                  delete_basic_block (b);
-                 if (!(mode & CLEANUP_CFGLAYOUT))
-                   changed = true;
+                 changed = true;
                  /* Avoid trying to remove ENTRY_BLOCK_PTR.  */
                  b = (c == ENTRY_BLOCK_PTR ? c->next_bb : c);
                  continue;