OSDN Git Service

PR c++/26068
[pf3gnuchains/gcc-fork.git] / gcc / jump.c
index 2bf4b2a..b087394 100644 (file)
@@ -1,6 +1,7 @@
 /* Optimize jump instructions, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
-   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,11 +17,11 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 /* This is the pathetic reminder of old fame of the jump-optimization pass
-   of the compiler.  Now it contains basically set of utility function to
+   of the compiler.  Now it contains basically a set of utility functions to
    operate with jumps.
 
    Each CODE_LABEL has a count of the times it is used
@@ -55,6 +56,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "reload.h"
 #include "predict.h"
 #include "timevar.h"
+#include "tree-pass.h"
+#include "target.h"
 
 /* Optimize jump y; x: ... y: jumpif... x?
    Don't know if it is worth bothering with.  */
@@ -101,7 +104,7 @@ rebuild_jump_labels (rtx f)
    This simple pass moves barriers and removes duplicates so that the
    old code is happy.
  */
-void
+unsigned int
 cleanup_barriers (void)
 {
   rtx insn, next, prev;
@@ -117,10 +120,28 @@ cleanup_barriers (void)
            reorder_insns (insn, insn, prev);
        }
     }
+  return 0;
 }
 
-void
-purge_line_number_notes (rtx f)
+struct tree_opt_pass pass_cleanup_barriers =
+{
+  "barriers",                           /* name */
+  NULL,                                 /* gate */
+  cleanup_barriers,                     /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  0,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* letter */
+};
+
+unsigned int
+purge_line_number_notes (void)
 {
   rtx last_note = 0;
   rtx insn;
@@ -129,7 +150,7 @@ purge_line_number_notes (rtx f)
      extraneous.  There should be some indication where that line belonged,
      even if it became empty.  */
 
-  for (insn = f; insn; insn = NEXT_INSN (insn))
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (NOTE_P (insn))
       {
        if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
@@ -155,7 +176,26 @@ purge_line_number_notes (rtx f)
            last_note = insn;
          }
       }
+  return 0;
 }
+
+struct tree_opt_pass pass_purge_lineno_notes =
+{
+  "elnotes",                            /* name */
+  NULL,                                 /* gate */
+  purge_line_number_notes,              /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  0,                                    /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* letter */
+};
+
 \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
@@ -208,7 +248,7 @@ mark_all_labels (rtx f)
                  {
                    /* But a LABEL_REF around the REG_LABEL note, so
                       that we can canonicalize it.  */
-                   rtx label_ref = gen_rtx_LABEL_REF (VOIDmode,
+                   rtx label_ref = gen_rtx_LABEL_REF (Pmode,
                                                       XEXP (label_note, 0));
 
                    mark_jump_label (label_ref, insn, 0);
@@ -220,11 +260,11 @@ mark_all_labels (rtx f)
       }
 }
 \f
-/* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
-   notes between START and END out before START.  START and END may be such
-   notes.  Returns the values of the new starting and ending insns, which
-   may be different if the original ones were such notes.
-   Return true if there were only such notes and no real instructions.  */
+/* Move all block-beg, block-end and loop-beg notes between START and END out
+   before START.  START and END may be such notes.  Returns the values of the
+   new starting and ending insns, which may be different if the original ones
+   were such notes.  Return true if there were only such notes and no real
+   instructions.  */
 
 bool
 squeeze_notes (rtx* startp, rtx* endp)
@@ -242,9 +282,7 @@ squeeze_notes (rtx* startp, rtx* endp)
       next = NEXT_INSN (insn);
       if (NOTE_P (insn)
          && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
-             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
+             || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
        {
          /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass.  */
          gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
@@ -448,6 +486,20 @@ reversed_comparison_code (rtx comparison, rtx insn)
                                         XEXP (comparison, 0),
                                         XEXP (comparison, 1), insn);
 }
+
+/* Return comparison with reversed code of EXP.
+   Return NULL_RTX in case we fail to do the reversal.  */
+rtx
+reversed_comparison (rtx exp, enum machine_mode mode)
+{
+  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
+  if (reversed_code == UNKNOWN)
+    return NULL_RTX;
+  else
+    return simplify_gen_relational (reversed_code, mode, VOIDmode,
+                                    XEXP (exp, 0), XEXP (exp, 1));
+}
+
 \f
 /* Given an rtx-code for a comparison, return the code for the negated
    comparison.  If no such code exists, return UNKNOWN.
@@ -496,7 +548,7 @@ reverse_condition (enum rtx_code code)
       return UNKNOWN;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -539,7 +591,7 @@ reverse_condition_maybe_unordered (enum rtx_code code)
       return LTGT;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -585,7 +637,7 @@ swap_condition (enum rtx_code code)
       return UNLE;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -616,7 +668,7 @@ unsigned_condition (enum rtx_code code)
       return LEU;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -645,7 +697,7 @@ signed_condition (enum rtx_code code)
       return LE;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 \f
@@ -987,8 +1039,7 @@ sets_cc0_p (rtx x)
    If the chain loops or we can't find end, return LABEL,
    since that tells caller to avoid changing the insn.
 
-   If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or
-   a USE or CLOBBER.  */
+   If RELOAD_COMPLETED is 0, we do not chain across a USE or CLOBBER.  */
 
 rtx
 follow_jumps (rtx label)
