OSDN Git Service

* config/xtensa/xtensa.md: Remove unused type attributes.
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index 54afcdd..1fe4752 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1,6 +1,6 @@
 /* Common subexpression elimination for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "output.h"
 #include "ggc.h"
+#include "timevar.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -1989,7 +1990,7 @@ remove_invalid_refs (regno)
       {
        next = p->next_same_hash;
        if (GET_CODE (p->exp) != REG
-           && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*)0))
+           && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
          remove_from_table (p, i);
       }
 }
@@ -2019,7 +2020,7 @@ remove_invalid_subreg_refs (regno, offset, mode)
                || (((SUBREG_BYTE (exp)
                      + (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
                    && SUBREG_BYTE (exp) <= end))
-           && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*)0))
+           && refers_to_regno_p (regno, regno + 1, p->exp, (rtx*) 0))
          remove_from_table (p, i);
       }
 }
@@ -2272,10 +2273,10 @@ canon_hash (x, mode)
                || CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno))
                || (SMALL_REGISTER_CLASSES
                    && ! fixed_regs[regno]
-                   && regno != FRAME_POINTER_REGNUM
-                   && regno != HARD_FRAME_POINTER_REGNUM
-                   && regno != ARG_POINTER_REGNUM
-                   && regno != STACK_POINTER_REGNUM
+                   && x != frame_pointer_rtx
+                   && x != hard_frame_pointer_rtx
+                   && x != arg_pointer_rtx
+                   && x != stack_pointer_rtx
                    && GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
          {
            do_not_record = 1;
@@ -2323,6 +2324,22 @@ canon_hash (x, mode)
                 + (unsigned) CONST_DOUBLE_HIGH (x));
       return hash;
 
+    case CONST_VECTOR:
+      {
+       int units;
+       rtx elt;
+
+       units = CONST_VECTOR_NUNITS (x);
+
+       for (i = 0; i < units; ++i)
+         {
+           elt = CONST_VECTOR_ELT (x, i);
+           hash += canon_hash (elt, GET_MODE (elt));
+         }
+
+       return hash;
+      }
+
       /* Assume there is only one rtx object for any given label.  */
     case LABEL_REF:
       hash += ((unsigned) LABEL_REF << 7) + (unsigned long) XEXP (x, 0);
@@ -2776,6 +2793,7 @@ canon_reg (x, insn)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case ADDR_VEC:
@@ -3317,6 +3335,7 @@ fold_rtx (x, insn)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case REG:
@@ -3727,6 +3746,7 @@ fold_rtx (x, insn)
          case SYMBOL_REF:
          case LABEL_REF:
          case CONST_DOUBLE:
+         case CONST_VECTOR:
            const_arg = arg;
            break;
 
