OSDN Git Service

* gcc.c-torture/compile/20001226-1.x: Only xfail for Xtensa
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index d6c2025..01a79d5 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1,28 +1,27 @@
 /* Common subexpression elimination for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+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.  */
 
 #include "config.h"
 /* stdio.h must precede rtl.h for FFS.  */
 #include "system.h"
-#include <setjmp.h>
 
 #include "rtl.h"
 #include "tm_p.h"
@@ -38,6 +37,7 @@ Boston, MA 02111-1307, USA.  */
 #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
@@ -346,11 +346,6 @@ static struct cse_reg_info *cached_cse_reg_info;
 
 static HARD_REG_SET hard_regs_in_table;
 
-/* A HARD_REG_SET containing all the hard registers that are invalidated
-   by a CALL_INSN.  */
-
-static HARD_REG_SET regs_invalidated_by_call;
-
 /* CUID of insn that starts the basic block currently being cse-processed.  */
 
 static int cse_basic_block_start;
@@ -382,9 +377,8 @@ static int cse_altered;
 
 static int cse_jumps_altered;
 
-/* Nonzero if we put a LABEL_REF into the hash table.  Since we may have put
-   it into an INSN without a REG_LABEL, we have to rerun jump after CSE
-   to put in the note.  */
+/* Nonzero if we put a LABEL_REF into the hash table for an INSN without a
+   REG_LABEL, we have to rerun jump after CSE to put in the note.  */
 static int recorded_label_ref;
 
 /* canon_hash stores 1 in do_not_record
@@ -689,11 +683,15 @@ static void cse_check_loop_start PARAMS ((rtx, rtx, void *));
 static void cse_set_around_loop        PARAMS ((rtx, rtx, rtx));
 static rtx cse_basic_block     PARAMS ((rtx, rtx, struct branch_path *, int));
 static void count_reg_usage    PARAMS ((rtx, int *, rtx, int));
+static int check_for_label_ref PARAMS ((rtx *, void *));
 extern void dump_class          PARAMS ((struct table_elt*));
 static struct cse_reg_info * get_cse_reg_info PARAMS ((unsigned int));
 static int check_dependence    PARAMS ((rtx *, void *));
 
 static void flush_hash_table   PARAMS ((void));
+static bool insn_live_p                PARAMS ((rtx, int *));
+static bool set_live_p         PARAMS ((rtx, rtx, int *));
+static bool dead_libcall_p     PARAMS ((rtx, int *));
 \f
 /* Dump the expressions in the equivalence class indicated by CLASSP.
    This function is used only for debugging.  */
@@ -715,50 +713,50 @@ dump_class (classp)
 }
 
 /* Subroutine of approx_reg_cost; called through for_each_rtx.  */
+
 static int
 approx_reg_cost_1 (xp, data)
      rtx *xp;
      void *data;
 {
   rtx x = *xp;
-  regset set = (regset) data;
+  int *cost_p = data;
 
   if (x && GET_CODE (x) == REG)
-    SET_REGNO_REG_SET (set, REGNO (x));
+    {
+      unsigned int regno = REGNO (x);
+
+      if (! CHEAP_REGNO (regno))
+       {
+         if (regno < FIRST_PSEUDO_REGISTER)
+           {
+             if (SMALL_REGISTER_CLASSES)
+               return 1;
+             *cost_p += 2;
+           }
+         else
+           *cost_p += 1;
+       }
+    }
+
   return 0;
 }
 
 /* Return an estimate of the cost of the registers used in an rtx.
    This is mostly the number of different REG expressions in the rtx;
-   however for some excecptions like fixed registers we use a cost of
+   however for some exceptions like fixed registers we use a cost of
    0.  If any other hard register reference occurs, return MAX_COST.  */
 
 static int
 approx_reg_cost (x)
      rtx x;
 {
-  regset_head set;
-  int i;
   int cost = 0;
-  int hardregs = 0;
 
-  INIT_REG_SET (&set);
-  for_each_rtx (&x, approx_reg_cost_1, (void *)&set);
+  if (for_each_rtx (&x, approx_reg_cost_1, (void *) &cost))
+    return MAX_COST;
 
-  EXECUTE_IF_SET_IN_REG_SET
-    (&set, 0, i,
-     {
-       if (! CHEAP_REGNO (i))
-        {
-          if (i < FIRST_PSEUDO_REGISTER)
-            hardregs++;
-
-          cost += i < FIRST_PSEUDO_REGISTER ? 2 : 1;
-        }
-     });
-
-  CLEAR_REG_SET (&set);
-  return hardregs && SMALL_REGISTER_CLASSES ? MAX_COST : cost;
+  return cost;
 }
 
 /* Return a negative value if an rtx A, whose costs are given by COST_A
@@ -828,10 +826,10 @@ rtx_cost (x, outer_code)
      rtx x;
      enum rtx_code outer_code ATTRIBUTE_UNUSED;
 {
-  register int i, j;
-  register enum rtx_code code;
-  register const char *fmt;
-  register int total;
+  int i, j;
+  enum rtx_code code;
+  const char *fmt;
+  int total;
 
   if (x == 0)
     return 0;
@@ -843,13 +841,7 @@ rtx_cost (x, outer_code)
   switch (code)
     {
     case MULT:
-      /* Count multiplication by 2**n as a shift,
-        because if we are considering it, we would output it as a shift.  */
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT
-         && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
-       total = 2;
-      else
-       total = COSTS_N_INSNS (5);
+      total = COSTS_N_INSNS (5);
       break;
     case DIV:
     case UDIV:
@@ -907,7 +899,7 @@ rtx_cost (x, outer_code)
 }
 \f
 /* Return cost of address expression X.
-   Expect that X is propertly formed address reference.  */
+   Expect that X is properly formed address reference.  */
 
 int
 address_cost (x, mode)
@@ -987,7 +979,7 @@ get_cse_reg_info (regno)
 static void
 new_basic_block ()
 {
-  register int i;
+  int i;
 
   next_qty = max_reg;
 
@@ -1045,9 +1037,9 @@ make_new_qty (reg, mode)
      unsigned int reg;
      enum machine_mode mode;
 {
-  register int q;
-  register struct qty_table_elem *ent;
-  register struct reg_eqv_elem *eqv;
+  int q;
+  struct qty_table_elem *ent;
+  struct reg_eqv_elem *eqv;
 
   if (next_qty >= max_qty)
     abort ();
@@ -1135,9 +1127,9 @@ static void
 delete_reg_equiv (reg)
      unsigned int reg;
 {
-  register struct qty_table_elem *ent;
-  register int q = REG_QTY (reg);
-  register int p, n;
+  struct qty_table_elem *ent;
+  int q = REG_QTY (reg);
+  int p, n;
 
   /* If invalid, do nothing.  */
   if (q == (int) reg)
@@ -1176,10 +1168,10 @@ static int
 mention_regs (x)
      rtx x;
 {
-  register enum rtx_code code;
-  register int i, j;
-  register const char *fmt;
-  register int changed = 0;
+  enum rtx_code code;
+  int i, j;
+  const char *fmt;
+  int changed = 0;
 
   if (x == 0)
     return 0;
@@ -1217,11 +1209,11 @@ mention_regs (x)
          /* If reg_tick has been incremented more than once since
             reg_in_table was last set, that means that the entire
             register has been set before, so discard anything memorized
-            for the entrire register, including all SUBREG expressions.  */
+            for the entire register, including all SUBREG expressions.  */
          if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
            remove_invalid_refs (i);
          else
-           remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
+           remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
        }
 
       REG_IN_TABLE (i) = REG_TICK (i);
@@ -1242,7 +1234,7 @@ mention_regs (x)
     {
       if (GET_CODE (XEXP (x, 0)) == REG
          && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))
-       if (insert_regs (XEXP (x, 0), NULL_PTR, 0))
+       if (insert_regs (XEXP (x, 0), NULL, 0))
          {
            rehash_using_reg (XEXP (x, 0));
            changed = 1;
@@ -1250,7 +1242,7 @@ mention_regs (x)
 
       if (GET_CODE (XEXP (x, 1)) == REG
          && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1))))
-       if (insert_regs (XEXP (x, 1), NULL_PTR, 0))
+       if (insert_regs (XEXP (x, 1), NULL, 0))
          {
            rehash_using_reg (XEXP (x, 1));
            changed = 1;
@@ -1343,7 +1335,7 @@ insert_regs (x, classp, modified)
   else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
           && ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))
     {
-      insert_regs (SUBREG_REG (x), NULL_PTR, 0);
+      insert_regs (SUBREG_REG (x), NULL, 0);
       mention_regs (x);
       return 1;
     }
