OSDN Git Service

PR c/12553
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index a90f0d8..7612a5a 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -42,6 +42,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "timevar.h"
 #include "except.h"
 #include "target.h"
+#include "params.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -502,9 +503,9 @@ struct table_elt
    a cost of 2.  Aside from these special cases, call `rtx_cost'.  */
 
 #define CHEAP_REGNO(N) \
-  ((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM     \
-   || (N) == STACK_POINTER_REGNUM || (N) == ARG_POINTER_REGNUM         \
-   || ((N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER)  \
+  ((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM     \
+   || (N) == STACK_POINTER_REGNUM || (N) == ARG_POINTER_REGNUM         \
+   || ((N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER)  \
    || ((N) < FIRST_PSEUDO_REGISTER                                     \
        && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
 
@@ -513,7 +514,7 @@ struct table_elt
 
 /* Get the info associated with register N.  */
 
-#define GET_CSE_REG_INFO(N)                    \
+#define GET_CSE_REG_INFO(N)                    \
   (((N) == cached_regno && cached_cse_reg_info)        \
    ? cached_cse_reg_info : get_cse_reg_info ((N)))
 
@@ -568,10 +569,7 @@ static struct table_elt *last_jump_equiv_class;
    the insn.  */
 
 static int constant_pool_entries_cost;
-
-/* Define maximum length of a branch path.  */
-
-#define PATHLENGTH     10
+static int constant_pool_entries_regcost;
 
 /* This data describes a block that will be processed by cse_basic_block.  */
 
@@ -596,79 +594,77 @@ struct cse_basic_block_data
         except that it is used when the destination label is not preceded
        by a BARRIER.  */
       enum taken {TAKEN, NOT_TAKEN, AROUND} status;
-    } path[PATHLENGTH];
+    } *path;
 };
 
-static bool fixed_base_plus_p  PARAMS ((rtx x));
-static int notreg_cost         PARAMS ((rtx, enum rtx_code));
-static int approx_reg_cost_1   PARAMS ((rtx *, void *));
-static int approx_reg_cost     PARAMS ((rtx));
-static int preferrable         PARAMS ((int, int, int, int));
-static void new_basic_block    PARAMS ((void));
-static void make_new_qty       PARAMS ((unsigned int, enum machine_mode));
-static void make_regs_eqv      PARAMS ((unsigned int, unsigned int));
-static void delete_reg_equiv   PARAMS ((unsigned int));
-static int mention_regs                PARAMS ((rtx));
-static int insert_regs         PARAMS ((rtx, struct table_elt *, int));
-static void remove_from_table  PARAMS ((struct table_elt *, unsigned));
-static struct table_elt *lookup        PARAMS ((rtx, unsigned, enum machine_mode)),
-       *lookup_for_remove PARAMS ((rtx, unsigned, enum machine_mode));
-static rtx lookup_as_function  PARAMS ((rtx, enum rtx_code));
-static struct table_elt *insert PARAMS ((rtx, struct table_elt *, unsigned,
-                                        enum machine_mode));
-static void merge_equiv_classes PARAMS ((struct table_elt *,
-                                        struct table_elt *));
-static void invalidate         PARAMS ((rtx, enum machine_mode));
-static int cse_rtx_varies_p    PARAMS ((rtx, int));
-static void remove_invalid_refs        PARAMS ((unsigned int));
-static void remove_invalid_subreg_refs PARAMS ((unsigned int, unsigned int,
-                                                enum machine_mode));
-static void rehash_using_reg   PARAMS ((rtx));
-static void invalidate_memory  PARAMS ((void));
-static void invalidate_for_call        PARAMS ((void));
-static rtx use_related_value   PARAMS ((rtx, struct table_elt *));
-static unsigned canon_hash     PARAMS ((rtx, enum machine_mode));
-static unsigned canon_hash_string PARAMS ((const char *));
-static unsigned safe_hash      PARAMS ((rtx, enum machine_mode));
-static int exp_equiv_p         PARAMS ((rtx, rtx, int, int));
-static rtx canon_reg           PARAMS ((rtx, rtx));
-static void find_best_addr     PARAMS ((rtx, rtx *, enum machine_mode));
-static enum rtx_code find_comparison_args PARAMS ((enum rtx_code, rtx *, rtx *,
-                                                  enum machine_mode *,
-                                                  enum machine_mode *));
-static rtx fold_rtx            PARAMS ((rtx, rtx));
-static rtx equiv_constant      PARAMS ((rtx));
-static void record_jump_equiv  PARAMS ((rtx, int));
-static void record_jump_cond   PARAMS ((enum rtx_code, enum machine_mode,
-                                        rtx, rtx, int));
-static void cse_insn           PARAMS ((rtx, rtx));
-static int addr_affects_sp_p   PARAMS ((rtx));
-static void invalidate_from_clobbers PARAMS ((rtx));
-static rtx cse_process_notes   PARAMS ((rtx, rtx));
-static void cse_around_loop    PARAMS ((rtx));
-static void invalidate_skipped_set PARAMS ((rtx, rtx, void *));
-static void invalidate_skipped_block PARAMS ((rtx));
-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 *));
+static bool fixed_base_plus_p (rtx x);
+static int notreg_cost (rtx, enum rtx_code);
+static int approx_reg_cost_1 (rtx *, void *);
+static int approx_reg_cost (rtx);
+static int preferrable (int, int, int, int);
+static void new_basic_block (void);
+static void make_new_qty (unsigned int, enum machine_mode);
+static void make_regs_eqv (unsigned int, unsigned int);
+static void delete_reg_equiv (unsigned int);
+static int mention_regs (rtx);
+static int insert_regs (rtx, struct table_elt *, int);
+static void remove_from_table (struct table_elt *, unsigned);
+static struct table_elt *lookup        (rtx, unsigned, enum machine_mode);
+static struct table_elt *lookup_for_remove (rtx, unsigned, enum machine_mode);
+static rtx lookup_as_function (rtx, enum rtx_code);
+static struct table_elt *insert (rtx, struct table_elt *, unsigned,
+                                enum machine_mode);
+static void merge_equiv_classes (struct table_elt *, struct table_elt *);
+static void invalidate (rtx, enum machine_mode);
+static int cse_rtx_varies_p (rtx, int);
+static void remove_invalid_refs (unsigned int);
+static void remove_invalid_subreg_refs (unsigned int, unsigned int,
+                                       enum machine_mode);
+static void rehash_using_reg (rtx);
+static void invalidate_memory (void);
+static void invalidate_for_call (void);
+static rtx use_related_value (rtx, struct table_elt *);
+static unsigned canon_hash (rtx, enum machine_mode);
+static unsigned canon_hash_string (const char *);
+static unsigned safe_hash (rtx, enum machine_mode);
+static int exp_equiv_p (rtx, rtx, int, int);
+static rtx canon_reg (rtx, rtx);
+static void find_best_addr (rtx, rtx *, enum machine_mode);
+static enum rtx_code find_comparison_args (enum rtx_code, rtx *, rtx *,
+                                          enum machine_mode *,
+                                          enum machine_mode *);
+static rtx fold_rtx (rtx, rtx);
+static rtx equiv_constant (rtx);
+static void record_jump_equiv (rtx, int);
+static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
+                             int);
+static void cse_insn (rtx, rtx);
+static int addr_affects_sp_p (rtx);
+static void invalidate_from_clobbers (rtx);
+static rtx cse_process_notes (rtx, rtx);
+static void cse_around_loop (rtx);
+static void invalidate_skipped_set (rtx, rtx, void *);
+static void invalidate_skipped_block (rtx);
+static void cse_check_loop_start (rtx, rtx, void *);
+static void cse_set_around_loop (rtx, rtx, rtx);
+static rtx cse_basic_block (rtx, rtx, struct branch_path *, int);
+static void count_reg_usage (rtx, int *, int);
+static int check_for_label_ref (rtx *, void *);
+extern void dump_class (struct table_elt*);
+static struct cse_reg_info * get_cse_reg_info (unsigned int);
+static int check_dependence (rtx *, void *);
+
+static void flush_hash_table (void);
+static bool insn_live_p (rtx, int *);
+static bool set_live_p (rtx, rtx, int *);
+static bool dead_libcall_p (rtx, int *);
 \f
 /* Nonzero if X has the form (PLUS frame-pointer integer).  We check for
    virtual regs here because the simplify_*_operation routines are called
    by integrate.c, which is called before virtual register instantiation.  */
 
 static bool
-fixed_base_plus_p (x)
-     rtx x;
+fixed_base_plus_p (rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -698,8 +694,7 @@ fixed_base_plus_p (x)
 /* Dump the expressions in the equivalence class indicated by CLASSP.
    This function is used only for debugging.  */
 void
-dump_class (classp)
-     struct table_elt *classp;
+dump_class (struct table_elt *classp)
 {
   struct table_elt *elt;
 
@@ -717,9 +712,7 @@ 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;
+approx_reg_cost_1 (rtx *xp, void *data)
 {
   rtx x = *xp;
   int *cost_p = data;
@@ -750,8 +743,7 @@ approx_reg_cost_1 (xp, data)
    0.  If any other hard register reference occurs, return MAX_COST.  */
 
 static int
-approx_reg_cost (x)
-     rtx x;
+approx_reg_cost (rtx x)
 {
   int cost = 0;
 
@@ -766,8 +758,7 @@ approx_reg_cost (x)
    Return a positive value if A is less desirable, or 0 if the two are
    equally good.  */
 static int
-preferrable (cost_a, regcost_a, cost_b, regcost_b)
-     int cost_a, regcost_a, cost_b, regcost_b;
+preferrable (int cost_a, int regcost_a, int cost_b, int regcost_b)
 {
   /* First, get rid of cases involving expressions that are entirely
      unwanted.  */
@@ -801,9 +792,7 @@ preferrable (cost_a, regcost_a, cost_b, regcost_b)
    from COST macro to keep it simple.  */
 
 static int
-notreg_cost (x, outer)
-     rtx x;
-     enum rtx_code outer;
+notreg_cost (rtx x, enum rtx_code outer)
 {
   return ((GET_CODE (x) == SUBREG
           && GET_CODE (SUBREG_REG (x)) == REG
@@ -824,9 +813,7 @@ notreg_cost (x, outer)
    Other uses like the latter are expected in the future.  */
 
 int
-rtx_cost (x, outer_code)
-     rtx x;
-     enum rtx_code outer_code ATTRIBUTE_UNUSED;
+rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED)
 {
   int i, j;
   enum rtx_code code;
@@ -896,9 +883,7 @@ rtx_cost (x, outer_code)
    Expect that X is properly formed address reference.  */
 
 int
-address_cost (x, mode)
-     rtx x;
-     enum machine_mode mode;
+address_cost (rtx x, enum machine_mode mode)
 {
   /* The address_cost target hook does not deal with ADDRESSOF nodes.  But,
      during CSE, such nodes are present.  Using an ADDRESSOF node which
@@ -921,15 +906,13 @@ address_cost (x, mode)
 /* If the target doesn't override, compute the cost as with arithmetic.  */
 
 int
-default_address_cost (x)
-     rtx x;
+default_address_cost (rtx x)
 {
   return rtx_cost (x, MEM);
 }
 \f
 static struct cse_reg_info *
-get_cse_reg_info (regno)
-     unsigned int regno;
+get_cse_reg_info (unsigned int regno)
 {
   struct cse_reg_info **hash_head = &reg_hash[REGHASH_FN (regno)];
   struct cse_reg_info *p;
@@ -947,7 +930,7 @@ get_cse_reg_info (regno)
          cse_reg_info_free_list = p->next;
        }
       else
-       p = (struct cse_reg_info *) xmalloc (sizeof (struct cse_reg_info));
+       p = xmalloc (sizeof (struct cse_reg_info));
 
       /* Insert into hash table.  */
       p->hash_next = *hash_head;
@@ -977,7 +960,7 @@ get_cse_reg_info (regno)
    for a new basic block.  */
 
 static void
-new_basic_block ()
+new_basic_block (void)
 {
   int i;
 
@@ -985,7 +968,7 @@ new_basic_block ()
 
   /* Clear out hash table state for this pass.  */
 
-  memset ((char *) reg_hash, 0, sizeof reg_hash);
+  memset (reg_hash, 0, sizeof reg_hash);
 
   if (cse_reg_info_used_list)
     {
@@ -1032,9 +1015,7 @@ new_basic_block ()
    register before and initialize that quantity.  */
 
 static void
-make_new_qty (reg, mode)
-     unsigned int reg;
-     enum machine_mode mode;
+make_new_qty (unsigned int reg, enum machine_mode mode)
 {
   int q;
   struct qty_table_elem *ent;
@@ -1059,8 +1040,7 @@ make_new_qty (reg, mode)
    OLD is not changing; NEW is.  */
 
 static void
-make_regs_eqv (new, old)
-     unsigned int new, old;
+make_regs_eqv (unsigned int new, unsigned int old)
 {
   unsigned int lastr, firstr;
   int q = REG_QTY (old);
@@ -1123,8 +1103,7 @@ make_regs_eqv (new, old)
 /* Remove REG from its equivalence class.  */
 
 static void
-delete_reg_equiv (reg)
-     unsigned int reg;
+delete_reg_equiv (unsigned int reg)
 {
   struct qty_table_elem *ent;
   int q = REG_QTY (reg);
@@ -1164,8 +1143,7 @@ delete_reg_equiv (reg)
    of X.  */
 
 static int
-mention_regs (x)
-     rtx x;
+mention_regs (rtx x)
 {
   enum rtx_code code;
   int i, j;
@@ -1274,10 +1252,7 @@ mention_regs (x)
    so X's hash code may be different.  */
 
 static int
-insert_regs (x, classp, modified)
-     rtx x;
-     struct table_elt *classp;
-     int modified;
+insert_regs (rtx x, struct table_elt *classp, int modified)
 {
   if (GET_CODE (x) == REG)
     {
@@ -1354,9 +1329,7 @@ insert_regs (x, classp, modified)
    and we save much time not recomputing it.  */
 
 static void
-remove_from_table (elt, hash)
-     struct table_elt *elt;
-     unsigned hash;
+remove_from_table (struct table_elt *elt, unsigned int hash)
 {
   if (elt == 0)
     return;
@@ -1439,10 +1412,7 @@ remove_from_table (elt, hash)
    looks like X.  */
 
 static struct table_elt *
-lookup (x, hash, mode)
-     rtx x;
-     unsigned hash;
-     enum machine_mode mode;
+lookup (rtx x, unsigned int hash, enum machine_mode mode)
 {
   struct table_elt *p;
 
@@ -1458,10 +1428,7 @@ lookup (x, hash, mode)
    Also ignore discrepancies in the machine mode of a register.  */
 
 static struct table_elt *
-lookup_for_remove (x, hash, mode)
-     rtx x;
-     unsigned hash;
-     enum machine_mode mode;
+lookup_for_remove (rtx x, unsigned int hash, enum machine_mode mode)
 {
   struct table_elt *p;
 
@@ -1490,9 +1457,7 @@ lookup_for_remove (x, hash, mode)
    If one is found, return that expression.  */
 
 static rtx
-lookup_as_function (x, code)
-     rtx x;
-     enum rtx_code code;
+lookup_as_function (rtx x, enum rtx_code code)
 {
   struct table_elt *p
     = lookup (x, safe_hash (x, VOIDmode) & HASH_MASK, GET_MODE (x));
@@ -1548,11 +1513,7 @@ lookup_as_function (x, code)
  (preferrable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
 
 static struct table_elt *
-insert (x, classp, hash, mode)
-     rtx x;
-     struct table_elt *classp;
-     unsigned hash;
-     enum machine_mode mode;
+insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode)
 {
   struct table_elt *elt;
 
@@ -1580,7 +1541,7 @@ insert (x, classp, hash, mode)
   else
     {
       n_elements_made++;
-      elt = (struct table_elt *) xmalloc (sizeof (struct table_elt));
+      elt = xmalloc (sizeof (struct table_elt));
     }
 
   elt->exp = x;
@@ -1611,7 +1572,7 @@ insert (x, classp, hash, mode)
     {
       classp = classp->first_same_value;
       if (CHEAPER (elt, classp))
-       /* Insert at the head of the class */
+       /* Insert at the head of the class */
        {
          struct table_elt *p;
          elt->next_same_value = classp;
@@ -1738,8 +1699,7 @@ insert (x, classp, hash, mode)
    Any invalid entries in CLASS2 will not be copied.  */
 
 static void
-merge_equiv_classes (class1, class2)
-     struct table_elt *class1, *class2;
+merge_equiv_classes (struct table_elt *class1, struct table_elt *class2)
 {
   struct table_elt *elt, *next, *new;
 
@@ -1786,7 +1746,7 @@ merge_equiv_classes (class1, class2)
 /* Flush the entire hash table.  */
 
 static void
-flush_hash_table ()
+flush_hash_table (void)
 {
   int i;
   struct table_elt *p;
@@ -1811,9 +1771,7 @@ struct check_dependence_data
 };
 
 static int
-check_dependence (x, data)
-     rtx *x;
-     void *data;
+check_dependence (rtx *x, void *data)
 {
   struct check_dependence_data *d = (struct check_dependence_data *) data;
   if (*x && GET_CODE (*x) == MEM)
@@ -1835,9 +1793,7 @@ check_dependence (x, data)
    or it may be either of those plus a numeric offset.  */
 
 static void
-invalidate (x, full_mode)
-     rtx x;
-     enum machine_mode full_mode;
+invalidate (rtx x, enum machine_mode full_mode)
 {
   int i;
   struct table_elt *p;
@@ -1977,8 +1933,7 @@ invalidate (x, full_mode)
    expressions to reappear as valid.  */
 
 static void
-remove_invalid_refs (regno)
-     unsigned int regno;
+remove_invalid_refs (unsigned int regno)
 {
   unsigned int i;
   struct table_elt *p, *next;
@@ -1996,10 +1951,8 @@ remove_invalid_refs (regno)
 /* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
    and mode MODE.  */
 static void
-remove_invalid_subreg_refs (regno, offset, mode)
-     unsigned int regno;
-     unsigned int offset;
-     enum machine_mode mode;
+remove_invalid_subreg_refs (unsigned int regno, unsigned int offset,
+                           enum machine_mode mode)
 {
   unsigned int i;
   struct table_elt *p, *next;
@@ -2029,8 +1982,7 @@ remove_invalid_subreg_refs (regno, offset, mode)
    This is called when we make a jump equivalence.  */
 
 static void
-rehash_using_reg (x)
-     rtx x;
+rehash_using_reg (rtx x)
 {
   unsigned int i;
   struct table_elt *p, *next;
@@ -2080,7 +2032,7 @@ rehash_using_reg (x)
    register.  Also update their TICK values.  */
 
 static void
-invalidate_for_call ()
+invalidate_for_call (void)
 {
   unsigned int regno, endregno;
   unsigned int i;
@@ -2139,9 +2091,7 @@ invalidate_for_call ()
    If none can be found, return 0.  */
 
 static rtx
-use_related_value (x, elt)
-     rtx x;
-     struct table_elt *elt;
+use_related_value (rtx x, struct table_elt *elt)
 {
   struct table_elt *relt = 0;
   struct table_elt *p, *q;
@@ -2209,8 +2159,7 @@ use_related_value (x, elt)
 \f
 /* Hash a string.  Just add its bytes up.  */
 static inline unsigned
-canon_hash_string (ps)
-     const char *ps;
+canon_hash_string (const char *ps)
 {
   unsigned hash = 0;
   const unsigned char *p = (const unsigned char *) ps;
@@ -2236,9 +2185,7 @@ canon_hash_string (ps)
    is just (int) MEM plus the hash code of the address.  */
 
 static unsigned
-canon_hash (x, mode)
-     rtx x;
-     enum machine_mode mode;
+canon_hash (rtx x, enum machine_mode mode)
 {
   int i, j;
   unsigned hash = 0;
@@ -2290,7 +2237,7 @@ canon_hash (x, mode)
          record = false;
        else
          record = true;
-           
+
        if (!record)
          {
            do_not_record = 1;
@@ -2490,9 +2437,7 @@ canon_hash (x, mode)
 /* Like canon_hash but with no side effects.  */
 
 static unsigned
-safe_hash (x, mode)
-     rtx x;
-     enum machine_mode mode;
+safe_hash (rtx x, enum machine_mode mode)
 {
   int save_do_not_record = do_not_record;
   int save_hash_arg_in_memory = hash_arg_in_memory;
@@ -2518,10 +2463,7 @@ safe_hash (x, mode)
    is the same as that of the given value is pure luck.  */
 
 static int
-exp_equiv_p (x, y, validate, equal_values)
-     rtx x, y;
-     int validate;
-     int equal_values;
+exp_equiv_p (rtx x, rtx y, int validate, int equal_values)
 {
   int i, j;
   enum rtx_code code;
@@ -2713,9 +2655,7 @@ exp_equiv_p (x, y, validate, equal_values)
    against certain constants or near-constants.  */
 
 static int
-cse_rtx_varies_p (x, from_alias)
-     rtx x;
-     int from_alias;
+cse_rtx_varies_p (rtx x, int from_alias)
 {
   /* We need not check for X and the equivalence class being of the same
      mode because if X is equivalent to a constant in some mode, it
@@ -2783,9 +2723,7 @@ cse_rtx_varies_p (x, from_alias)
    generally be discarded since the changes we are making are optional.  */
 
 static rtx
-canon_reg (x, insn)
-     rtx x;
-     rtx insn;
+canon_reg (rtx x, rtx insn)
 {
   int i;
   enum rtx_code code;
@@ -2882,10 +2820,7 @@ canon_reg (x, insn)
    hard registers here because we would also prefer the pseudo registers.  */
 
 static void
-find_best_addr (insn, loc, mode)
-     rtx insn;
-     rtx *loc;
-     enum machine_mode mode;
+find_best_addr (rtx insn, rtx *loc, enum machine_mode mode)
 {
   struct table_elt *elt;
   rtx addr = *loc;
@@ -3012,10 +2947,9 @@ find_best_addr (insn, loc, mode)
   if (flag_expensive_optimizations
       && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
          || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
-      && GET_CODE (XEXP (*loc, 0)) == REG
-      && GET_CODE (XEXP (*loc, 1)) == CONST_INT)
+      && GET_CODE (XEXP (*loc, 0)) == REG)
     {
-      rtx c = XEXP (*loc, 1);
+      rtx op1 = XEXP (*loc, 1);
 
       do_not_record = 0;
       hash = HASH (XEXP (*loc, 0), Pmode);
@@ -3057,7 +2991,7 @@ find_best_addr (insn, loc, mode)
                    || exp_equiv_p (p->exp, p->exp, 1, 0)))
              {
                rtx new = simplify_gen_binary (GET_CODE (*loc), Pmode,
-                                              p->exp, c);
+                                              p->exp, op1);
                int new_cost;
                new_cost = address_cost (new, mode);
 
@@ -3099,10 +3033,8 @@ find_best_addr (insn, loc, mode)
    A or the code corresponding to the inverse of the comparison.  */
 
 static enum rtx_code
-find_comparison_args (code, parg1, parg2, pmode1, pmode2)
-     enum rtx_code code;
-     rtx *parg1, *parg2;
-     enum machine_mode *pmode1, *pmode2;
+find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
+                     enum machine_mode *pmode1, enum machine_mode *pmode2)
 {
   rtx arg1, arg2;
 
@@ -3297,9 +3229,7 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
    of X before modifying it.  */
 
 static rtx
-fold_rtx (x, insn)
-     rtx x;
-     rtx insn;
+fold_rtx (rtx x, rtx insn)
 {
   enum rtx_code code;
   enum machine_mode mode;
@@ -3600,7 +3530,10 @@ fold_rtx (x, insn)
            rtx new;
 
            if (CONSTANT_P (constant) && GET_CODE (constant) != CONST_INT)
-             constant_pool_entries_cost = COST (constant);
+             {
+               constant_pool_entries_cost = COST (constant);
+               constant_pool_entries_regcost = approx_reg_cost (constant);
+             }
 
            /* If we are loading the full constant, we have an equivalence.  */
            if (offset == 0 && mode == const_mode)
@@ -3854,10 +3787,11 @@ fold_rtx (x, insn)
       || code == LTGT || code == UNEQ || code == ORDERED
       || code == UNORDERED)
     {
-      if (must_swap || (const_arg0
-                       && (const_arg1 == 0
-                           || (GET_CODE (const_arg0) == CONST_INT
-                               && GET_CODE (const_arg1) != CONST_INT))))
+      if (must_swap
+         || swap_commutative_operands_p (const_arg0 ? const_arg0
+                                                    : XEXP (x, 0),
+                                         const_arg1 ? const_arg1
+                                                    : XEXP (x, 1)))
        {
          rtx tem = XEXP (x, 0);
 
@@ -4223,7 +4157,7 @@ fold_rtx (x, insn)
                 with a pre- or post-increment.  Similarly for two subtracts of
                 identical powers of two with post decrement.  */
 
-             if (code == PLUS && INTVAL (const_arg1) == INTVAL (inner_const)
+             if (code == PLUS && const_arg1 == inner_const
                  && ((HAVE_PRE_INCREMENT
                          && exact_log2 (INTVAL (const_arg1)) >= 0)
                      || (HAVE_POST_INCREMENT
@@ -4327,8 +4261,7 @@ fold_rtx (x, insn)
    Return 0 if we don't know one.  */
 
 static rtx
-equiv_constant (x)
-     rtx x;
+equiv_constant (rtx x)
 {
   if (GET_CODE (x) == REG
       && REGNO_QTY_VALID_P (REGNO (x)))
@@ -4378,9 +4311,7 @@ equiv_constant (x)
    This is similar to gen_lowpart in emit-rtl.c.  */
 
 rtx
-gen_lowpart_if_possible (mode, x)
-     enum machine_mode mode;
-     rtx x;
+gen_lowpart_if_possible (enum machine_mode mode, rtx x)
 {
   rtx result = gen_lowpart_common (mode, x);
 
@@ -4416,16 +4347,14 @@ gen_lowpart_if_possible (mode, x)
 
    In certain cases, this can cause us to add an equivalence.  For example,
    if we are following the taken case of
-       if (i == 2)
+       if (i == 2)
    we can add the fact that `i' and '2' are now equivalent.
 
    In any case, we can record that this comparison was passed.  If the same
    comparison is seen later, we will know its value.  */
 
 static void