@@ -3961,19 +3981,18 @@ fold_rtx (x, insn)
                                        & HASH_MASK), mode_arg0))
                      && p0->first_same_value == p1->first_same_value))
                {
-                  /* Sadly two equal NaNs are not equivalent.  */
-                  if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-                      || ! FLOAT_MODE_P (mode_arg0) 
-                      || flag_unsafe_math_optimizations)
-                     return ((code == EQ || code == LE || code == GE
-                              || code == LEU || code == GEU || code == UNEQ
-                              || code == UNLE || code == UNGE || code == ORDERED)
-                             ? true_rtx : false_rtx);
-                  /* Take care for the FP compares we can resolve.  */
-                  if (code == UNEQ || code == UNLE || code == UNGE)
-                    return true_rtx;
-                  if (code == LTGT || code == LT || code == GT)
-                    return false_rtx;
+                 /* Sadly two equal NaNs are not equivalent.  */
+                 if (!HONOR_NANS (mode_arg0))
+                   return ((code == EQ || code == LE || code == GE
+                            || code == LEU || code == GEU || code == UNEQ
+                            || code == UNLE || code == UNGE
+                            || code == ORDERED)
+                           ? true_rtx : false_rtx);
+                 /* Take care for the FP compares we can resolve.  */
+                 if (code == UNEQ || code == UNLE || code == UNGE)
+                   return true_rtx;
+                 if (code == LTGT || code == LT || code == GT)
+                   return false_rtx;
                }
 
              /* If FOLDED_ARG0 is a register, see if the comparison we are
@@ -5781,10 +5800,11 @@ cse_insn (insn, libcall_insn)
             and hope for the best.  */
          if (n_sets == 1)
            {
-             rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
+             rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
 
              JUMP_LABEL (new) = XEXP (src, 0);
              LABEL_NUSES (XEXP (src, 0))++;
+             delete_insn (insn);
              insn = new;
 
              /* Now emit a BARRIER after the unconditional jump.  */
@@ -5795,7 +5815,7 @@ cse_insn (insn, libcall_insn)
          else
            INSN_CODE (insn) = -1;
 
-         never_reached_warning (insn);
+         never_reached_warning (insn, NULL);
 
          /* Do not bother deleting any unreachable code,
             let jump/flow do that.  */
@@ -5912,9 +5932,7 @@ cse_insn (insn, libcall_insn)
                /* Don't put a hard register source into the table if this is
                   the last insn of a libcall.  In this case, we only need
                   to put src_eqv_elt in src_elt.  */
-               if (GET_CODE (src) != REG
-                   || REGNO (src) >= FIRST_PSEUDO_REGISTER
-                   || ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
+               if (! find_reg_note (insn, REG_RETVAL, NULL_RTX))
                  {
                    struct table_elt *elt;
 
@@ -6427,6 +6445,7 @@ cse_process_notes (x, object)
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case CC0:
     case LO_SUM:
@@ -7418,6 +7437,7 @@ count_reg_usage (x, counts, dest, incr)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
       return;
@@ -7585,81 +7605,42 @@ dead_libcall_p (insn)
    move dead invariants out of loops or make givs for dead quantities.  The
    remaining passes of the compilation are also sped up.  */
 
-void
-delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
+int
+delete_trivially_dead_insns (insns, nreg)
      rtx insns;
      int nreg;
-     int preserve_basic_blocks;
 {
   int *counts;
   rtx insn, prev;
-  int i;
   int in_libcall = 0, dead_libcall = 0;
-  basic_block bb;
+  int ndead = 0, nlastdead, niterations = 0;
 
+  timevar_push (TV_DELETE_TRIVIALLY_DEAD);
   /* First count the number of times each register is used.  */
   counts = (int *) xcalloc (nreg, sizeof (int));
   for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
     count_reg_usage (insn, counts, NULL_RTX, 1);
 
-  /* Go from the last insn to the first and delete insns that only set unused
-     registers or copy a register to itself.  As we delete an insn, remove
-     usage counts for registers it uses.
-
-     The first jump optimization pass may leave a real insn as the last
-     insn in the function.   We must not skip that insn or we may end
-     up deleting code that is not really dead.  */
-  insn = get_last_insn ();
-  if (! INSN_P (insn))
-    insn = prev_real_insn (insn);
-
-  if (!preserve_basic_blocks)
-    for (; insn; insn = prev)
-      {
-       int live_insn = 0;
-
-       prev = prev_real_insn (insn);
-
-       /* Don't delete any insns that are part of a libcall block unless
-          we can delete the whole libcall block.
-
-          Flow or loop might get confused if we did that.  Remember
-          that we are scanning backwards.  */
-       if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
-         {
-           in_libcall = 1;
-           live_insn = 1;
-           dead_libcall = dead_libcall_p (insn);
-         }
-       else if (in_libcall)
-         live_insn = ! dead_libcall;
-       else
-         live_insn = insn_live_p (insn, counts);
-
-       /* If this is a dead insn, delete it and show registers in it aren't
-          being used.  */
-
-       if (! live_insn)
-         {
-           count_reg_usage (insn, counts, NULL_RTX, -1);
-           delete_related_insns (insn);
-         }
+  do
+    {
+      nlastdead = ndead;
+      niterations++;
+      /* Go from the last insn to the first and delete insns that only set unused
+        registers or copy a register to itself.  As we delete an insn, remove
+        usage counts for registers it uses.
+
+        The first jump optimization pass may leave a real insn as the last
+        insn in the function.   We must not skip that insn or we may end
+        up deleting code that is not really dead.  */
+      insn = get_last_insn ();
+      if (! INSN_P (insn))
+       insn = prev_real_insn (insn);
 
-       if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-         {
-           in_libcall = 0;
-           dead_libcall = 0;
-         }
-      }
-  else
-    for (i = 0; i < n_basic_blocks; i++)
-      for (bb = BASIC_BLOCK (i), insn = bb->end; insn != bb->head; insn = prev)
+      for (; insn; insn = prev)
        {
          int live_insn = 0;
 
-         prev = PREV_INSN (insn);
-         if (!INSN_P (insn))
-           continue;
+         prev = prev_real_insn (insn);
 
          /* Don't delete any insns that are part of a libcall block unless
             we can delete the whole libcall block.
@@ -7683,7 +7664,8 @@ delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
          if (! live_insn)
            {
              count_reg_usage (insn, counts, NULL_RTX, -1);
-             delete_insn (insn);
+             delete_insn_and_edges (insn);
+             ndead++;
            }
 
          if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
@@ -7692,7 +7674,13 @@ delete_trivially_dead_insns (insns, nreg, preserve_basic_blocks)
              dead_libcall = 0;
            }
        }
+    } while (ndead != nlastdead);
 
+  if (rtl_dump_file && ndead)
+    fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+            ndead, niterations);
   /* Clean up.  */
   free (counts);
+  timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
+  return ndead;
 }