@@ -1360,7 +1352,7 @@ insert_regs (x, classp, modified)
 
 static void
 remove_from_table (elt, hash)
-     register struct table_elt *elt;
+     struct table_elt *elt;
      unsigned hash;
 {
   if (elt == 0)
@@ -1372,8 +1364,8 @@ remove_from_table (elt, hash)
   /* Remove the table element from its equivalence class.  */
 
   {
-    register struct table_elt *prev = elt->prev_same_value;
-    register struct table_elt *next = elt->next_same_value;
+    struct table_elt *prev = elt->prev_same_value;
+    struct table_elt *next = elt->next_same_value;
 
     if (next)
       next->prev_same_value = prev;
@@ -1382,7 +1374,7 @@ remove_from_table (elt, hash)
       prev->next_same_value = next;
     else
       {
-       register struct table_elt *newfirst = next;
+       struct table_elt *newfirst = next;
        while (next)
          {
            next->first_same_value = newfirst;
@@ -1394,8 +1386,8 @@ remove_from_table (elt, hash)
   /* Remove the table element from its hash bucket.  */
 
   {
-    register struct table_elt *prev = elt->prev_same_hash;
-    register struct table_elt *next = elt->next_same_hash;
+    struct table_elt *prev = elt->prev_same_hash;
+    struct table_elt *next = elt->next_same_hash;
 
     if (next)
       next->prev_same_hash = prev;
@@ -1420,7 +1412,7 @@ remove_from_table (elt, hash)
 
   if (elt->related_value != 0 && elt->related_value != elt)
     {
-      register struct table_elt *p = elt->related_value;
+      struct table_elt *p = elt->related_value;
 
       while (p->related_value != elt)
        p = p->related_value;
@@ -1449,7 +1441,7 @@ lookup (x, hash, mode)
      unsigned hash;
      enum machine_mode mode;
 {
-  register struct table_elt *p;
+  struct table_elt *p;
 
   for (p = table[hash]; p; p = p->next_same_hash)
     if (mode == p->mode && ((x == p->exp && GET_CODE (x) == REG)
@@ -1468,7 +1460,7 @@ lookup_for_remove (x, hash, mode)
      unsigned hash;
      enum machine_mode mode;
 {
-  register struct table_elt *p;
+  struct table_elt *p;
 
   if (GET_CODE (x) == REG)
     {
@@ -1499,7 +1491,7 @@ lookup_as_function (x, code)
      rtx x;
      enum rtx_code code;
 {
-  register struct table_elt *p
+  struct table_elt *p
     = lookup (x, safe_hash (x, VOIDmode) & HASH_MASK, GET_MODE (x));
 
   /* If we are looking for a CONST_INT, the mode doesn't really matter, as
@@ -1554,12 +1546,12 @@ lookup_as_function (x, code)
 
 static struct table_elt *
 insert (x, classp, hash, mode)
-     register rtx x;
-     register struct table_elt *classp;
+     rtx x;
+     struct table_elt *classp;
      unsigned hash;
      enum machine_mode mode;
 {
-  register struct table_elt *elt;
+  struct table_elt *elt;
 
   /* If X is a register and we haven't made a quantity for it,
      something is wrong.  */
@@ -1577,12 +1569,6 @@ insert (x, classp, hash, mode)
        SET_HARD_REG_BIT (hard_regs_in_table, i);
     }
 
-  /* If X is a label, show we recorded it.  */
-  if (GET_CODE (x) == LABEL_REF
-      || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
-         && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF))
-    recorded_label_ref = 1;
-
   /* Put an element for X into the right hash bucket.  */
 
   elt = free_element_chain;
@@ -1608,8 +1594,8 @@ insert (x, classp, hash, mode)
   elt->is_const = (CONSTANT_P (x)
                   /* GNU C++ takes advantage of this for `this'
                      (and other const values).  */
-                  || (RTX_UNCHANGING_P (x)
-                      && GET_CODE (x) == REG
+                  || (GET_CODE (x) == REG
+                      && RTX_UNCHANGING_P (x)
                       && REGNO (x) >= FIRST_PSEUDO_REGISTER)
                   || FIXED_BASE_PLUS_P (x));
 
@@ -1624,7 +1610,7 @@ insert (x, classp, hash, mode)
       if (CHEAPER (elt, classp))
        /* Insert at the head of the class */
        {
-         register struct table_elt *p;
+         struct table_elt *p;
          elt->next_same_value = classp;
          classp->prev_same_value = elt;
          elt->first_same_value = elt;
@@ -1636,7 +1622,7 @@ insert (x, classp, hash, mode)
        {
          /* Insert not at head of the class.  */
          /* Put it after the last element cheaper than X.  */
-         register struct table_elt *p, *next;
+         struct table_elt *p, *next;
 
          for (p = classp; (next = p->next_same_value) && CHEAPER (next, elt);
               p = next);
@@ -1684,7 +1670,7 @@ insert (x, classp, hash, mode)
           && ! qty_table[REG_QTY (REGNO (x))].const_rtx
           && ! elt->is_const)
     {
-      register struct table_elt *p;
+      struct table_elt *p;
 
       for (p = classp; p != 0; p = p->next_same_value)
        {
@@ -1721,7 +1707,7 @@ insert (x, classp, hash, mode)
          subhash = safe_hash (subexp, mode) & HASH_MASK;
          subelt = lookup (subexp, subhash, mode);
          if (subelt == 0)
-           subelt = insert (subexp, NULL_PTR, subhash, mode);
+           subelt = insert (subexp, NULL, subhash, mode);
          /* Initialize SUBELT's circular chain if it has none.  */
          if (subelt->related_value == 0)
            subelt->related_value = subelt;
@@ -1820,6 +1806,7 @@ struct check_dependence_data
   enum machine_mode mode;
   rtx exp;
 };
+
 static int
 check_dependence (x, data)
      rtx *x;
@@ -1849,8 +1836,8 @@ invalidate (x, full_mode)
      rtx x;
      enum machine_mode full_mode;
 {
-  register int i;
-  register struct table_elt *p;
+  int i;
+  struct table_elt *p;
 
   switch (GET_CODE (x))
     {
@@ -1891,7 +1878,7 @@ invalidate (x, full_mode)
            unsigned int endregno
              = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
            unsigned int tregno, tendregno, rn;
-           register struct table_elt *p, *next;
+           struct table_elt *p, *next;
 
            CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
 
@@ -1950,7 +1937,7 @@ invalidate (x, full_mode)
 
       for (i = 0; i < HASH_SIZE; i++)
        {
-         register struct table_elt *next;
+         struct table_elt *next;
 
          for (p = table[i]; p; p = next)
            {
@@ -1996,38 +1983,37 @@ remove_invalid_refs (regno)
       {
        next = p->next_same_hash;
        if (GET_CODE (p->exp) != REG
-           && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
+           && refers_to_regno_p (regno, regno + 1, p->exp, (rtx *) 0))
          remove_from_table (p, i);
       }
 }
 
-/* Likewise for a subreg with subreg_reg WORD and mode MODE.  */
+/* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
+   and mode MODE.  */
 static void
-remove_invalid_subreg_refs (regno, word, mode)
+remove_invalid_subreg_refs (regno, offset, mode)
      unsigned int regno;
-     unsigned int word;
+     unsigned int offset;
      enum machine_mode mode;
 {
   unsigned int i;
   struct table_elt *p, *next;
-  unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
+  unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
 
   for (i = 0; i < HASH_SIZE; i++)
     for (p = table[i]; p; p = next)
       {
-       rtx exp;
+       rtx exp = p->exp;
        next = p->next_same_hash;
 
-       exp = p->exp;
-       if (GET_CODE (p->exp) != REG
+       if (GET_CODE (exp) != REG
            && (GET_CODE (exp) != SUBREG
                || GET_CODE (SUBREG_REG (exp)) != REG
                || REGNO (SUBREG_REG (exp)) != regno
-               || (((SUBREG_WORD (exp)
-                     + (GET_MODE_SIZE (GET_MODE (exp)) - 1) / UNITS_PER_WORD)
-                    >= word)
-                   && SUBREG_WORD (exp) <= end))
-           && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
+               || (((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))
          remove_from_table (p, i);
       }
 }
@@ -2149,8 +2135,8 @@ use_related_value (x, elt)
      rtx x;
      struct table_elt *elt;
 {
-  register struct table_elt *relt = 0;
-  register struct table_elt *p, *q;
+  struct table_elt *relt = 0;
+  struct table_elt *p, *q;
   HOST_WIDE_INT offset;
 
   /* First, is there anything related known?
@@ -2219,8 +2205,8 @@ canon_hash_string (ps)
      const char *ps;
 {
   unsigned hash = 0;
-  const unsigned char *p = (const unsigned char *)ps;
-  
+  const unsigned char *p = (const unsigned char *) ps;
+
   if (p)
     while (*p)
       hash += *p++;
@@ -2246,10 +2232,10 @@ canon_hash (x, mode)
      rtx x;
      enum machine_mode mode;
 {
-  register int i, j;
-  register unsigned hash = 0;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i, j;
+  unsigned hash = 0;
+  enum rtx_code code;
+  const char *fmt;
 
   /* repeat is used to turn tail-recursion into iteration.  */
  repeat:
@@ -2262,26 +2248,42 @@ canon_hash (x, mode)
     case REG:
       {
        unsigned int regno = REGNO (x);
+       bool record;
 
        /* On some machines, we can't record any non-fixed hard register,
           because extending its life will cause reload problems.  We
-          consider ap, fp, and sp to be fixed for this purpose.
+          consider ap, fp, sp, gp to be fixed for this purpose.
 
           We also consider CCmode registers to be fixed for this purpose;
           failure to do so leads to failure to simplify 0<100 type of
           conditionals.
 
-          On all machines, we can't record any global registers.  */
-
-       if (regno < FIRST_PSEUDO_REGISTER
-           && (global_regs[regno]
-               || (SMALL_REGISTER_CLASSES
-                   && ! fixed_regs[regno]
-                   && regno != FRAME_POINTER_REGNUM
-                   && regno != HARD_FRAME_POINTER_REGNUM
-                   && regno != ARG_POINTER_REGNUM
-                   && regno != STACK_POINTER_REGNUM
-                   && GET_MODE_CLASS (GET_MODE (x)) != MODE_CC)))
+          On all machines, we can't record any global registers.
+          Nor should we record any register that is in a small
+          class, as defined by CLASS_LIKELY_SPILLED_P.  */
+
+       if (regno >= FIRST_PSEUDO_REGISTER)
+         record = true;
+       else if (x == frame_pointer_rtx
+                || x == hard_frame_pointer_rtx
+                || x == arg_pointer_rtx
+                || x == stack_pointer_rtx
+                || x == pic_offset_table_rtx)
+         record = true;
+       else if (global_regs[regno])
+         record = false;
+       else if (fixed_regs[regno])
+         record = true;
+       else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
+         record = true;
+       else if (SMALL_REGISTER_CLASSES)
+         record = false;
+       else if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (regno)))
+         record = false;
+       else
+         record = true;
+           
+       if (!record)
          {
            do_not_record = 1;
            return 0;
@@ -2299,7 +2301,8 @@ canon_hash (x, mode)
        if (GET_CODE (SUBREG_REG (x)) == REG)
          {
            hash += (((unsigned) SUBREG << 7)
-                    + REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+                    + REGNO (SUBREG_REG (x))
+                    + (SUBREG_BYTE (x) / UNITS_PER_WORD));
            return hash;
          }
        break;
@@ -2327,6 +2330,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);
@@ -2362,7 +2381,7 @@ canon_hash (x, mode)
       if (GET_CODE (XEXP (x, 0)) == MEM
          && ! MEM_VOLATILE_P (XEXP (x, 0)))
        {
-         hash += (unsigned)USE;
+         hash += (unsigned) USE;
          x = XEXP (x, 0);
 
          if (! RTX_UNCHANGING_P (x) || FIXED_BASE_PLUS_P (XEXP (x, 0)))
@@ -2453,7 +2472,7 @@ canon_hash (x, mode)
        hash += canon_hash_string (XSTR (x, i));
       else if (fmt[i] == 'i')
        {
-         register unsigned tem = XINT (x, i);
+         unsigned tem = XINT (x, i);
          hash += tem;
        }
       else if (fmt[i] == '0' || fmt[i] == 't')
@@ -2501,9 +2520,9 @@ exp_equiv_p (x, y, validate, equal_values)
      int validate;
      int equal_values;
 {
-  register int i, j;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i, j;
+  enum rtx_code code;
+  const char *fmt;
 
   /* Note: it is incorrect to assume an expression is equivalent to itself
      if VALIDATE is nonzero.  */
@@ -2692,7 +2711,7 @@ exp_equiv_p (x, y, validate, equal_values)
 
 static int
 cse_rtx_varies_p (x, from_alias)
-     register rtx x;
+     rtx x;
      int from_alias;
 {
   /* We need not check for X and the equivalence class being of the same
@@ -2765,9 +2784,9 @@ canon_reg (x, insn)
      rtx x;
      rtx insn;
 {
-  register int i;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  enum rtx_code code;
+  const char *fmt;
 
   if (x == 0)
     return x;
@@ -2780,6 +2799,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:
@@ -2788,9 +2808,9 @@ canon_reg (x, insn)
 
     case REG:
       {
-       register int first;
-       register int q;
-       register struct qty_table_elem *ent;
+       int first;
+       int q;
+       struct qty_table_elem *ent;
 
        /* Never replace a hard reg, because hard regs can appear
           in more than one machine mode, and we must preserve the mode
@@ -2816,7 +2836,7 @@ canon_reg (x, insn)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      register int j;
+      int j;
 
       if (fmt[i] == 'e')
        {
@@ -2975,7 +2995,7 @@ find_best_addr (insn, loc, mode)
                     || exp_equiv_p (p->exp, p->exp, 1, 0))
                    && ((exp_cost = address_cost (p->exp, mode)) < best_addr_cost
                        || (exp_cost == best_addr_cost
-                           && (p->cost + 1) >> 1 < best_rtx_cost)))
+                           && ((p->cost + 1) >> 1) > best_rtx_cost)))
                  {
                    found_better = 1;
                    best_addr_cost = exp_cost;
@@ -3223,7 +3243,7 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
 #ifdef FLOAT_STORE_FLAG_VALUE
                    || (code == GE
                        && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                       && (REAL_VALUE_NEGATIVE
+                       && (REAL_VALUE_NEGATIVE
                            (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
 #endif
                    )
@@ -3251,15 +3271,17 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
       /* If we need to reverse the comparison, make sure that that is
         possible -- we can't necessarily infer the value of GE from LT
         with floating-point operands.  */
-      if (reverse_code && ! can_reverse_comparison_p (x, NULL_RTX))
-       break;
-
-      arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
-      if (GET_RTX_CLASS (GET_CODE (x)) == '<')
-       code = GET_CODE (x);
-
       if (reverse_code)
-       code = reverse_condition (code);
+       {
+         enum rtx_code reversed = reversed_comparison_code (x, NULL_RTX);
+         if (reversed == UNKNOWN)
+           break;
+         else
+           code = reversed;
+       }
+      else if (GET_RTX_CLASS (GET_CODE (x)) == '<')
+       code = GET_CODE (x);
+      arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
     }
 
   /* Return our results.  Return the modes from before fold_rtx
@@ -3288,10 +3310,10 @@ fold_rtx (x, insn)
      rtx x;
      rtx insn;
 {
-  register enum rtx_code code;
-  register enum machine_mode mode;
-  register const char *fmt;
-  register int i;
+  enum rtx_code code;
+  enum machine_mode mode;
+  const char *fmt;
+  int i;
   rtx new = 0;
   int copied = 0;
   int must_swap = 0;
@@ -3320,6 +3342,7 @@ fold_rtx (x, insn)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
     case REG:
@@ -3341,7 +3364,7 @@ fold_rtx (x, insn)
     case PC:
       /* If the next insn is a CODE_LABEL followed by a jump table,
         PC's value is a LABEL_REF pointing to that label.  That
-        lets us fold switch statements on the Vax.  */
+        lets us fold switch statements on the VAX.  */
       if (insn && GET_CODE (insn) == JUMP_INSN)
        {
          rtx next = next_nonnote_insn (insn);
@@ -3404,15 +3427,8 @@ fold_rtx (x, insn)
 
       if (folded_arg0 != SUBREG_REG (x))
        {
-         new = 0;
-
-         if (GET_MODE_CLASS (mode) == MODE_INT
-             && GET_MODE_SIZE (mode) == UNITS_PER_WORD
-             && GET_MODE (SUBREG_REG (x)) != VOIDmode)
-           new = operand_subword (folded_arg0, SUBREG_WORD (x), 0,
-                                  GET_MODE (SUBREG_REG (x)));
-         if (new == 0 && subreg_lowpart_p (x))
-           new = gen_lowpart_if_possible (mode, folded_arg0);
+         new = simplify_subreg (mode, folded_arg0,
+                                GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
          if (new)
            return new;
        }
@@ -3456,7 +3472,9 @@ fold_rtx (x, insn)
                  && GET_CODE (elt->exp) != SIGN_EXTEND
                  && GET_CODE (elt->exp) != ZERO_EXTEND
                  && GET_CODE (XEXP (elt->exp, 0)) == SUBREG
-                 && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode)
+                 && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode
+                 && (GET_MODE_CLASS (mode)
+                     == GET_MODE_CLASS (GET_MODE (XEXP (elt->exp, 0)))))
                {
                  rtx op0 = SUBREG_REG (XEXP (elt->exp, 0));
 
@@ -3737,6 +3755,7 @@ fold_rtx (x, insn)
          case SYMBOL_REF:
          case LABEL_REF:
          case CONST_DOUBLE:
+         case CONST_VECTOR:
            const_arg = arg;
            break;
 
@@ -3798,7 +3817,7 @@ fold_rtx (x, insn)
        replacements[0] = cheap_arg;
        replacements[1] = expensive_arg;
 
-       for (j = 0; j < 2 && replacements[j];  j++)
+       for (j = 0; j < 2 && replacements[j]; j++)
          {
            int old_cost = COST_IN (XEXP (x, i), code);
            int new_cost = COST_IN (replacements[j], code);
@@ -3855,7 +3874,7 @@ fold_rtx (x, insn)
                            || (GET_CODE (const_arg0) == CONST_INT
                                && GET_CODE (const_arg1) != CONST_INT))))
        {
-         register rtx tem = XEXP (x, 0);
+         rtx tem = XEXP (x, 0);
 
          if (insn == 0 && ! copied)
            {
@@ -3909,15 +3928,15 @@ fold_rtx (x, insn)
       if (const_arg0 == 0 || const_arg1 == 0)
        {
          struct table_elt *p0, *p1;
-         rtx true = const_true_rtx, false = const0_rtx;
+         rtx true_rtx = const_true_rtx, false_rtx = const0_rtx;
          enum machine_mode mode_arg1;
 
 #ifdef FLOAT_STORE_FLAG_VALUE
          if (GET_MODE_CLASS (mode) == MODE_FLOAT)
            {
-             true = (CONST_DOUBLE_FROM_REAL_VALUE
-                     (FLOAT_STORE_FLAG_VALUE (mode), mode));
-             false = CONST0_RTX (mode);
+             true_rtx = (CONST_DOUBLE_FROM_REAL_VALUE
+                         (FLOAT_STORE_FLAG_VALUE (mode), mode));
+             false_rtx = CONST0_RTX (mode);
            }
 #endif
 
@@ -3951,9 +3970,9 @@ fold_rtx (x, insn)
                      || GET_CODE (folded_arg0) == CONST))
                {
                  if (code == EQ)
-                   return false;
+                   return false_rtx;
                  else if (code == NE)
-                   return true;
+                   return true_rtx;
                }
 
              /* See if the two operands are the same.  */
@@ -3971,18 +3990,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_fast_math)
-                     return ((code == EQ || code == LE || code == GE
-                              || code == LEU || code == GEU || code == UNEQ
-                              || code == UNLE || code == UNGE || code == ORDERED)
-                             ? true : false);
-                  /* Take care for the FP compares we can resolve.  */
-                  if (code == UNEQ || code == UNLE || code == UNGE)
-                    return true;
-                  if (code == LTGT || code == LT || code == GT)
-                    return false;
+                 /* 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
@@ -4007,7 +4026,7 @@ fold_rtx (x, insn)
                              || (GET_CODE (folded_arg1) == REG
                                  && (REG_QTY (REGNO (folded_arg1)) == ent->comparison_qty))))
                        return (comparison_dominates_p (ent->comparison_code, code)
-                               ? true : false);
+                               ? true_rtx : false_rtx);
                    }
                }
            }
@@ -4031,30 +4050,30 @@ fold_rtx (x, insn)
              int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum
                              && (INTVAL (inner_const)
                                  & ((HOST_WIDE_INT) 1 << sign_bitnum)));
-             rtx true = const_true_rtx, false = const0_rtx;
+             rtx true_rtx = const_true_rtx, false_rtx = const0_rtx;
 
 #ifdef FLOAT_STORE_FLAG_VALUE
              if (GET_MODE_CLASS (mode) == MODE_FLOAT)
                {
-                 true = (CONST_DOUBLE_FROM_REAL_VALUE
+                 true_rtx = (CONST_DOUBLE_FROM_REAL_VALUE
                          (FLOAT_STORE_FLAG_VALUE (mode), mode));
-                 false = CONST0_RTX (mode);
+                 false_rtx = CONST0_RTX (mode);
                }
 #endif
 
              switch (code)
                {
                case EQ:
-                 return false;
+                 return false_rtx;
                case NE:
-                 return true;
+                 return true_rtx;
                case LT:  case LE:
                  if (has_sign)
-                   return true;
+                   return true_rtx;
                  break;
                case GT:  case GE:
                  if (has_sign)
-                   return false;
+                   return false_rtx;
                  break;
                default:
                  break;
@@ -4141,7 +4160,7 @@ fold_rtx (x, insn)
             CONST_INT, see if we can find a register equivalent to the
             positive constant.  Make a MINUS if so.  Don't do this for
             a non-negative constant since we might then alternate between
-            chosing positive and negative constants.  Having the positive
+            choosing positive and negative constants.  Having the positive
             constant previously-used is the more common case.  Be sure
             the resulting constant is non-negative; if const_arg1 were
             the smallest negative number this would overflow: depending
@@ -4372,7 +4391,7 @@ equiv_constant (x)
 rtx
 gen_lowpart_if_possible (mode, x)
      enum machine_mode mode;
-     register rtx x;
+     rtx x;
 {
   rtx result = gen_lowpart_common (mode, x);
 
@@ -4381,7 +4400,7 @@ gen_lowpart_if_possible (mode, x)
   else if (GET_CODE (x) == MEM)
     {
       /* This is the only other case we handle.  */
-      register int offset = 0;
+      int offset = 0;
       rtx new;
 
       if (WORDS_BIG_ENDIAN)
@@ -4392,10 +4411,11 @@ gen_lowpart_if_possible (mode, x)
           unchanged.  */
        offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
                   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
-      new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
+
+      new = adjust_address_nv (x, mode, offset);
       if (! memory_address_p (mode, XEXP (new, 0)))
        return 0;
-      MEM_COPY_ATTRIBUTES (new, x);
+
       return new;
     }
   else
@@ -4446,8 +4466,7 @@ record_jump_equiv (insn, taken)
   code = find_comparison_args (code, &op0, &op1, &mode0, &mode1);
   if (! cond_known_true)
     {
-      reversed_nonequality = (code != EQ && code != NE);
-      code = reverse_condition (code);
+      code = reversed_comparison_code_parts (code, op0, op1, insn);
 
       /* Don't remember if we can't find the inverse.  */
       if (code == UNKNOWN)
@@ -4596,7 +4615,7 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
         new quantity number.  */
       if (op0_elt == 0)
        {
-         if (insert_regs (op0, NULL_PTR, 0))
+         if (insert_regs (op0, NULL, 0))
            {
              rehash_using_reg (op0);
              op0_hash = HASH (op0, mode);
@@ -4608,7 +4627,7 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
                op1_hash = HASH (op1,mode);
            }
 
-         op0_elt = insert (op0, NULL_PTR, op0_hash, mode);
+         op0_elt = insert (op0, NULL, op0_hash, mode);
          op0_elt->in_memory = op0_in_memory;
        }
 
@@ -4624,13 +4643,13 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
          /* Put OP1 in the hash table so it gets a new quantity number.  */
          if (op1_elt == 0)
            {
-             if (insert_regs (op1, NULL_PTR, 0))
+             if (insert_regs (op1, NULL, 0))
                {
                  rehash_using_reg (op1);
                  op1_hash = HASH (op1, mode);
                }
 
-             op1_elt = insert (op1, NULL_PTR, op1_hash, mode);
+             op1_elt = insert (op1, NULL, op1_hash, mode);
              op1_elt->in_memory = op1_in_memory;
            }
 
@@ -4651,25 +4670,25 @@ record_jump_cond (code, mode, op0, op1, reversed_nonequality)
 
   if (op0_elt == 0)
     {
-      if (insert_regs (op0, NULL_PTR, 0))
+      if (insert_regs (op0, NULL, 0))
        {
          rehash_using_reg (op0);
          op0_hash = HASH (op0, mode);
        }
 
-      op0_elt = insert (op0, NULL_PTR, op0_hash, mode);
+      op0_elt = insert (op0, NULL, op0_hash, mode);
       op0_elt->in_memory = op0_in_memory;
     }
 
   if (op1_elt == 0)
     {
-      if (insert_regs (op1, NULL_PTR, 0))
+      if (insert_regs (op1, NULL, 0))
        {
          rehash_using_reg (op1);
          op1_hash = HASH (op1, mode);
        }
 
-      op1_elt = insert (op1, NULL_PTR, op1_hash, mode);
+      op1_elt = insert (op1, NULL, op1_hash, mode);
       op1_elt->in_memory = op1_in_memory;
     }
 
@@ -4725,10 +4744,10 @@ cse_insn (insn, libcall_insn)
      rtx insn;
      rtx libcall_insn;
 {
-  register rtx x = PATTERN (insn);
-  register int i;
+  rtx x = PATTERN (insn);
+  int i;
   rtx tem;
-  register int n_sets = 0;
+  int n_sets = 0;
 
 #ifdef HAVE_cc0
   /* Records what this insn does to set CC0.  */
@@ -4742,7 +4761,7 @@ cse_insn (insn, libcall_insn)
   int src_eqv_in_memory = 0;
   unsigned src_eqv_hash = 0;
 
-  struct set *sets = (struct set *) NULL_PTR;
+  struct set *sets = (struct set *) 0;
 
   this_insn = insn;
 
@@ -4754,8 +4773,11 @@ cse_insn (insn, libcall_insn)
   if (GET_CODE (insn) == CALL_INSN)
     {
       for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
-       if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
-         invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
+       {
+         if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
+           invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
+         XEXP (tem, 0) = canon_reg (XEXP (tem, 0), insn);
+       }
     }
 
   if (GET_CODE (x) == SET)
@@ -4793,7 +4815,7 @@ cse_insn (insn, libcall_insn)
     }
   else if (GET_CODE (x) == PARALLEL)
     {
-      register int lim = XVECLEN (x, 0);
+      int lim = XVECLEN (x, 0);
 
       sets = (struct set *) alloca (lim * sizeof (struct set));
 
@@ -4810,7 +4832,7 @@ cse_insn (insn, libcall_insn)
         anything in that case.  */
       for (i = 0; i < lim; i++)
        {
-         register rtx y = XVECEXP (x, 0, i);
+         rtx y = XVECEXP (x, 0, i);
          if (GET_CODE (y) == CLOBBER)
            {
              rtx clobbered = XEXP (y, 0);
@@ -4826,7 +4848,7 @@ cse_insn (insn, libcall_insn)
 
       for (i = 0; i < lim; i++)
        {
-         register rtx y = XVECEXP (x, 0, i);
+         rtx y = XVECEXP (x, 0, i);
          if (GET_CODE (y) == SET)
            {
              /* As above, we ignore unconditional jumps and call-insns and
@@ -4893,7 +4915,10 @@ cse_insn (insn, libcall_insn)
       && (tem = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0
       && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
          || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
-    src_eqv = canon_reg (XEXP (tem, 0), NULL_RTX);
+    {
+      src_eqv = fold_rtx (canon_reg (XEXP (tem, 0), NULL_RTX), insn);
+      XEXP (tem, 0) = src_eqv;
+    }
 
   /* Canonicalize sources and addresses of destinations.
      We do this in a separate pass to avoid problems when a MATCH_DUP is
@@ -4958,9 +4983,9 @@ cse_insn (insn, libcall_insn)
 
   for (i = 0; i < n_sets; i++)
     {
-      register rtx src, dest;
-      register rtx src_folded;
-      register struct table_elt *elt = 0, *p;
+      rtx src, dest;
+      rtx src_folded;
+      struct table_elt *elt = 0, *p;
       enum machine_mode mode;
       rtx src_eqv_here;
       rtx src_const = 0;
@@ -4997,7 +5022,6 @@ cse_insn (insn, libcall_insn)
            eqvmode = GET_MODE (SUBREG_REG (XEXP (dest, 0)));
          do_not_record = 0;
          hash_arg_in_memory = 0;
-         src_eqv = fold_rtx (src_eqv, insn);
          src_eqv_hash = HASH (src_eqv, eqvmode);
 
          /* Find the equivalence class for the equivalent expression.  */
@@ -5057,18 +5081,16 @@ cse_insn (insn, libcall_insn)
       sets[i].src_in_memory = hash_arg_in_memory;
 
       /* If SRC is a MEM, there is a REG_EQUIV note for SRC, and DEST is
-        a pseudo that is set more than once, do not record SRC.  Using
-        SRC as a replacement for anything else will be incorrect in that
-        situation.  Note that this usually occurs only for stack slots,
-        in which case all the RTL would be referring to SRC, so we don't
-        lose any optimization opportunities by not having SRC in the
-        hash table.  */
+        a pseudo, do not record SRC.  Using SRC as a replacement for
+        anything else will be incorrect in that situation.  Note that
+        this usually occurs only for stack slots, in which case all the
+        RTL would be referring to SRC, so we don't lose any optimization
+        opportunities by not having SRC in the hash table.  */
 
       if (GET_CODE (src) == MEM
-         && find_reg_note (insn, REG_EQUIV, src) != 0
+         && find_reg_note (insn, REG_EQUIV, NULL_RTX) != 0
          && GET_CODE (dest) == REG
-         && REGNO (dest) >= FIRST_PSEUDO_REGISTER
-         && REG_N_SETS (REGNO (dest)) != 1)
+         && REGNO (dest) >= FIRST_PSEUDO_REGISTER)
        sets[i].src_volatile = 1;
 
 #if 0
@@ -5458,13 +5480,13 @@ cse_insn (insn, libcall_insn)
              continue;
            }
 
-          if (elt)
+         if (elt)
            {
              src_elt_cost = elt->cost;
              src_elt_regcost = elt->regcost;
            }
 
-          /* Find cheapest and skip it for the next time.   For items
+         /* Find cheapest and skip it for the next time.   For items
             of equal cost, use this order:
             src_folded, src, src_eqv, src_related and hash table entry.  */
          if (src_folded
@@ -5498,7 +5520,7 @@ cse_insn (insn, libcall_insn)
          else if (src_related
                   && preferrable (src_related_cost, src_related_regcost,
                                   src_elt_cost, src_elt_regcost) <= 0)
-           trial = copy_rtx (src_related), src_related_cost = MAX_COST;
+           trial = copy_rtx (src_related), src_related_cost = MAX_COST;
          else
            {
              trial = copy_rtx (elt->exp);
@@ -5510,31 +5532,17 @@ cse_insn (insn, libcall_insn)
             check for this separately here.  We will delete such an
             insn below.
 
-            Tablejump insns contain a USE of the table, so simply replacing
-            the operand with the constant won't match.  This is simply an
-            unconditional branch, however, and is therefore valid.  Just
-            insert the substitution here and we will delete and re-emit
-            the insn later.  */
-
+            For other cases such as a table jump or conditional jump
+            where we know the ultimate target, go ahead and replace the
+            operand.  While that may not make a valid insn, we will
+            reemit the jump below (and also insert any necessary
+            barriers).  */
          if (n_sets == 1 && dest == pc_rtx
              && (trial == pc_rtx
                  || (GET_CODE (trial) == LABEL_REF
                      && ! condjump_p (insn))))
            {
-             if (trial == pc_rtx)
-               {
-                 SET_SRC (sets[i].rtl) = trial;
-                 cse_jumps_altered = 1;
-                 break;
-               }
-
-             PATTERN (insn) = gen_jump (XEXP (trial, 0));
-             INSN_CODE (insn) = -1;
-
-             if (NEXT_INSN (insn) != 0
-                 && GET_CODE (NEXT_INSN (insn)) != BARRIER)
-               emit_barrier_after (insn);
-
+             SET_SRC (sets[i].rtl) = trial;
              cse_jumps_altered = 1;
              break;
            }
@@ -5670,20 +5678,14 @@ cse_insn (insn, libcall_insn)
                && GET_CODE (XEXP (XEXP (src_const, 0), 0)) == LABEL_REF
                && GET_CODE (XEXP (XEXP (src_const, 0), 1)) == LABEL_REF))
        {
-         tem = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-
          /* Make sure that the rtx is not shared with any other insn.  */
          src_const = copy_rtx (src_const);
 
          /* Record the actual constant value in a REG_EQUAL note, making
             a new one if one does not already exist.  */
-         if (tem)
-           XEXP (tem, 0) = src_const;
-         else
-           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                                 src_const, REG_NOTES (insn));
+         set_unique_reg_note (insn, REG_EQUAL, src_const);
 
-          /* If storing a constant value in a register that
+         /* If storing a constant value in a register that
             previously held the constant value 0,
             record this fact with a REG_WAS_0 note on this insn.
 
@@ -5785,45 +5787,49 @@ cse_insn (insn, libcall_insn)
       else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx)
        {
          /* One less use of the label this insn used to jump to.  */
-         if (JUMP_LABEL (insn) != 0)
-           --LABEL_NUSES (JUMP_LABEL (insn));
-         PUT_CODE (insn, NOTE);
-         NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-         NOTE_SOURCE_FILE (insn) = 0;
+         delete_insn (insn);
          cse_jumps_altered = 1;
          /* No more processing for this set.  */
          sets[i].rtl = 0;
        }
 
       /* If this SET is now setting PC to a label, we know it used to
-        be a conditional or computed branch.  So we see if we can follow
-        it.  If it was a computed branch, delete it and re-emit.  */
+        be a conditional or computed branch.  */
       else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF)
        {
-         /* If this is not in the format for a simple branch and
-            we are the only SET in it, re-emit it.  */
-         if (! simplejump_p (insn) && n_sets == 1)
+         /* Now emit a BARRIER after the unconditional jump.  */
+         if (NEXT_INSN (insn) == 0
+             || GET_CODE (NEXT_INSN (insn)) != BARRIER)
+           emit_barrier_after (insn);
+
+         /* We reemit the jump in as many cases as possible just in
+            case the form of an unconditional jump is significantly
+            different than a computed jump or conditional jump.
+
+            If this insn has multiple sets, then reemitting the
+            jump is nontrivial.  So instead we just force rerecognition
+            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.  */
+             if (NEXT_INSN (insn) == 0
+                 || GET_CODE (NEXT_INSN (insn)) != BARRIER)
+               emit_barrier_after (insn);
            }
          else
-           /* Otherwise, force rerecognition, since it probably had
-              a different pattern before.
-              This shouldn't really be necessary, since whatever
-              changed the source value above should have done this.
-              Until the right place is found, might as well do this here.  */
            INSN_CODE (insn) = -1;
 
-         never_reached_warning (insn);
+         never_reached_warning (insn, NULL);
 
-         /* Now emit a BARRIER after the unconditional jump.  Do not bother
-            deleting any unreachable code, let jump/flow do that.  */
-         if (NEXT_INSN (insn) != 0
-             && GET_CODE (NEXT_INSN (insn)) != BARRIER)
-           emit_barrier_after (insn);
+         /* Do not bother deleting any unreachable code,
+            let jump/flow do that.  */
 
          cse_jumps_altered = 1;
          sets[i].rtl = 0;
@@ -5880,8 +5886,8 @@ cse_insn (insn, libcall_insn)
   if (src_eqv && src_eqv_elt == 0 && sets[0].rtl != 0 && ! src_eqv_volatile
       && ! rtx_equal_p (src_eqv, SET_DEST (sets[0].rtl)))
     {
-      register struct table_elt *elt;
-      register struct table_elt *classp = sets[0].src_elt;
+      struct table_elt *elt;
+      struct table_elt *classp = sets[0].src_elt;
       rtx dest = SET_DEST (sets[0].rtl);
       enum machine_mode eqvmode = GET_MODE (dest);
 
@@ -5926,9 +5932,9 @@ cse_insn (insn, libcall_insn)
          {
            /* Insert source and constant equivalent into hash table, if not
               already present.  */
-           register struct table_elt *classp = src_eqv_elt;
-           register rtx src = sets[i].src;
-           register rtx dest = SET_DEST (sets[i].rtl);
+           struct table_elt *classp = src_eqv_elt;
+           rtx src = sets[i].src;
+           rtx dest = SET_DEST (sets[i].rtl);
            enum machine_mode mode
              = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
 
@@ -5937,11 +5943,9 @@ 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))
                  {
-                   register struct table_elt *elt;
+                   struct table_elt *elt;
 
                    /* Note that these insert_regs calls cannot remove
                       any of the src_elt's, because they would have failed to
@@ -5978,7 +5982,7 @@ cse_insn (insn, libcall_insn)
 
   if (GET_CODE (insn) == CALL_INSN)
     {
-      if (! CONST_CALL_P (insn))
+      if (! CONST_OR_PURE_CALL_P (insn))
        invalidate_memory ();
       invalidate_for_call ();
     }
@@ -5993,7 +5997,7 @@ cse_insn (insn, libcall_insn)
       {
        /* We can't use the inner dest, because the mode associated with
           a ZERO_EXTRACT is significant.  */
-       register rtx dest = SET_DEST (sets[i].rtl);
+       rtx dest = SET_DEST (sets[i].rtl);
 
        /* Needed for registers to remove the register from its
           previous quantity's chain.
@@ -6077,7 +6081,7 @@ cse_insn (insn, libcall_insn)
          /* If elt was removed, find current head of same class,
             or 0 if nothing remains of that class.  */
          {
-           register struct table_elt *elt = sets[i].src_elt;
+           struct table_elt *elt = sets[i].src_elt;
 
            while (elt && elt->prev_same_value)
              elt = elt->prev_same_value;
@@ -6093,9 +6097,9 @@ cse_insn (insn, libcall_insn)
   for (i = 0; i < n_sets; i++)
     if (sets[i].rtl)
       {
-       register rtx dest = SET_DEST (sets[i].rtl);
+       rtx dest = SET_DEST (sets[i].rtl);
        rtx inner_dest = sets[i].inner_dest;
-       register struct table_elt *elt;
+       struct table_elt *elt;
 
        /* Don't record value if we are not supposed to risk allocating
           floating-point values in registers that might be wider than
@@ -6273,7 +6277,7 @@ cse_insn (insn, libcall_insn)
 
             This section previously turned the REG_EQUIV into a REG_EQUAL
             note.  We cannot do that because REG_EQUIV may provide an
-            uninitialised stack slot when REG_PARM_STACK_SPACE is used. */
+            uninitialised stack slot when REG_PARM_STACK_SPACE is used.  */
 
          if (prev != 0 && GET_CODE (prev) == INSN
              && GET_CODE (PATTERN (prev)) == SET
@@ -6333,11 +6337,7 @@ cse_insn (insn, libcall_insn)
       && (tem = single_set (prev_insn)) != 0
       && SET_DEST (tem) == cc0_rtx
       && ! reg_mentioned_p (cc0_rtx, x))
-    {
-      PUT_CODE (prev_insn, NOTE);
-      NOTE_LINE_NUMBER (prev_insn) = NOTE_INSN_DELETED;
-      NOTE_SOURCE_FILE (prev_insn) = 0;
-    }
+    delete_insn (prev_insn);
 
   prev_insn_cc0 = this_insn_cc0;
   prev_insn_cc0_mode = this_insn_cc0_mode;
@@ -6351,8 +6351,8 @@ cse_insn (insn, libcall_insn)
 static void
 invalidate_memory ()
 {
-  register int i;
-  register struct table_elt *p, *next;
+  int i;
+  struct table_elt *p, *next;
 
   for (i = 0; i < HASH_SIZE; i++)
     for (p = table[i]; p; p = next)
@@ -6368,7 +6368,7 @@ invalidate_memory ()
 
 static int
 addr_affects_sp_p (addr)
-     register rtx addr;
+     rtx addr;
 {
   if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
       && GET_CODE (XEXP (addr, 0)) == REG
@@ -6413,10 +6413,10 @@ invalidate_from_clobbers (x)
     }
   else if (GET_CODE (x) == PARALLEL)
     {
-      register int i;
+      int i;
       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
        {
-         register rtx y = XVECEXP (x, 0, i);
+         rtx y = XVECEXP (x, 0, i);
          if (GET_CODE (y) == CLOBBER)
            {
              rtx ref = XEXP (y, 0);
@@ -6456,13 +6456,15 @@ cse_process_notes (x, object)
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case CC0:
     case LO_SUM:
       return x;
 
     case MEM:
-      XEXP (x, 0) = cse_process_notes (XEXP (x, 0), x);
+      validate_change (x, &XEXP (x, 0),
+                      cse_process_notes (XEXP (x, 0), x), 0);
       return x;
 
     case EXPR_LIST:
@@ -6657,7 +6659,7 @@ invalidate_skipped_block (start)
 
       if (GET_CODE (insn) == CALL_INSN)
        {
-         if (! CONST_CALL_P (insn))
+         if (! CONST_OR_PURE_CALL_P (insn))
            invalidate_memory ();
          invalidate_for_call ();
        }
@@ -6873,11 +6875,11 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
          && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
        break;
 
-      /* Don't cse over a call to setjmp; on some machines (eg vax)
+      /* Don't cse over a call to setjmp; on some machines (eg VAX)
         the regs restored by the longjmp come from
         a later time than the setjmp.  */
-      if (GET_CODE (p) == NOTE
-         && NOTE_LINE_NUMBER (p) == NOTE_INSN_SETJMP)
+      if (PREV_INSN (p) && GET_CODE (PREV_INSN (p)) == CALL_INSN
+         && find_reg_note (PREV_INSN (p), REG_SETJMP, NULL))
        break;
 
       /* A PARALLEL can have lots of SETs in it,
@@ -6927,7 +6929,8 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
          for (q = PREV_INSN (JUMP_LABEL (p)); q; q = PREV_INSN (q))
            if ((GET_CODE (q) != NOTE
                 || NOTE_LINE_NUMBER (q) == NOTE_INSN_LOOP_END
-                || NOTE_LINE_NUMBER (q) == NOTE_INSN_SETJMP)
+                || (PREV_INSN (q) && GET_CODE (PREV_INSN (q)) == CALL_INSN
+                    && find_reg_note (PREV_INSN (q), REG_SETJMP, NULL)))
                && (GET_CODE (q) != CODE_LABEL || LABEL_NUSES (q) != 0))
              break;
 
@@ -6967,7 +6970,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
          /* Detect a branch around a block of code.  */
          else if (skip_blocks && q != 0 && GET_CODE (q) != CODE_LABEL)
            {
-             register rtx tmp;
+             rtx tmp;
 
              if (next_real_insn (q) == next)
                {
@@ -7042,8 +7045,8 @@ cse_main (f, nregs, after_loop, file)
      FILE *file;
 {
   struct cse_basic_block_data val;
-  register rtx insn = f;
-  register int i;
+  rtx insn = f;
+  int i;
 
   cse_jumps_altered = 0;
   recorded_label_ref = 0;
@@ -7092,37 +7095,6 @@ cse_main (f, nregs, after_loop, file)
        INSN_CUID (insn) = i;
     }
 
-  /* Initialize which registers are clobbered by calls.  */
-
-  CLEAR_HARD_REG_SET (regs_invalidated_by_call);
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if ((call_used_regs[i]
-        /* Used to check !fixed_regs[i] here, but that isn't safe;
-           fixed regs are still call-clobbered, and sched can get
-           confused if they can "live across calls".
-
-           The frame pointer is always preserved across calls.  The arg
-           pointer is if it is fixed.  The stack pointer usually is, unless
-           RETURN_POPS_ARGS, in which case an explicit CLOBBER
-           will be present.  If we are generating PIC code, the PIC offset
-           table register is preserved across calls.  */
-
-        && i != STACK_POINTER_REGNUM
-        && i != FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-        && i != HARD_FRAME_POINTER_REGNUM
-#endif
-#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
-        && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
-#endif
-#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
-        && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
-#endif
-        )
-       || global_regs[i])
-      SET_HARD_REG_BIT (regs_invalidated_by_call, i);
-
   ggc_push_context ();
 
   /* Loop over basic blocks.
@@ -7213,11 +7185,11 @@ cse_main (f, nregs, after_loop, file)
 
 static rtx
 cse_basic_block (from, to, next_branch, around_loop)
-     register rtx from, to;
+     rtx from, to;
      struct branch_path *next_branch;
      int around_loop;
 {
-  register rtx insn;
+  rtx insn;
   int to_usage = 0;
   rtx libcall_insn = NULL_RTX;
   int num_insns = 0;
@@ -7238,7 +7210,7 @@ cse_basic_block (from, to, next_branch, around_loop)
 
   for (insn = from; insn != to; insn = NEXT_INSN (insn))
     {
-      register enum rtx_code code = GET_CODE (insn);
+      enum rtx_code code = GET_CODE (insn);
 
       /* If we have processed 1,000 insns, flush the hash table to
         avoid extreme quadratic behavior.  We must not include NOTEs
@@ -7306,6 +7278,13 @@ cse_basic_block (from, to, next_branch, around_loop)
            }
 
          cse_insn (insn, libcall_insn);
+
+         /* If we haven't already found an insn where we added a LABEL_REF,
+            check this one.  */
+         if (GET_CODE (insn) == INSN && ! recorded_label_ref
+             && for_each_rtx (&PATTERN (insn), check_for_label_ref,
+                              (void *) insn))
+           recorded_label_ref = 1;
        }
 
       /* If INSN is now an unconditional jump, skip to the end of our
@@ -7399,20 +7378,42 @@ cse_basic_block (from, to, next_branch, around_loop)
      we can cse into the loop.  Don't do this if we changed the jump
      structure of a loop unless we aren't going to be following jumps.  */
 
+  insn = prev_nonnote_insn (to);
   if ((cse_jumps_altered == 0
        || (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
       && around_loop && to != 0
       && GET_CODE (to) == NOTE && NOTE_LINE_NUMBER (to) == NOTE_INSN_LOOP_END
-      && GET_CODE (PREV_INSN (to)) == JUMP_INSN
-      && JUMP_LABEL (PREV_INSN (to)) != 0
-      && LABEL_NUSES (JUMP_LABEL (PREV_INSN (to))) == 1)
-    cse_around_loop (JUMP_LABEL (PREV_INSN (to)));
+      && GET_CODE (insn) == JUMP_INSN
+      && JUMP_LABEL (insn) != 0
+      && LABEL_NUSES (JUMP_LABEL (insn)) == 1)
+    cse_around_loop (JUMP_LABEL (insn));
 
   free (qty_table + max_reg);
 
   return to ? NEXT_INSN (to) : 0;
 }
 \f
+/* Called via for_each_rtx to see if an insn is using a LABEL_REF for which
+   there isn't a REG_LABEL note.  Return one if so.  DATA is the insn.  */
+
+static int
+check_for_label_ref (rtl, data)
+     rtx *rtl;
+     void *data;
+{
+  rtx insn = (rtx) data;
+
+  /* If this insn uses a LABEL_REF and there isn't a REG_LABEL note for it,
+     we must rerun jump since it needs to place the note.  If this is a
+     LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
+     since no REG_LABEL will be added.  */
+  return (GET_CODE (*rtl) == LABEL_REF
+         && ! LABEL_REF_NONLOCAL_P (*rtl)
+         && LABEL_P (XEXP (*rtl, 0))
+         && INSN_UID (XEXP (*rtl, 0)) != 0
+         && ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
+}
+\f
 /* Count the number of times registers are used (not set) in X.
    COUNTS is an array in which we accumulate the count, INCR is how much
    we count each register usage.
@@ -7447,6 +7448,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;
@@ -7511,6 +7513,108 @@ count_reg_usage (x, counts, dest, incr)
     }
 }
 \f
+/* Return true if set is live.  */
+static bool
+set_live_p (set, insn, counts)
+     rtx set;
+     rtx insn ATTRIBUTE_UNUSED;        /* Only used with HAVE_cc0.  */
+     int *counts;
+{
+#ifdef HAVE_cc0
+  rtx tem;
+#endif
+
+  if (set_noop_p (set))
+    ;
+
+#ifdef HAVE_cc0
+  else if (GET_CODE (SET_DEST (set)) == CC0
+          && !side_effects_p (SET_SRC (set))
+          && ((tem = next_nonnote_insn (insn)) == 0
+              || !INSN_P (tem)
+              || !reg_referenced_p (cc0_rtx, PATTERN (tem))))
+    return false;
+#endif
+  else if (GET_CODE (SET_DEST (set)) != REG
+          || REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
+          || counts[REGNO (SET_DEST (set))] != 0
+          || side_effects_p (SET_SRC (set))
+          /* An ADDRESSOF expression can turn into a use of the
+             internal arg pointer, so always consider the
+             internal arg pointer live.  If it is truly dead,
+             flow will delete the initializing insn.  */
+          || (SET_DEST (set) == current_function_internal_arg_pointer))
+    return true;
+  return false;
+}
+
+/* Return true if insn is live.  */
+
+static bool
+insn_live_p (insn, counts)
+     rtx insn;
+     int *counts;
+{
+  int i;
+  if (GET_CODE (PATTERN (insn)) == SET)
+    return set_live_p (PATTERN (insn), insn, counts);
+  else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+    {
+      for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+       {
+         rtx elt = XVECEXP (PATTERN (insn), 0, i);
+
+         if (GET_CODE (elt) == SET)
+           {
+             if (set_live_p (elt, insn, counts))
+               return true;
+           }
+         else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
+           return true;
+       }
+      return false;
+    }
+  else
+    return true;
+}
+
+/* Return true if libcall is dead as a whole.  */
+
+static bool
+dead_libcall_p (insn, counts)
+     rtx insn;
+     int *counts;
+{
+  rtx note;
+  /* See if there's a REG_EQUAL note on this insn and try to
+     replace the source with the REG_EQUAL expression.
+
+     We assume that insns with REG_RETVALs can only be reg->reg
+     copies at this point.  */
+  note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+  if (note)
+    {
+      rtx set = single_set (insn);
+      rtx new = simplify_rtx (XEXP (note, 0));
+
+      if (!new)
+       new = XEXP (note, 0);
+
+      /* While changing insn, we must update the counts accordingly.  */
+      count_reg_usage (insn, counts, NULL_RTX, -1);
+
+      if (set && validate_change (insn, &SET_SRC (set), new, 0))
+       {
+          count_reg_usage (insn, counts, NULL_RTX, 1);
+         remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
+         remove_note (insn, note);
+         return true;
+       }
+       count_reg_usage (insn, counts, NULL_RTX, 1);
+    }
+  return false;
+}
+
 /* Scan all the insns and delete any that are dead; i.e., they store a register
    that is never used or they copy a register to itself.
 
@@ -7519,163 +7623,83 @@ count_reg_usage (x, counts, dest, incr)
    move dead invariants out of loops or make givs for dead quantities.  The
    remaining passes of the compilation are also sped up.  */
 
-void
+int
 delete_trivially_dead_insns (insns, nreg)
      rtx insns;
      int nreg;
 {
   int *counts;
   rtx insn, prev;
-#ifdef HAVE_cc0
-  rtx tem;
-#endif
-  int i;
   int in_libcall = 0, dead_libcall = 0;
+  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);
-
-  for (; insn; insn = prev)
+  do
     {
-      int live_insn = 0;
-      rtx note;
-
-      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.
+      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);
 
-        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))
+      for (; insn; insn = prev)
        {
-         in_libcall = 1;
-         live_insn = 1;
-         dead_libcall = 0;
+         int live_insn = 0;
 
-         /* See if there's a REG_EQUAL note on this insn and try to
-            replace the source with the REG_EQUAL expression.
+         prev = prev_real_insn (insn);
 
-            We assume that insns with REG_RETVALs can only be reg->reg
-            copies at this point.  */
-         note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
-         if (note)
-           {
-             rtx set = single_set (insn);
-             rtx new = simplify_rtx (XEXP (note, 0));
-
-             if (!new)
-               new = XEXP (note, 0);
+         /* Don't delete any insns that are part of a libcall block unless
+            we can delete the whole libcall block.
 
-             if (set && validate_change (insn, &SET_SRC (set), new, 0))
-               {
-                 remove_note (insn,
-                              find_reg_note (insn, REG_RETVAL, NULL_RTX));
-                 dead_libcall = 1;
-               }
-           }
-       }
-      else if (in_libcall)
-       live_insn = ! dead_libcall;
-      else if (GET_CODE (PATTERN (insn)) == SET)
-       {
-         if ((GET_CODE (SET_DEST (PATTERN (insn))) == REG
-              || GET_CODE (SET_DEST (PATTERN (insn))) == SUBREG)
-             && rtx_equal_p (SET_DEST (PATTERN (insn)),
-                             SET_SRC (PATTERN (insn))))
-           ;
-         else if (GET_CODE (SET_DEST (PATTERN (insn))) == STRICT_LOW_PART
-                  && rtx_equal_p (XEXP (SET_DEST (PATTERN (insn)), 0),
-                                  SET_SRC (PATTERN (insn))))
-           ;
-
-#ifdef HAVE_cc0
-         else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0
-                  && ! side_effects_p (SET_SRC (PATTERN (insn)))
-                  && ((tem = next_nonnote_insn (insn)) == 0
-                      || ! INSN_P (tem)
-                      || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
-           ;
-#endif
-         else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG
-                  || REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
-                  || counts[REGNO (SET_DEST (PATTERN (insn)))] != 0
-                  || side_effects_p (SET_SRC (PATTERN (insn)))
-                  /* An ADDRESSOF expression can turn into a use of the
-                     internal arg pointer, so always consider the
-                     internal arg pointer live.  If it is truly dead,
-                     flow will delete the initializing insn.  */
-                  || (SET_DEST (PATTERN (insn))
-                      == current_function_internal_arg_pointer))
-           live_insn = 1;
-       }
-      else if (GET_CODE (PATTERN (insn)) == PARALLEL)
-       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
-         {
-           rtx elt = XVECEXP (PATTERN (insn), 0, i);
-
-           if (GET_CODE (elt) == SET)
-             {
-               if ((GET_CODE (SET_DEST (elt)) == REG
-                    || GET_CODE (SET_DEST (elt)) == SUBREG)
-                   && rtx_equal_p (SET_DEST (elt), SET_SRC (elt)))
-                 ;
-
-#ifdef HAVE_cc0
-               else if (GET_CODE (SET_DEST (elt)) == CC0
-                        && ! side_effects_p (SET_SRC (elt))
-                        && ((tem = next_nonnote_insn (insn)) == 0
-                            || ! INSN_P (tem)
-                            || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
-                 ;
-#endif
-               else if (GET_CODE (SET_DEST (elt)) != REG
-                        || REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER
-                        || counts[REGNO (SET_DEST (elt))] != 0
-                        || side_effects_p (SET_SRC (elt))
-                        /* An ADDRESSOF expression can turn into a use of the
-                           internal arg pointer, so always consider the
-                           internal arg pointer live.  If it is truly dead,
-                           flow will delete the initializing insn.  */
-                        || (SET_DEST (elt)
-                            == current_function_internal_arg_pointer))
-                 live_insn = 1;
-             }
-           else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
+            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;
-         }
-      else
-       live_insn = 1;
+             dead_libcall = dead_libcall_p (insn, counts);
+           }
+         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 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_insn (insn);
-       }
+         if (! live_insn)
+           {
+             count_reg_usage (insn, counts, NULL_RTX, -1);
+             delete_insn_and_edges (insn);
+             ndead++;
+           }
 
-      if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-       {
-         in_libcall = 0;
-         dead_libcall = 0;
+         if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+           {
+             in_libcall = 0;
+             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;
 }