-record_jump_equiv (insn, taken)
-     rtx insn;
-     int taken;
+record_jump_equiv (rtx insn, int taken)
 {
   int cond_known_true;
   rtx op0, op1;
@@ -4476,11 +4405,8 @@ record_jump_equiv (insn, taken)
    above function and called recursively.  */
 
 static void
-record_jump_cond (code, mode, op0, op1, reversed_nonequality)
-     enum rtx_code code;
-     enum machine_mode mode;
-     rtx op0, op1;
-     int reversed_nonequality;
+record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
+                 rtx op1, int reversed_nonequality)
 {
   unsigned op0_hash, op1_hash;
   int op0_in_memory, op1_in_memory;
@@ -4731,9 +4657,7 @@ struct set
 };
 
 static void
-cse_insn (insn, libcall_insn)
-     rtx insn;
-     rtx libcall_insn;
+cse_insn (rtx insn, rtx libcall_insn)
 {
   rtx x = PATTERN (insn);
   int i;
@@ -4773,7 +4697,7 @@ cse_insn (insn, libcall_insn)
 
   if (GET_CODE (x) == SET)
     {
-      sets = (struct set *) alloca (sizeof (struct set));
+      sets = alloca (sizeof (struct set));
       sets[0].rtl = x;
 
       /* Ignore SETs that are unconditional jumps.
@@ -4808,7 +4732,7 @@ cse_insn (insn, libcall_insn)
     {
       int lim = XVECLEN (x, 0);
 
-      sets = (struct set *) alloca (lim * sizeof (struct set));
+      sets = alloca (lim * sizeof (struct set));
 
       /* Find all regs explicitly clobbered in this insn,
         and ensure they are not replaced with any other regs
@@ -5492,7 +5416,11 @@ cse_insn (insn, libcall_insn)
            {
              trial = src_folded, src_folded_cost = MAX_COST;
              if (src_folded_force_flag)
-               trial = force_const_mem (mode, trial);
+               {
+                 rtx forced = force_const_mem (mode, trial);
+                 if (forced)
+                   trial = forced;
+               }
            }
          else if (src
                   && preferrable (src_cost, src_regcost,
@@ -5550,8 +5478,8 @@ cse_insn (insn, libcall_insn)
                  && (GET_CODE (sets[i].orig_src) == REG
                      || GET_CODE (sets[i].orig_src) == SUBREG
                      || GET_CODE (sets[i].orig_src) == MEM))
-               replace_rtx (REG_NOTES (libcall_insn), sets[i].orig_src,
-                            copy_rtx (new));
+               simplify_replace_rtx (REG_NOTES (libcall_insn),
+                                     sets[i].orig_src, copy_rtx (new));
 
              /* The result of apply_change_group can be ignored; see
                 canon_reg.  */
@@ -5587,6 +5515,7 @@ cse_insn (insn, libcall_insn)
              src_folded_force_flag = 1;
              src_folded = trial;
              src_folded_cost = constant_pool_entries_cost;
+             src_folded_regcost = constant_pool_entries_regcost;
            }
        }
 
