OSDN Git Service

* tree-inline.c (find_builtin_longjmp_call): Save and restore
[pf3gnuchains/gcc-fork.git] / gcc / jump.c
index 65312b4..15c9d36 100644 (file)
@@ -1,6 +1,6 @@
 /* Optimize jump instructions, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
-   1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -36,6 +36,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -51,6 +53,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "reload.h"
 #include "predict.h"
+#include "timevar.h"
 
 /* Optimize jump y; x: ... y: jumpif... x?
    Don't know if it is worth bothering with.  */
@@ -59,7 +62,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    or even change what is live at any point.
    So perhaps let combiner do it.  */
 
-static int init_label_info             PARAMS ((rtx));
+static rtx next_nonnote_insn_in_loop   PARAMS ((rtx));
+static void init_label_info            PARAMS ((rtx));
 static void mark_all_labels            PARAMS ((rtx));
 static int duplicate_loop_exit_test    PARAMS ((rtx));
 static void delete_computation         PARAMS ((rtx));
@@ -78,10 +82,9 @@ rebuild_jump_labels (f)
      rtx f;
 {
   rtx insn;
-  int max_uid = 0;
-
-  max_uid = init_label_info (f) + 1;
 
+  timevar_push (TV_REBUILD_JUMP);
+  init_label_info (f);
   mark_all_labels (f);
 
   /* Keep track of labels used from static data; we don't track them
@@ -91,6 +94,7 @@ rebuild_jump_labels (f)
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
     if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL)
       LABEL_NUSES (XEXP (insn, 0))++;
+  timevar_pop (TV_REBUILD_JUMP);
 }
 \f
 /* Some old code expects exactly one BARRIER as the NEXT_INSN of a
@@ -119,6 +123,27 @@ cleanup_barriers ()
     }
 }
 \f
+/* Return the next insn after INSN that is not a NOTE and is in the loop,
+   i.e. when there is no such INSN before NOTE_INSN_LOOP_END return NULL_RTX.
+   This routine does not look inside SEQUENCEs.  */
+
+static rtx
+next_nonnote_insn_in_loop (insn)
+     rtx insn;
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0 || GET_CODE (insn) != NOTE)
+       break;
+      if (GET_CODE (insn) == NOTE
+         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+       return NULL_RTX;
+    }
+
+  return insn;
+}
+
 void
 copy_loop_headers (f)
      rtx f;