@@ -1009,19 +1060,15 @@ follow_jumps (rtx label)
        && BARRIER_P (next));
        depth++)
     {
-      /* Don't chain through the insn that jumps into a loop
-        from outside the loop,
-        since that would create multiple loop entry jumps
-        and prevent loop optimization.  */
       rtx tem;
-      if (!reload_completed)
-       for (tem = value; tem != insn; tem = NEXT_INSN (tem))
-         if (NOTE_P (tem)
-             && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG
-                 /* ??? Optional.  Disables some optimizations, but makes
-                    gcov output more accurate with -O.  */
-                 || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0)))
-           return value;
+      if (!reload_completed && flag_test_coverage)
+       {
+         /* ??? Optional.  Disables some optimizations, but makes
+            gcov output more accurate with -O.  */
+         for (tem = value; tem != insn; tem = NEXT_INSN (tem))
+           if (NOTE_P (tem) && NOTE_LINE_NUMBER (tem) > 0)
+             return value;
+       }
 
       /* If we have found a cycle, make the insn jump to itself.  */
       if (JUMP_LABEL (insn) == label)
@@ -1094,8 +1141,7 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
            && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL)
          break;
 
-       if (!LABEL_P (label))
-         abort ();
+       gcc_assert (LABEL_P (label));
 
        /* Ignore references to labels of containing functions.  */
        if (LABEL_REF_NONLOCAL_P (x))
@@ -1529,7 +1575,7 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
        {
          rtx n;
          if (nlabel)
-           n = gen_rtx_LABEL_REF (VOIDmode, nlabel);
+           n = gen_rtx_LABEL_REF (Pmode, nlabel);
          else
            n = gen_rtx_RETURN (VOIDmode);
 
@@ -1540,7 +1586,7 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
   else if (code == RETURN && olabel == 0)
     {
       if (nlabel)
-       x = gen_rtx_LABEL_REF (VOIDmode, nlabel);
+       x = gen_rtx_LABEL_REF (Pmode, nlabel);
       else
        x = gen_rtx_RETURN (VOIDmode);
       if (loc == &PATTERN (insn))
@@ -1708,14 +1754,19 @@ invert_jump_1 (rtx jump, rtx nlabel)
 {
   rtx x = pc_set (jump);
   int ochanges;
+  int ok;
 
   ochanges = num_validated_changes ();
-  if (!x || !invert_exp_1 (SET_SRC (x), jump))
-    abort ();
+  gcc_assert (x);
+  ok = invert_exp_1 (SET_SRC (x), jump);
+  gcc_assert (ok);
+  
   if (num_validated_changes () == ochanges)
     return 0;
 
-  return redirect_jump_1 (jump, nlabel);
+  /* redirect_jump_1 will fail of nlabel == olabel, and the current use is
+     in Pmode, so checking this is not merely an optimization.  */
+  return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel);
 }
 
 /* Invert the condition of the jump JUMP, and make it jump to label
@@ -1739,15 +1790,7 @@ invert_jump (rtx jump, rtx nlabel, int delete_unused)
 /* Like rtx_equal_p except that it considers two REGs as equal
    if they renumber to the same value and considers two commutative
    operations to be the same if the order of the operands has been
-   reversed.
-
-   ??? Addition is not commutative on the PA due to the weird implicit
-   space register selection rules for memory addresses.  Therefore, we
-   don't consider a + b == b + a.
-
-   We could/should make this test a little tighter.  Possibly only
-   disabling it on the PA via some backend macro or only disabling this
-   case when the PLUS is inside a MEM.  */
+   reversed.  */
 
 int
 rtx_renumbered_equal_p (rtx x, rtx y)
@@ -1831,6 +1874,7 @@ rtx_renumbered_equal_p (rtx x, rtx y)
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
     case CONST_INT:
+    case CONST_DOUBLE:
       return 0;
 
     case LABEL_REF:
@@ -1860,10 +1904,8 @@ rtx_renumbered_equal_p (rtx x, rtx y)
     return 0;
 
   /* For commutative operations, the RTX match if the operand match in any
-     order.  Also handle the simple binary and unary cases without a loop.
-
-     ??? Don't consider PLUS a commutative operator; see comments above.  */
-  if (COMMUTATIVE_P (x) && code != PLUS)
+     order.  Also handle the simple binary and unary cases without a loop.  */
+  if (targetm.commutative_p (x, UNKNOWN))
     return ((rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 0))
             && rtx_renumbered_equal_p (XEXP (x, 1), XEXP (y, 1)))
            || (rtx_renumbered_equal_p (XEXP (x, 0), XEXP (y, 1))
@@ -1924,7 +1966,7 @@ rtx_renumbered_equal_p (rtx x, rtx y)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   return 1;
@@ -1959,9 +2001,8 @@ true_regnum (rtx x)
 unsigned int
 reg_or_subregno (rtx reg)
 {
-  if (REG_P (reg))
-    return REGNO (reg);
   if (GET_CODE (reg) == SUBREG)
-    return REGNO (SUBREG_REG (reg));
-  abort ();
+    reg = SUBREG_REG (reg);
+  gcc_assert (REG_P (reg));
+  return REGNO (reg);
 }