@@ -5679,41 +5608,6 @@ cse_insn (insn, libcall_insn)
                 making a new one if one does not already exist.  */
              set_unique_reg_note (insn, REG_EQUAL, src_const);
            }
-
-         /* 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.
-
-            Note that the *register* is required to have previously held 0,
-            not just any register in the quantity and we must point to the
-            insn that set that register to zero.
-
-            Rather than track each register individually, we just see if
-            the last set for this quantity was for this register.  */
-
-         if (REGNO_QTY_VALID_P (REGNO (dest)))
-           {
-             int dest_q = REG_QTY (REGNO (dest));
-             struct qty_table_elem *dest_ent = &qty_table[dest_q];
-
-             if (dest_ent->const_rtx == const0_rtx)
-               {
-                 /* See if we previously had a REG_WAS_0 note.  */
-                 rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
-                 rtx const_insn = dest_ent->const_insn;
-
-                 if ((tem = single_set (const_insn)) != 0
-                     && rtx_equal_p (SET_DEST (tem), dest))
-                   {
-                     if (note)
-                       XEXP (note, 0) = const_insn;
-                     else
-                       REG_NOTES (insn)
-                         = gen_rtx_INSN_LIST (REG_WAS_0, const_insn,
-                                              REG_NOTES (insn));
-                   }
-               }
-           }
        }
 
       /* Now deal with the destination.  */