@@ -137,7 +162,7 @@ copy_loop_headers (f)
         the values of regno_first_uid and regno_last_uid.  */
       if (GET_CODE (insn) == NOTE
          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
-         && (temp1 = next_nonnote_insn (insn)) != 0
+         && (temp1 = next_nonnote_insn_in_loop (insn)) != 0
          && any_uncondjump_p (temp1) && onlyjump_p (temp1))
        {
          temp = PREV_INSN (insn);
@@ -186,36 +211,29 @@ purge_line_number_notes (f)
 /* Initialize LABEL_NUSES and JUMP_LABEL fields.  Delete any REG_LABEL
    notes whose labels don't occur in the insn any more.  Returns the
    largest INSN_UID found.  */
-static int
+static void
 init_label_info (f)
      rtx f;
 {
-  int largest_uid = 0;
   rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
-    {
-      if (GET_CODE (insn) == CODE_LABEL)
-       LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
-      else if (GET_CODE (insn) == JUMP_INSN)
-       JUMP_LABEL (insn) = 0;
-      else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
-       {
-         rtx note, next;
-
-         for (note = REG_NOTES (insn); note; note = next)
-           {
-             next = XEXP (note, 1);
-             if (REG_NOTE_KIND (note) == REG_LABEL
-                 && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
-               remove_note (insn, note);
-           }
-       }
-      if (INSN_UID (insn) > largest_uid)
-       largest_uid = INSN_UID (insn);
-    }
+    if (GET_CODE (insn) == CODE_LABEL)
+      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+    else if (GET_CODE (insn) == JUMP_INSN)
+      JUMP_LABEL (insn) = 0;
+    else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+      {
+       rtx note, next;
 
-  return largest_uid;
+       for (note = REG_NOTES (insn); note; note = next)
+         {
+           next = XEXP (note, 1);
+           if (REG_NOTE_KIND (note) == REG_LABEL
+               && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
+             remove_note (insn, note);
+         }
+      }
 }
 
 /* Mark the label each jump jumps to.
@@ -293,7 +311,8 @@ duplicate_loop_exit_test (loop_start)
   rtx insn, set, reg, p, link;
   rtx copy = 0, first_copy = 0;
   int num_insns = 0;
-  rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start)));
+  rtx exitcode
+    = NEXT_INSN (JUMP_LABEL (next_nonnote_insn_in_loop (loop_start)));
   rtx lastexit;
   int max_reg = max_reg_num ();
   rtx *reg_map = 0;
@@ -685,11 +704,7 @@ reversed_comparison_code_parts (code, arg0, arg1, insn)
       break;
     }
 
-  if (GET_MODE_CLASS (mode) == MODE_CC
-#ifdef HAVE_cc0
-      || arg0 == cc0_rtx
-#endif
-      )
+  if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
     {
       rtx prev;
       /* Try to search for the comparison to determine the real mode.
@@ -1397,7 +1412,6 @@ mark_jump_label (x, insn, in_mem)
     case PC:
     case CC0:
     case REG:
-    case SUBREG:
     case CONST_INT:
     case CONST_DOUBLE:
     case CLOBBER:
@@ -1691,9 +1705,9 @@ delete_computation (insn)
 }
 \f
 /* Delete insn INSN from the chain of insns and update label ref counts
-   and delete insns now unreachable. 
+   and delete insns now unreachable.
 
-   Returns the first insn after INSN that was not deleted. 
+   Returns the first insn after INSN that was not deleted.
 
    Usage of this instruction is deprecated.  Use delete_insn instead and
    subsequent cfg_cleanup pass to delete unreachable code if needed.  */
@@ -1878,14 +1892,14 @@ delete_for_peephole (from, to)
      is also an unconditional jump in that case.  */
 }
 \f
-/* We have determined that INSN is never reached, and are about to
-   delete it.  Print a warning if the user asked for one.
+/* We have determined that AVOIDED_INSN is never reached, and are
+   about to delete it.  If the insn chain between AVOIDED_INSN and
+   FINISH contains more than one line from the current function, and
+   contains at least one operation, print a warning if the user asked
+   for it.  If FINISH is NULL, look between AVOIDED_INSN and a LABEL.
 
-   To try to make this warning more useful, this should only be called
-   once per basic block not reached, and it only warns when the basic
-   block contains more than one line from the current function, and
-   contains at least one operation.  CSE and inlining can duplicate insns,
-   so it's possible to get spurious warnings from this.  */
+   CSE and inlining can duplicate insns, so it's possible to get
+   spurious warnings from this.  */
 
 void
 never_reached_warning (avoided_insn, finish)
@@ -1895,15 +1909,16 @@ never_reached_warning (avoided_insn, finish)
   rtx a_line_note = NULL;
   int two_avoided_lines = 0, contains_insn = 0, reached_end = 0;
 
-  if (! warn_notreached)
+  if (!warn_notreached)
     return;
 
-  /* Scan forwards, looking at LINE_NUMBER notes, until
-     we hit a LABEL or we run out of insns.  */
+  /* Scan forwards, looking at LINE_NUMBER notes, until we hit a LABEL
+     in case FINISH is NULL, otherwise until we run out of insns.  */
 
   for (insn = avoided_insn; insn != NULL; insn = NEXT_INSN (insn))
     {
-      if (finish == NULL && GET_CODE (insn) == CODE_LABEL)
+      if ((finish == NULL && GET_CODE (insn) == CODE_LABEL)
+         || GET_CODE (insn) == BARRIER)
        break;
 
       if (GET_CODE (insn) == NOTE              /* A line number note?  */