@@ -6292,7 +6186,7 @@ cse_insn (insn, libcall_insn)
            }
          while (prev && GET_CODE (prev) == NOTE
                 && NOTE_LINE_NUMBER (prev) != NOTE_INSN_BASIC_BLOCK);
-           
+
          /* Do not swap the registers around if the previous instruction
             attaches a REG_EQUIV note to REG1.
 
@@ -6319,20 +6213,6 @@ cse_insn (insn, libcall_insn)
              validate_change (insn, &SET_SRC (sets[0].rtl), dest, 1);
              apply_change_group ();
 
-             /* If there was a REG_WAS_0 note on PREV, remove it.  Move
-                any REG_WAS_0 note on INSN to PREV.  */
-             note = find_reg_note (prev, REG_WAS_0, NULL_RTX);
-             if (note)
-               remove_note (prev, note);
-
-             note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
-             if (note)
-               {
-                 remove_note (insn, note);
-                 XEXP (note, 1) = REG_NOTES (prev);
-                 REG_NOTES (prev) = note;
-               }
-
              /* If INSN has a REG_EQUAL note, and this note mentions
                 REG0, then we must delete it, because the value in
                 REG0 has changed.  If the note's value is REG1, we must
@@ -6374,7 +6254,7 @@ cse_insn (insn, libcall_insn)
 /* Remove from the hash table all expressions that reference memory.  */
 
 static void
-invalidate_memory ()
+invalidate_memory (void)
 {
   int i;
   struct table_elt *p, *next;
@@ -6392,8 +6272,7 @@ invalidate_memory ()
    1 and update the register tables to show the effect.  Else, return 0.  */
 
 static int
-addr_affects_sp_p (addr)
-     rtx addr;
+addr_affects_sp_p (rtx addr)
 {
   if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
       && GET_CODE (XEXP (addr, 0)) == REG
@@ -6424,8 +6303,7 @@ addr_affects_sp_p (addr)
    X is the pattern of the insn.  */
 
 static void
-invalidate_from_clobbers (x)
-     rtx x;
+invalidate_from_clobbers (rtx x)
 {
   if (GET_CODE (x) == CLOBBER)
     {
@@ -6470,9 +6348,7 @@ invalidate_from_clobbers (x)
    Return the replacement for X.  */
 
 static rtx
-cse_process_notes (x, object)
-     rtx x;
-     rtx object;
+cse_process_notes (rtx x, rtx object)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt = GET_RTX_FORMAT (code);
@@ -6564,8 +6440,7 @@ cse_process_notes (x, object)
    jumps to a label used only once.  */
 
 static void
-cse_around_loop (loop_start)
-     rtx loop_start;
+cse_around_loop (rtx loop_start)
 {
   rtx insn;
   int i;
@@ -6636,10 +6511,7 @@ cse_around_loop (loop_start)
    since they are done elsewhere.  This function is called via note_stores.  */
 
 static void
-invalidate_skipped_set (dest, set, data)
-     rtx set;
-     rtx dest;
-     void *data ATTRIBUTE_UNUSED;
+invalidate_skipped_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
 {
   enum rtx_code code = GET_CODE (dest);
 
@@ -6673,8 +6545,7 @@ invalidate_skipped_set (dest, set, data)
    conditionally executed.  */
 
 static void
-invalidate_skipped_block (start)
-     rtx start;
+invalidate_skipped_block (rtx start)
 {
   rtx insn;
 
@@ -6701,10 +6572,7 @@ invalidate_skipped_block (start)
    NULL_RTX.  */
 
 static void
-cse_check_loop_start (x, set, data)
-     rtx x;
-     rtx set ATTRIBUTE_UNUSED;
-     void *data;
+cse_check_loop_start (rtx x, rtx set ATTRIBUTE_UNUSED, void *data)
 {
   rtx *cse_check_loop_start_value = (rtx *) data;
 
@@ -6735,10 +6603,7 @@ cse_check_loop_start (x, set, data)
    In any event, we invalidate whatever this SET or CLOBBER modifies.  */
 
 static void
-cse_set_around_loop (x, insn, loop_start)
-     rtx x;
-     rtx insn;
-     rtx loop_start;
+cse_set_around_loop (rtx x, rtx insn, rtx loop_start)
 {
   struct table_elt *src_elt;
 
@@ -6810,7 +6675,15 @@ cse_set_around_loop (x, insn, loop_start)
                              abort ();
                          }
                        else
-                         emit_insn_after (move, p);
+                         {
+                           if (control_flow_insn_p (p))
+                             /* p can cause a control flow transfer so it
+                                is the last insn of a basic block.  We can't
+                                therefore use emit_insn_after.  */
+                             emit_insn_before (move, next_nonnote_insn (p));
+                           else
+                             emit_insn_after (move, p);
+                         }
                      }
                    break;
                  }
@@ -6845,12 +6718,8 @@ cse_set_around_loop (x, insn, loop_start)
    to construct the output branch path.  */
 
 void
-cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
-     rtx insn;
-     struct cse_basic_block_data *data;
-     int follow_jumps;
-     int after_loop;
-     int skip_blocks;
+cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
+                       int follow_jumps, int after_loop, int skip_blocks)
 {
   rtx p = insn, q;
   int nsets = 0;
@@ -6947,7 +6816,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
         In this case invalidate_skipped_block will be called to invalidate any
         registers set in the block when following the jump.  */
 
-      else if ((follow_jumps || skip_blocks) && path_size < PATHLENGTH - 1
+      else if ((follow_jumps || skip_blocks) && path_size < PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH) - 1
               && GET_CODE (p) == JUMP_INSN
               && GET_CODE (PATTERN (p)) == SET
               && GET_CODE (SET_SRC (PATTERN (p))) == IF_THEN_ELSE
@@ -7067,19 +6936,19 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
    in conditional jump instructions.  */
 
 int
-cse_main (f, nregs, after_loop, file)
-     rtx f;
-     int nregs;
-     int after_loop;
-     FILE *file;
+cse_main (rtx f, int nregs, int after_loop, FILE *file)
 {
   struct cse_basic_block_data val;
   rtx insn = f;
   int i;
 
+  val.path = xmalloc (sizeof (struct branch_path)
+                     * PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
+
   cse_jumps_altered = 0;
   recorded_label_ref = 0;
   constant_pool_entries_cost = 0;
+  constant_pool_entries_regcost = 0;
   val.path_size = 0;
 
   init_recog ();
@@ -7089,8 +6958,7 @@ cse_main (f, nregs, after_loop, file)
 
   max_insn_uid = get_max_uid ();
 
-  reg_eqv_table = (struct reg_eqv_elem *)
-    xmalloc (nregs * sizeof (struct reg_eqv_elem));
+  reg_eqv_table = xmalloc (nregs * sizeof (struct reg_eqv_elem));
 
 #ifdef LOAD_EXTEND_OP
 
@@ -7106,7 +6974,7 @@ cse_main (f, nregs, after_loop, file)
   /* Find the largest uid.  */
 
   max_uid = get_max_uid ();
-  uid_cuid = (int *) xcalloc (max_uid + 1, sizeof (int));
+  uid_cuid = xcalloc (max_uid + 1, sizeof (int));
 
   /* Compute the mapping from uids to cuids.
      CUIDs are numbers assigned to insns, like uids,
@@ -7200,6 +7068,7 @@ cse_main (f, nregs, after_loop, file)
   end_alias_analysis ();
   free (uid_cuid);
   free (reg_eqv_table);
+  free (val.path);
 
   return cse_jumps_altered || recorded_label_ref;
 }
@@ -7213,10 +7082,8 @@ cse_main (f, nregs, after_loop, file)
    block and this CSE pass is before loop.c.  */
 
 static rtx
-cse_basic_block (from, to, next_branch, around_loop)
-     rtx from, to;
-     struct branch_path *next_branch;
-     int around_loop;
+cse_basic_block (rtx from, rtx to, struct branch_path *next_branch,
+                int around_loop)
 {
   rtx insn;
   int to_usage = 0;
@@ -7226,9 +7093,7 @@ cse_basic_block (from, to, next_branch, around_loop)
   /* This array is undefined before max_reg, so only allocate
      the space actually needed and adjust the start.  */
 
-  qty_table
-    = (struct qty_table_elem *) xmalloc ((max_qty - max_reg)
-                                        * sizeof (struct qty_table_elem));
+  qty_table = xmalloc ((max_qty - max_reg) * sizeof (struct qty_table_elem));
   qty_table -= max_reg;
 
   new_basic_block ();
@@ -7377,7 +7242,10 @@ cse_basic_block (from, to, next_branch, around_loop)
             following branches in this case.  */
          to_usage = 0;
          val.path_size = 0;
+         val.path = xmalloc (sizeof (struct branch_path)
+                             * PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
          cse_end_of_basic_block (insn, &val, 0, 0, 0);
+         free (val.path);
 
          /* If the tables we allocated have enough space left
             to handle all the SETs in the next basic block,
@@ -7426,9 +7294,7 @@ cse_basic_block (from, to, next_branch, around_loop)
    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;
+check_for_label_ref (rtx *rtl, void *data)
 {
   rtx insn = (rtx) data;
 
@@ -7445,18 +7311,10 @@ check_for_label_ref (rtl, data)
 \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.
-
-   Don't count a usage of DEST, which is the SET_DEST of a SET which
-   contains X in its SET_SRC.  This is because such a SET does not
-   modify the liveness of DEST.  */
+   we count each register usage.  */
 
 static void
-count_reg_usage (x, counts, dest, incr)
-     rtx x;
-     int *counts;
-     rtx dest;
-     int incr;
+count_reg_usage (rtx x, int *counts, int incr)
 {
   enum rtx_code code;
   rtx note;
@@ -7469,8 +7327,7 @@ count_reg_usage (x, counts, dest, incr)
   switch (code = GET_CODE (x))
     {
     case REG:
-      if (x != dest)
-       counts[REGNO (x)] += incr;
+      counts[REGNO (x)] += incr;
       return;
 
     case PC:
@@ -7487,32 +7344,61 @@ count_reg_usage (x, counts, dest, incr)
       /* If we are clobbering a MEM, mark any registers inside the address
          as being used.  */
       if (GET_CODE (XEXP (x, 0)) == MEM)
-       count_reg_usage (XEXP (XEXP (x, 0), 0), counts, NULL_RTX, incr);
+       count_reg_usage (XEXP (XEXP (x, 0), 0), counts, incr);
       return;
 
     case SET:
       /* Unless we are setting a REG, count everything in SET_DEST.  */
       if (GET_CODE (SET_DEST (x)) != REG)
-       count_reg_usage (SET_DEST (x), counts, NULL_RTX, incr);
-      count_reg_usage (SET_SRC (x), counts,
-                      SET_DEST (x),
-                      incr);
+       count_reg_usage (SET_DEST (x), counts, incr);
+      count_reg_usage (SET_SRC (x), counts, incr);
       return;
 
     case CALL_INSN:
-      count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, NULL_RTX, incr);
+      count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, incr);
       /* Fall through.  */
 
     case INSN:
     case JUMP_INSN:
-      count_reg_usage (PATTERN (x), counts, NULL_RTX, incr);
+      count_reg_usage (PATTERN (x), counts, incr);
 
       /* Things used in a REG_EQUAL note aren't dead since loop may try to
         use them.  */
 
       note = find_reg_equal_equiv_note (x);
       if (note)
-        count_reg_usage (XEXP (note, 0), counts, NULL_RTX, incr);
+       {
+         rtx eqv = XEXP (note, 0);
+
+         if (GET_CODE (eqv) == EXPR_LIST)
+         /* This REG_EQUAL note describes the result of a function call.
+            Process all the arguments.  */
+           do
+             {
+               count_reg_usage (XEXP (eqv, 0), counts, incr);
+               eqv = XEXP (eqv, 1);
+             }
+           while (eqv && GET_CODE (eqv) == EXPR_LIST);
+         else
+           count_reg_usage (eqv, counts, incr);
+       }
+      return;
+
+    case EXPR_LIST:
+      if (REG_NOTE_KIND (x) == REG_EQUAL
+         || (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE)
+         /* FUNCTION_USAGE expression lists may include (CLOBBER (mem /u)),
+            involving registers in the address.  */
+         || GET_CODE (XEXP (x, 0)) == CLOBBER)
+       count_reg_usage (XEXP (x, 0), counts, incr);
+
+      count_reg_usage (XEXP (x, 1), counts, incr);
+      return;
+
+    case ASM_OPERANDS:
+      /* Iterate over just the inputs, not the constraints as well.  */
+      for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
+       count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, incr);
       return;
 
     case INSN_LIST:
@@ -7526,19 +7412,17 @@ count_reg_usage (x, counts, dest, incr)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       count_reg_usage (XEXP (x, i), counts, dest, incr);
+       count_reg_usage (XEXP (x, i), counts, incr);
       else if (fmt[i] == 'E')
        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         count_reg_usage (XVECEXP (x, i, j), counts, dest, incr);
+         count_reg_usage (XVECEXP (x, i, j), counts, 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;
+set_live_p (rtx set, rtx insn ATTRIBUTE_UNUSED, /* Only used with HAVE_cc0.  */
+           int *counts)
 {
 #ifdef HAVE_cc0
   rtx tem;
@@ -7571,9 +7455,7 @@ set_live_p (set, insn, counts)
 /* Return true if insn is live.  */
 
 static bool
-insn_live_p (insn, counts)
-     rtx insn;
-     int *counts;
+insn_live_p (rtx insn, int *counts)
 {
   int i;
   if (flag_non_call_exceptions && may_trap_p (PATTERN (insn)))
@@ -7603,37 +7485,51 @@ insn_live_p (insn, counts)
 /* Return true if libcall is dead as a whole.  */
 
 static bool
-dead_libcall_p (insn, counts)
-     rtx insn;
-     int *counts;
+dead_libcall_p (rtx insn, int *counts)
 {
-  rtx note;
+  rtx note, set, new;
+
   /* 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 (!note)
+    return false;
+
+  set = single_set (insn);
+  if (!set)
+    return false;
 
-      if (!new)
-       new = XEXP (note, 0);
+  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);
+  /* While changing insn, we must update the counts accordingly.  */
+  count_reg_usage (insn, counts, -1);
 
-      if (set && validate_change (insn, &SET_SRC (set), new, 0))
+  if (validate_change (insn, &SET_SRC (set), new, 0))
+    {
+      count_reg_usage (insn, counts, 1);
+      remove_note (insn, find_reg_note (insn, REG_RETVAL, NULL_RTX));
+      remove_note (insn, note);
+      return true;
+    }
+
+  if (CONSTANT_P (new))
+    {
+      new = force_const_mem (GET_MODE (SET_DEST (set)), new);
+      if (new && validate_change (insn, &SET_SRC (set), new, 0))
        {
-          count_reg_usage (insn, counts, NULL_RTX, 1);
+         count_reg_usage (insn, counts, 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);
     }
+
+  count_reg_usage (insn, counts, 1);
   return false;
 }
 
@@ -7646,9 +7542,7 @@ dead_libcall_p (insn, counts)
    remaining passes of the compilation are also sped up.  */
 
 int
-delete_trivially_dead_insns (insns, nreg)
-     rtx insns;
-     int nreg;
+delete_trivially_dead_insns (rtx insns, int nreg)
 {
   int *counts;
   rtx insn, prev;
@@ -7657,9 +7551,9 @@ delete_trivially_dead_insns (insns, nreg)
 
   timevar_push (TV_DELETE_TRIVIALLY_DEAD);
   /* First count the number of times each register is used.  */
-  counts = (int *) xcalloc (nreg, sizeof (int));
+  counts = xcalloc (nreg, sizeof (int));
   for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
-    count_reg_usage (insn, counts, NULL_RTX, 1);
+    count_reg_usage (insn, counts, 1);
 
   do
     {
@@ -7703,7 +7597,7 @@ delete_trivially_dead_insns (insns, nreg)
 
          if (! live_insn)
            {
-             count_reg_usage (insn, counts, NULL_RTX, -1);
+             count_reg_usage (insn, counts, -1);
              delete_insn_and_edges (insn);
              ndead++;
            }