OSDN Git Service

* combine.c (move_deaths): Compare LUIDs within the same BB only.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 6077e78..0f8b087 100644 (file)
@@ -1,13 +1,13 @@
 /* Optimize by combining instructions for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ 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 GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* This module is essentially the "combiner" phase of the U. of Arizona
    Portable Optimizer, but redone to work on our list-structured
@@ -105,6 +104,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "timevar.h"
 #include "tree-pass.h"
 #include "df.h"
+#include "cgraph.h"
 
 /* Number of attempts to combine instructions in this function.  */
 
@@ -143,11 +143,7 @@ static rtx i2mod_old_rhs;
 
 static rtx i2mod_new_rhs;
 \f
-/* Maximum register number, which is the size of the tables below.  */
-
-static unsigned int combine_max_regno;
-
-struct reg_stat {
+typedef struct reg_stat_struct {
   /* Record last point of death of (hard or pseudo) register n.  */
   rtx                          last_death;
 
@@ -254,9 +250,12 @@ struct reg_stat {
      value.  */
 
   ENUM_BITFIELD(machine_mode)  truncated_to_mode : 8;
-};
+} reg_stat_type;
+
+DEF_VEC_O(reg_stat_type);
+DEF_VEC_ALLOC_O(reg_stat_type,heap);
 
-static struct reg_stat *reg_stat;
+static VEC(reg_stat_type,heap) *reg_stat;
 
 /* Record the luid of the last insn that invalidated memory
    (anything that writes memory, and subroutine calls, but not pushes).  */
@@ -298,6 +297,7 @@ static rtx added_links_insn;
 
 /* Basic block in which we are performing combines.  */
 static basic_block this_basic_block;
+static bool optimize_this_for_speed_p;
 
 \f
 /* Length of the currently allocated uid_insn_cost array.  */
@@ -342,10 +342,12 @@ static int nonzero_sign_valid;
 /* Record one modification to rtl structure
    to be undone by storing old_contents into *where.  */
 
+enum undo_kind { UNDO_RTX, UNDO_INT, UNDO_MODE };
+
 struct undo
 {
   struct undo *next;
-  enum { UNDO_RTX, UNDO_INT, UNDO_MODE } kind;
+  enum undo_kind kind;
   union { rtx r; int i; enum machine_mode m; } old_contents;
   union { rtx *r; int *i; } where;
 };
@@ -370,18 +372,18 @@ static struct undobuf undobuf;
 
 static int n_occurrences;
 
-static rtx reg_nonzero_bits_for_combine (rtx, enum machine_mode, rtx,
+static rtx reg_nonzero_bits_for_combine (const_rtx, enum machine_mode, const_rtx,
                                         enum machine_mode,
                                         unsigned HOST_WIDE_INT,
                                         unsigned HOST_WIDE_INT *);
-static rtx reg_num_sign_bit_copies_for_combine (rtx, enum machine_mode, rtx,
+static rtx reg_num_sign_bit_copies_for_combine (const_rtx, enum machine_mode, const_rtx,
                                                enum machine_mode,
                                                unsigned int, unsigned int *);
 static void do_SUBST (rtx *, rtx);
 static void do_SUBST_INT (int *, int);
 static void init_reg_last (void);
 static void setup_incoming_promotions (rtx);
-static void set_nonzero_bits_and_sign_copies (rtx, rtx, void *);
+static void set_nonzero_bits_and_sign_copies (rtx, const_rtx, void *);
 static int cant_combine_insn_p (rtx);
 static int can_combine_p (rtx, rtx, rtx, rtx, rtx *, rtx *);
 static int combinable_i3pat (rtx, rtx *, rtx, rtx, int, rtx *);
@@ -396,7 +398,7 @@ static rtx simplify_if_then_else (rtx);
 static rtx simplify_set (rtx);
 static rtx simplify_logical (rtx);
 static rtx expand_compound_operation (rtx);
-static rtx expand_field_assignment (rtx);
+static const_rtx expand_field_assignment (const_rtx);
 static rtx make_extraction (enum machine_mode, rtx, HOST_WIDE_INT,
                            rtx, unsigned HOST_WIDE_INT, int, int, int);
 static rtx extract_left_shift (rtx, int);
@@ -426,13 +428,13 @@ static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
 static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
 static void update_table_tick (rtx);
 static void record_value_for_reg (rtx, rtx, rtx);
-static void check_conversions (rtx, rtx);
-static void record_dead_and_set_regs_1 (rtx, rtx, void *);
+static void check_promoted_subreg (rtx, rtx);
+static void record_dead_and_set_regs_1 (rtx, const_rtx, void *);
 static void record_dead_and_set_regs (rtx);
 static int get_last_value_validate (rtx *, rtx, int, int);
-static rtx get_last_value (rtx);
-static int use_crosses_set_p (rtx, int);
-static void reg_dead_at_p_1 (rtx, rtx, void *);
+static rtx get_last_value (const_rtx);
+static int use_crosses_set_p (const_rtx, int);
+static void reg_dead_at_p_1 (rtx, const_rtx, void *);
 static int reg_dead_at_p (rtx, rtx);
 static void move_deaths (rtx, rtx, int, rtx, rtx *);
 static int reg_bitfield_target_p (rtx, rtx);
@@ -442,8 +444,9 @@ static void mark_used_regs_combine (rtx);
 static void record_promoted_value (rtx, rtx);
 static int unmentioned_reg_p_1 (rtx *, void *);
 static bool unmentioned_reg_p (rtx, rtx);
-static void record_truncated_value (rtx);
-static bool reg_truncated_to_mode (enum machine_mode, rtx);
+static int record_truncated_value (rtx *, void *);
+static void record_truncated_values (rtx *, void *);
+static bool reg_truncated_to_mode (enum machine_mode, const_rtx);
 static rtx gen_lowpart_or_truncate (enum machine_mode, rtx);
 \f
 
@@ -468,6 +471,25 @@ static rtx gen_lowpart_or_truncate (enum machine_mode, rtx);
 static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER;
 
 \f
+/* Try to split PATTERN found in INSN.  This returns NULL_RTX if
+   PATTERN can not be split.  Otherwise, it returns an insn sequence.
+   This is a wrapper around split_insns which ensures that the
+   reg_stat vector is made larger if the splitter creates a new
+   register.  */
+
+static rtx
+combine_split_insns (rtx pattern, rtx insn)
+{
+  rtx ret;
+  unsigned int nregs;
+
+  ret = split_insns (pattern, insn);
+  nregs = max_reg_num ();
+  if (nregs > VEC_length (reg_stat_type, reg_stat))
+    VEC_safe_grow_cleared (reg_stat_type, heap, reg_stat, nregs);
+  return ret;
+}
+
 /* This is used by find_single_use to locate an rtx in LOC that
    contains exactly one use of DEST, which is typically either a REG
    or CC0.  It returns a pointer to the innermost rtx expression
@@ -585,6 +607,7 @@ find_single_use_1 (rtx dest, rtx *loc)
 static rtx *
 find_single_use (rtx dest, rtx insn, rtx *ploc)
 {
+  basic_block bb;
   rtx next;
   rtx *result;
   rtx link;
@@ -607,9 +630,10 @@ find_single_use (rtx dest, rtx insn, rtx *ploc)
   if (!REG_P (dest))
     return 0;
 
-  for (next = next_nonnote_insn (insn);
-       next != 0 && !LABEL_P (next);
-       next = next_nonnote_insn (next))
+  bb = BLOCK_FOR_INSN (insn);
+  for (next = NEXT_INSN (insn);
+       next && BLOCK_FOR_INSN (next) == bb;
+       next = NEXT_INSN (next))
     if (INSN_P (next) && dead_or_set_p (next, dest))
       {
        for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
@@ -733,7 +757,7 @@ do_SUBST_MODE (rtx *into, enum machine_mode newval)
   buf->kind = UNDO_MODE;
   buf->where.r = into;
   buf->old_contents.m = oldval;
-  PUT_MODE (*into, newval);
+  adjust_reg_mode (*into, newval);
 
   buf->next = undobuf.undos, undobuf.undos = buf;
 }
@@ -741,14 +765,17 @@ do_SUBST_MODE (rtx *into, enum machine_mode newval)
 #define SUBST_MODE(INTO, NEWVAL)  do_SUBST_MODE(&(INTO), (NEWVAL))
 \f
 /* Subroutine of try_combine.  Determine whether the combine replacement
-   patterns NEWPAT and NEWI2PAT are cheaper according to insn_rtx_cost
-   that the original instruction sequence I1, I2 and I3.  Note that I1
-   and/or NEWI2PAT may be NULL_RTX.  This function returns false, if the
-   costs of all instructions can be estimated, and the replacements are
-   more expensive than the original sequence.  */
+   patterns NEWPAT, NEWI2PAT and NEWOTHERPAT are cheaper according to
+   insn_rtx_cost that the original instruction sequence I1, I2, I3 and
+   undobuf.other_insn.  Note that I1 and/or NEWI2PAT may be NULL_RTX. 
+   NEWOTHERPAT and undobuf.other_insn may also both be NULL_RTX.  This
+   function returns false, if the costs of all instructions can be
+   estimated, and the replacements are more expensive than the original
+   sequence.  */
 
 static bool
-combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat)
+combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat,
+                      rtx newotherpat)
 {
   int i1_cost, i2_cost, i3_cost;
   int new_i2_cost, new_i3_cost;
@@ -771,10 +798,10 @@ combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat)
     }
 
   /* Calculate the replacement insn_rtx_costs.  */
-  new_i3_cost = insn_rtx_cost (newpat);
+  new_i3_cost = insn_rtx_cost (newpat, optimize_this_for_speed_p);
   if (newi2pat)
     {
-      new_i2_cost = insn_rtx_cost (newi2pat);
+      new_i2_cost = insn_rtx_cost (newi2pat, optimize_this_for_speed_p);
       new_cost = (new_i2_cost > 0 && new_i3_cost > 0)
                 ? new_i2_cost + new_i3_cost : 0;
     }
@@ -789,7 +816,7 @@ combine_validate_cost (rtx i1, rtx i2, rtx i3, rtx newpat, rtx newi2pat)
       int old_other_cost, new_other_cost;
 
       old_other_cost = INSN_COST (undobuf.other_insn);
-      new_other_cost = insn_rtx_cost (PATTERN (undobuf.other_insn));
+      new_other_cost = insn_rtx_cost (newotherpat, optimize_this_for_speed_p);
       if (old_other_cost > 0 && new_other_cost > 0)
        {
          old_cost += old_other_cost;
@@ -860,23 +887,6 @@ delete_noop_moves (void)
          next = NEXT_INSN (insn);
          if (INSN_P (insn) && noop_move_p (insn))
            {
-             rtx note;
-
-             /* If we're about to remove the first insn of a libcall
-                then move the libcall note to the next real insn and
-                update the retval note.  */
-             if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX))
-                      && XEXP (note, 0) != insn)
-               {
-                 rtx new_libcall_insn = next_real_insn (insn);
-                 rtx retval_note = find_reg_note (XEXP (note, 0),
-                                                  REG_RETVAL, NULL_RTX);
-                 REG_NOTES (new_libcall_insn)
-                   = gen_rtx_INSN_LIST (REG_LIBCALL, XEXP (note, 0),
-                                        REG_NOTES (new_libcall_insn));
-                 XEXP (retval_note, 0) = new_libcall_insn;
-               }
-
              if (dump_file)
                fprintf (dump_file, "deleting noop move %d\n", INSN_UID (insn));
 
@@ -894,7 +904,7 @@ create_log_links (void)
 {
   basic_block bb;
   rtx *next_use, insn;
-  struct df_ref **def_vec, **use_vec;
+  df_ref *def_vec, *use_vec;
 
   next_use = XCNEWVEC (rtx, max_reg_num ());
 
@@ -919,7 +929,7 @@ create_log_links (void)
 
           for (def_vec = DF_INSN_DEFS (insn); *def_vec; def_vec++)
             {
-             struct df_ref *def = *def_vec;
+             df_ref def = *def_vec;
               int regno = DF_REF_REGNO (def);
               rtx use_insn;
 
@@ -955,15 +965,25 @@ create_log_links (void)
                      assignments later.  */
                   if (regno >= FIRST_PSEUDO_REGISTER
                       || asm_noperands (PATTERN (use_insn)) < 0)
-                    LOG_LINKS (use_insn) =
-                      alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
+                   {
+                     /* Don't add duplicate links between instructions.  */
+                     rtx links;
+                     for (links = LOG_LINKS (use_insn); links;
+                          links = XEXP (links, 1))
+                       if (insn == XEXP (links, 0))
+                         break;
+
+                     if (!links)
+                       LOG_LINKS (use_insn) =
+                         alloc_INSN_LIST (insn, LOG_LINKS (use_insn));
+                   }
                 }
               next_use[regno] = NULL_RTX;
             }
 
           for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
             {
-             struct df_ref *use = *use_vec;
+             df_ref use = *use_vec;
              int regno = DF_REF_REGNO (use);
 
               /* Do not consider the usage of the stack pointer
@@ -1021,11 +1041,9 @@ combine_instructions (rtx f, unsigned int nregs)
   combine_extras = 0;
   combine_successes = 0;
 
-  combine_max_regno = nregs;
-
   rtl_hooks = combine_rtl_hooks;
 
-  reg_stat = XCNEWVEC (struct reg_stat, nregs);
+  VEC_safe_grow_cleared (reg_stat_type, heap, reg_stat, nregs);
 
   init_recog_no_volatile ();
 
@@ -1048,16 +1066,19 @@ combine_instructions (rtx f, unsigned int nregs)
      Also set any known values so that we can use it while searching
      for what bits are known to be set.  */
 
-  label_tick = label_tick_ebb_start = 1;
-
   setup_incoming_promotions (first);
 
   create_log_links ();
+  label_tick_ebb_start = ENTRY_BLOCK_PTR->index;
   FOR_EACH_BB (this_basic_block)
     {
+      optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block);
       last_call_luid = 0;
       mem_last_set = -1;
-      label_tick++;
+      label_tick = this_basic_block->index;
+      if (!single_pred_p (this_basic_block)
+         || single_pred (this_basic_block)->index != label_tick - 1)
+       label_tick_ebb_start = label_tick;
       FOR_BB_INSNS (this_basic_block, insn)
         if (INSN_P (insn) && BLOCK_FOR_INSN (insn))
          {
@@ -1077,28 +1098,32 @@ combine_instructions (rtx f, unsigned int nregs)
 
            /* Record the current insn_rtx_cost of this instruction.  */
            if (NONJUMP_INSN_P (insn))
-             INSN_COST (insn) = insn_rtx_cost (PATTERN (insn));
+             INSN_COST (insn) = insn_rtx_cost (PATTERN (insn),
+                                               optimize_this_for_speed_p);
            if (dump_file)
              fprintf(dump_file, "insn_cost %d: %d\n",
                    INSN_UID (insn), INSN_COST (insn));
          }
-       else if (LABEL_P (insn))
-         label_tick_ebb_start = label_tick;
     }
 
   nonzero_sign_valid = 1;
 
   /* Now scan all the insns in forward order.  */
 
-  label_tick = label_tick_ebb_start = 1;
+  label_tick_ebb_start = ENTRY_BLOCK_PTR->index;
   init_reg_last ();
   setup_incoming_promotions (first);
 
   FOR_EACH_BB (this_basic_block)
     {
+      optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block);
       last_call_luid = 0;
       mem_last_set = -1;
-      label_tick++;
+      label_tick = this_basic_block->index;
+      if (!single_pred_p (this_basic_block)
+         || single_pred (this_basic_block)->index != label_tick - 1)
+       label_tick_ebb_start = label_tick;
+      rtl_profile_for_bb (this_basic_block);
       for (insn = BB_HEAD (this_basic_block);
           insn != NEXT_INSN (BB_END (this_basic_block));
           insn = next ? next : NEXT_INSN (insn))
@@ -1108,7 +1133,12 @@ combine_instructions (rtx f, unsigned int nregs)
            {
              /* See if we know about function return values before this
                 insn based upon SUBREG flags.  */
-             check_conversions (insn, PATTERN (insn));
+             check_promoted_subreg (insn, PATTERN (insn));
+
+             /* See if we can find hardregs and subreg of pseudos in
+                narrower modes.  This could help turning TRUNCATEs
+                into SUBREGs.  */
+             note_uses (&PATTERN (insn), record_truncated_values, NULL);
 
              /* Try this insn with each insn it links back to.  */
 
@@ -1245,11 +1275,10 @@ combine_instructions (rtx f, unsigned int nregs)
            retry:
              ;
            }
-         else if (LABEL_P (insn))
-           label_tick_ebb_start = label_tick;
        }
     }
 
+  default_rtl_profile ();
   clear_log_links ();
   clear_bb_flags ();
   new_direct_jump_p |= purge_all_dead_edges ();
@@ -1258,7 +1287,7 @@ combine_instructions (rtx f, unsigned int nregs)
   /* Clean up.  */
   free (uid_log_links);
   free (uid_insn_cost);
-  free (reg_stat);
+  VEC_free (reg_stat_type, heap, reg_stat);
 
   {
     struct undo *undo, *next;
@@ -1290,8 +1319,10 @@ static void
 init_reg_last (void)
 {
   unsigned int i;
-  for (i = 0; i < combine_max_regno; i++)
-    memset (reg_stat + i, 0, offsetof (struct reg_stat, sign_bit_copies));
+  reg_stat_type *p;
+
+  for (i = 0; VEC_iterate (reg_stat_type, reg_stat, i, p); ++i)
+    memset (p, 0, offsetof (reg_stat_type, sign_bit_copies));
 }
 \f
 /* Set up any promoted values for incoming argument registers.  */
@@ -1300,6 +1331,7 @@ static void
 setup_incoming_promotions (rtx first)
 {
   tree arg;
+  bool strictly_local = false;
 
   if (!targetm.calls.promote_function_args (TREE_TYPE (cfun->decl)))
     return;
@@ -1308,27 +1340,63 @@ setup_incoming_promotions (rtx first)
        arg = TREE_CHAIN (arg))
     {
       rtx reg = DECL_INCOMING_RTL (arg);
+      int uns1, uns3;
+      enum machine_mode mode1, mode2, mode3, mode4;
 
+      /* Only continue if the incoming argument is in a register.  */
       if (!REG_P (reg))
        continue;
 
-      if (TYPE_MODE (DECL_ARG_TYPE (arg)) == TYPE_MODE (TREE_TYPE (arg)))
-       {
-         enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
-         int uns = TYPE_UNSIGNED (TREE_TYPE (arg));
-
-         mode = promote_mode (TREE_TYPE (arg), mode, &uns, 1);
-         if (mode == GET_MODE (reg) && mode != DECL_MODE (arg))
-           {
-             rtx x;
-             x = gen_rtx_CLOBBER (DECL_MODE (arg), const0_rtx);
-             x = gen_rtx_fmt_e ((uns ? ZERO_EXTEND : SIGN_EXTEND), mode, x);
-             record_value_for_reg (reg, first, x);
-           }
+      /* Determine, if possible, whether all call sites of the current
+         function lie within the current compilation unit.  (This does
+        take into account the exporting of a function via taking its
+        address, and so forth.)  */
+      strictly_local = cgraph_local_info (current_function_decl)->local;
+
+      /* The mode and signedness of the argument before any promotions happen
+         (equal to the mode of the pseudo holding it at that stage).  */
+      mode1 = TYPE_MODE (TREE_TYPE (arg));
+      uns1 = TYPE_UNSIGNED (TREE_TYPE (arg));
+
+      /* The mode and signedness of the argument after any source language and
+         TARGET_PROMOTE_PROTOTYPES-driven promotions.  */
+      mode2 = TYPE_MODE (DECL_ARG_TYPE (arg));
+      uns3 = TYPE_UNSIGNED (DECL_ARG_TYPE (arg));
+
+      /* The mode and signedness of the argument as it is actually passed, 
+         after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions.  */
+      mode3 = promote_mode (DECL_ARG_TYPE (arg), mode2, &uns3, 1);
+
+      /* The mode of the register in which the argument is being passed.  */
+      mode4 = GET_MODE (reg);
+
+      /* Eliminate sign extensions in the callee when possible.  Only
+         do this when:
+        (a) a mode promotion has occurred;
+        (b) the mode of the register is the same as the mode of
+            the argument as it is passed; and
+        (c) the signedness does not change across any of the promotions; and
+        (d) when no language-level promotions (which we cannot guarantee
+            will have been done by an external caller) are necessary,
+            unless we know that this function is only ever called from
+            the current compilation unit -- all of whose call sites will
+            do the mode1 --> mode2 promotion.  */
+      if (mode1 != mode3
+          && mode3 == mode4
+          && uns1 == uns3
+         && (mode1 == mode2 || strictly_local))
+        {
+         /* Record that the value was promoted from mode1 to mode3,
+            so that any sign extension at the head of the current
+            function may be eliminated.  */
+         rtx x;
+         x = gen_rtx_CLOBBER (mode1, const0_rtx);
+         x = gen_rtx_fmt_e ((uns3 ? ZERO_EXTEND : SIGN_EXTEND), mode3, x);
+         record_value_for_reg (reg, first, x);
        }
     }
 }
-\f
+
 /* Called via note_stores.  If X is a pseudo that is narrower than
    HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero.
 
@@ -1341,7 +1409,7 @@ setup_incoming_promotions (rtx first)
    by any set of X.  */
 
 static void
-set_nonzero_bits_and_sign_copies (rtx x, rtx set, void *data)
+set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 {
   rtx insn = (rtx) data;
   unsigned int num;
@@ -1354,10 +1422,12 @@ set_nonzero_bits_and_sign_copies (rtx x, rtx set, void *data)
            (DF_LR_IN (ENTRY_BLOCK_PTR->next_bb), REGNO (x))
       && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
     {
+      reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
+
       if (set == 0 || GET_CODE (set) == CLOBBER)
        {
-         reg_stat[REGNO (x)].nonzero_bits = GET_MODE_MASK (GET_MODE (x));
-         reg_stat[REGNO (x)].sign_bit_copies = 1;
+         rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+         rsp->sign_bit_copies = 1;
          return;
        }
 
@@ -1388,8 +1458,8 @@ set_nonzero_bits_and_sign_copies (rtx x, rtx set, void *data)
            }
          if (!link)
            {
-             reg_stat[REGNO (x)].nonzero_bits = GET_MODE_MASK (GET_MODE (x));
-             reg_stat[REGNO (x)].sign_bit_copies = 1;
+             rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+             rsp->sign_bit_copies = 1;
              return;
            }
        }
@@ -1431,18 +1501,17 @@ set_nonzero_bits_and_sign_copies (rtx x, rtx set, void *data)
 #endif
 
          /* Don't call nonzero_bits if it cannot change anything.  */
-         if (reg_stat[REGNO (x)].nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
-           reg_stat[REGNO (x)].nonzero_bits
-             |= nonzero_bits (src, nonzero_bits_mode);
+         if (rsp->nonzero_bits != ~(unsigned HOST_WIDE_INT) 0)
+           rsp->nonzero_bits |= nonzero_bits (src, nonzero_bits_mode);
          num = num_sign_bit_copies (SET_SRC (set), GET_MODE (x));
-         if (reg_stat[REGNO (x)].sign_bit_copies == 0
-             || reg_stat[REGNO (x)].sign_bit_copies > num)
-           reg_stat[REGNO (x)].sign_bit_copies = num;
+         if (rsp->sign_bit_copies == 0
+             || rsp->sign_bit_copies > num)
+           rsp->sign_bit_copies = num;
        }
       else
        {
-         reg_stat[REGNO (x)].nonzero_bits = GET_MODE_MASK (GET_MODE (x));
-         reg_stat[REGNO (x)].sign_bit_copies = 1;
+         rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+         rsp->sign_bit_copies = 1;
        }
     }
 }
@@ -1462,7 +1531,8 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
               rtx *pdest, rtx *psrc)
 {
   int i;
-  rtx set = 0, src, dest;
+  const_rtx set = 0;
+  rtx src, dest;
   rtx p;
 #ifdef AUTO_INC_DEC
   rtx link;
@@ -1582,7 +1652,7 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
   /* Don't eliminate a store in the stack pointer.  */
   if (dest == stack_pointer_rtx
       /* Don't combine with an insn that sets a register to itself if it has
-        a REG_EQUAL note.  This may be part of a REG_NO_CONFLICT sequence.  */
+        a REG_EQUAL note.  This may be part of a LIBCALL sequence.  */
       || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
       /* Can't merge an ASM_OPERANDS.  */
       || GET_CODE (src) == ASM_OPERANDS
@@ -1599,14 +1669,6 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
       || (succ && FIND_REG_INC_NOTE (succ, dest))
       /* Don't substitute into a non-local goto, this confuses CFG.  */
       || (JUMP_P (i3) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX))
-#if 0
-      /* Don't combine the end of a libcall into anything.  */
-      /* ??? This gives worse code, and appears to be unnecessary, since no
-        pass after flow uses REG_LIBCALL/REG_RETVAL notes.  Local-alloc does
-        use REG_RETVAL notes for noconflict blocks, but other code here
-        makes sure that those insns don't disappear.  */
-      || find_reg_note (insn, REG_RETVAL, NULL_RTX)
-#endif
       /* Make sure that DEST is not used after SUCC but before I3.  */
       || (succ && ! all_adjacent
          && reg_used_between_p (dest, succ, i3))
@@ -1625,15 +1687,11 @@ can_combine_p (rtx insn, rtx i3, rtx pred ATTRIBUTE_UNUSED, rtx succ,
               && use_crosses_set_p (src, DF_INSN_LUID (insn)))
              || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src))
              || GET_CODE (src) == UNSPEC_VOLATILE))
-      /* If there is a REG_NO_CONFLICT note for DEST in I3 or SUCC, we get
-        better register allocation by not doing the combine.  */
-      || find_reg_note (i3, REG_NO_CONFLICT, dest)
-      || (succ && find_reg_note (succ, REG_NO_CONFLICT, dest))
       /* Don't combine across a CALL_INSN, because that would possibly
         change whether the life span of some REGs crosses calls or not,
         and it is a pain to update that information.
         Exception: if source is a constant, moving it later can't hurt.
-        Accept that special case, because it helps -fforce-addr a lot.  */
+        Accept that as a special case.  */
       || (DF_INSN_LUID (insn) < last_call_luid && ! CONSTANT_P (src)))
     return 0;
 
@@ -1971,9 +2029,10 @@ struct likely_spilled_retval_info
 /* Called via note_stores by likely_spilled_retval_p.  Remove from info->mask
    hard registers that are known to be written to / clobbered in full.  */
 static void
-likely_spilled_retval_1 (rtx x, rtx set, void *data)
+likely_spilled_retval_1 (rtx x, const_rtx set, void *data)
 {
-  struct likely_spilled_retval_info *info = data;
+  struct likely_spilled_retval_info *const info =
+    (struct likely_spilled_retval_info *) data;
   unsigned regno, nregs;
   unsigned new_mask;
 
@@ -2057,6 +2116,8 @@ adjust_for_new_dest (rtx insn)
      of an insn just above it.  Call distribute_links to make a LOG_LINK from
      the next use of that destination.  */
   distribute_links (gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX));
+
+  df_insn_rescan (insn);
 }
 
 /* Return TRUE if combine can reuse reg X in mode MODE.
@@ -2103,6 +2164,25 @@ reg_subword_p (rtx x, rtx reg)
 }
 
 
+/* Delete the conditional jump INSN and adjust the CFG correspondingly.
+   Note that the INSN should be deleted *after* removing dead edges, so
+   that the kept edge is the fallthrough edge for a (set (pc) (pc))
+   but not for a (set (pc) (label_ref FOO)).  */
+
+static void
+update_cfg_for_uncondjump (rtx insn)
+{
+  basic_block bb = BLOCK_FOR_INSN (insn);
+
+  if (BB_END (bb) == insn)
+    purge_dead_edges (bb);
+
+  delete_insn (insn);
+  if (EDGE_COUNT (bb->succs) == 1)
+    single_succ_edge (bb)->flags |= EDGE_FALLTHRU;
+}
+
+
 /* Try to combine the insns I1 and I2 into I3.
    Here I1 and I2 appear earlier than I3.
    I1 can be zero; then we combine just I2 into I3.
@@ -2153,10 +2233,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
   /* Notes that I1, I2 or I3 is a MULT operation.  */
   int have_mult = 0;
   int swap_i2i3 = 0;
+  int changed_i3_dest = 0;
 
   int maxreg;
   rtx temp;
   rtx link;
+  rtx other_pat = 0;
+  rtx new_other_notes;
   int i;
 
   /* Exit early if one of the insns involved can't be used for
@@ -2164,16 +2247,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
   if (cant_combine_insn_p (i3)
       || cant_combine_insn_p (i2)
       || (i1 && cant_combine_insn_p (i1))
-      || likely_spilled_retval_p (i3)
-      /* We also can't do anything if I3 has a
-        REG_LIBCALL note since we don't want to disrupt the contiguity of a
-        libcall.  */
-#if 0
-      /* ??? This gives worse code, and appears to be unnecessary, since no
-        pass after flow uses REG_LIBCALL/REG_RETVAL notes.  */
-      || find_reg_note (i3, REG_LIBCALL, NULL_RTX)
-#endif
-      )
+      || likely_spilled_retval_p (i3))
     return 0;
 
   combine_attempts++;
@@ -2686,12 +2760,17 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
 
   if (i1 && GET_CODE (newpat) != CLOBBER)
     {
-      /* Before we can do this substitution, we must redo the test done
-        above (see detailed comments there) that ensures  that I1DEST
-        isn't mentioned in any SETs in NEWPAT that are field assignments.  */
-
-      if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX,
-                             0, (rtx*) 0))
+      /* Check that an autoincrement side-effect on I1 has not been lost.
+        This happens if I1DEST is mentioned in I2 and dies there, and
+        has disappeared from the new pattern.  */
+      if ((FIND_REG_INC_NOTE (i1, NULL_RTX) != 0
+          && !i1_feeds_i3
+          && dead_or_set_p (i2, i1dest)
+          && !reg_overlap_mentioned_p (i1dest, newpat))
+         /* Before we can do this substitution, we must redo the test done
+            above (see detailed comments there) that ensures  that I1DEST
+            isn't mentioned in any SETs in NEWPAT that are field assignments.  */
+          || !combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX, 0, 0))
        {
          undo_all ();
          return 0;
@@ -2842,14 +2921,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
          insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
 
          if (insn_code_number >= 0)
-           {
-             /* If we will be able to accept this, we have made a
-                change to the destination of I3.  This requires us to
-                do a few adjustments.  */
-
-             PATTERN (i3) = newpat;
-             adjust_for_new_dest (i3);
-           }
+           changed_i3_dest = 1;
        }
     }
 
@@ -2862,13 +2934,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
   if (i1 && insn_code_number < 0 && GET_CODE (newpat) == SET
       && asm_noperands (newpat) < 0)
     {
-      rtx m_split, *split;
+      rtx parallel, m_split, *split;
 
       /* See if the MD file can split NEWPAT.  If it can't, see if letting it
         use I2DEST as a scratch register will help.  In the latter case,
         convert I2DEST to the mode of the source of NEWPAT if we can.  */
 
-      m_split = split_insns (newpat, i3);
+      m_split = combine_split_insns (newpat, i3);
 
       /* We can only use I2DEST as a scratch reg if it doesn't overlap any
         inputs of NEWPAT.  */
@@ -2883,12 +2955,11 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
 
          /* First try to split using the original register as a
             scratch register.  */
-         m_split = split_insns (gen_rtx_PARALLEL
-                                (VOIDmode,
-                                 gen_rtvec (2, newpat,
-                                            gen_rtx_CLOBBER (VOIDmode,
-                                                             i2dest))),
-                                i3);
+         parallel = gen_rtx_PARALLEL (VOIDmode,
+                                      gen_rtvec (2, newpat,
+                                                 gen_rtx_CLOBBER (VOIDmode,
+                                                                  i2dest)));
+         m_split = combine_split_insns (parallel, i3);
 
          /* If that didn't work, try changing the mode of I2DEST if
             we can.  */
@@ -2908,19 +2979,19 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
                  ni2dest = regno_reg_rtx[REGNO (i2dest)];
                }
 
-             m_split = split_insns (gen_rtx_PARALLEL
-                                    (VOIDmode,
-                                     gen_rtvec (2, newpat,
-                                                gen_rtx_CLOBBER (VOIDmode,
-                                                                 ni2dest))),
-                                    i3);
+             parallel = (gen_rtx_PARALLEL
+                         (VOIDmode,
+                          gen_rtvec (2, newpat,
+                                     gen_rtx_CLOBBER (VOIDmode,
+                                                      ni2dest))));
+             m_split = combine_split_insns (parallel, i3);
 
              if (m_split == 0
                  && REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
                {
                  struct undo *buf;
 
-                 PUT_MODE (regno_reg_rtx[REGNO (i2dest)], old_mode);
+                 adjust_reg_mode (regno_reg_rtx[REGNO (i2dest)], old_mode);
                  buf = undobuf.undos;
                  undobuf.undos = buf->next;
                  buf->next = undobuf.frees;
@@ -2932,9 +3003,10 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
       /* If recog_for_combine has discarded clobbers, try to use them
         again for the split.  */
       if (m_split == 0 && newpat_vec_with_clobbers)
-       m_split
-         = split_insns (gen_rtx_PARALLEL (VOIDmode,
-                                          newpat_vec_with_clobbers), i3);
+       {
+         parallel = gen_rtx_PARALLEL (VOIDmode, newpat_vec_with_clobbers);
+         m_split = combine_split_insns (parallel, i3);
+       }
 
       if (m_split && NEXT_INSN (m_split) == NULL_RTX)
        {
@@ -3184,18 +3256,22 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
           && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
           && ! (temp = SET_DEST (XVECEXP (newpat, 0, 1)),
                 (REG_P (temp)
-                 && reg_stat[REGNO (temp)].nonzero_bits != 0
+                 && VEC_index (reg_stat_type, reg_stat,
+                               REGNO (temp))->nonzero_bits != 0
                  && GET_MODE_BITSIZE (GET_MODE (temp)) < BITS_PER_WORD
                  && GET_MODE_BITSIZE (GET_MODE (temp)) < HOST_BITS_PER_INT
-                 && (reg_stat[REGNO (temp)].nonzero_bits
+                 && (VEC_index (reg_stat_type, reg_stat,
+                                REGNO (temp))->nonzero_bits
                      != GET_MODE_MASK (word_mode))))
           && ! (GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) == SUBREG
                 && (temp = SUBREG_REG (SET_DEST (XVECEXP (newpat, 0, 1))),
                     (REG_P (temp)
-                     && reg_stat[REGNO (temp)].nonzero_bits != 0
+                     && VEC_index (reg_stat_type, reg_stat,
+                                   REGNO (temp))->nonzero_bits != 0
                      && GET_MODE_BITSIZE (GET_MODE (temp)) < BITS_PER_WORD
                      && GET_MODE_BITSIZE (GET_MODE (temp)) < HOST_BITS_PER_INT
-                     && (reg_stat[REGNO (temp)].nonzero_bits
+                     && (VEC_index (reg_stat_type, reg_stat,
+                                    REGNO (temp))->nonzero_bits
                          != GET_MODE_MASK (word_mode)))))
           && ! reg_overlap_mentioned_p (SET_DEST (XVECEXP (newpat, 0, 1)),
                                         SET_SRC (XVECEXP (newpat, 0, 1)))
@@ -3283,12 +3359,9 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
   /* If we had to change another insn, make sure it is valid also.  */
   if (undobuf.other_insn)
     {
-      rtx other_pat = PATTERN (undobuf.other_insn);
-      rtx new_other_notes;
-      rtx note, next;
-
       CLEAR_HARD_REG_SET (newpat_used_regs);
 
+      other_pat = PATTERN (undobuf.other_insn);
       other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
                                             &new_other_notes);
 
@@ -3297,24 +3370,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
          undo_all ();
          return 0;
        }
-
-      PATTERN (undobuf.other_insn) = other_pat;
-
-      /* If any of the notes in OTHER_INSN were REG_UNUSED, ensure that they
-        are still valid.  Then add any non-duplicate notes added by
-        recog_for_combine.  */
-      for (note = REG_NOTES (undobuf.other_insn); note; note = next)
-       {
-         next = XEXP (note, 1);
-
-         if (REG_NOTE_KIND (note) == REG_UNUSED
-             && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn)))
-           remove_note (undobuf.other_insn, note);
-       }
-
-      distribute_notes (new_other_notes, undobuf.other_insn,
-                       undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX);
     }
+
 #ifdef HAVE_cc0
   /* If I2 is the CC0 setter and I3 is the CC0 user then check whether
      they are adjacent to each other or not.  */
@@ -3331,15 +3388,47 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
 
   /* Only allow this combination if insn_rtx_costs reports that the
      replacement instructions are cheaper than the originals.  */
-  if (!combine_validate_cost (i1, i2, i3, newpat, newi2pat))
+  if (!combine_validate_cost (i1, i2, i3, newpat, newi2pat, other_pat))
     {
       undo_all ();
       return 0;
     }
 
+  /* If we will be able to accept this, we have made a
+     change to the destination of I3.  This requires us to
+     do a few adjustments.  */
+
+  if (changed_i3_dest)
+    {
+      PATTERN (i3) = newpat;
+      adjust_for_new_dest (i3);
+    }
+
   /* We now know that we can do this combination.  Merge the insns and
      update the status of registers and LOG_LINKS.  */
 
+  if (undobuf.other_insn)
+    {
+      rtx note, next;
+
+      PATTERN (undobuf.other_insn) = other_pat;
+
+      /* If any of the notes in OTHER_INSN were REG_UNUSED, ensure that they
+        are still valid.  Then add any non-duplicate notes added by
+        recog_for_combine.  */
+      for (note = REG_NOTES (undobuf.other_insn); note; note = next)
+       {
+         next = XEXP (note, 1);
+
+         if (REG_NOTE_KIND (note) == REG_UNUSED
+             && ! reg_set_p (XEXP (note, 0), PATTERN (undobuf.other_insn)))
+           remove_note (undobuf.other_insn, note);
+       }
+
+      distribute_notes (new_other_notes, undobuf.other_insn,
+                       undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX);
+    }
+
   if (swap_i2i3)
     {
       rtx insn;
@@ -3556,12 +3645,12 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
     if (i3dest_killed)
       {
        if (newi2pat && reg_set_p (i3dest_killed, newi2pat))
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
-                                              NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i3dest_killed,
+                                           NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, elim_i2, elim_i1);
        else
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
-                                              NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i3dest_killed,
+                                           NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            elim_i2, elim_i1);
       }
@@ -3569,10 +3658,10 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
     if (i2dest_in_i2src)
       {
        if (newi2pat && reg_set_p (i2dest, newi2pat))
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i2dest, NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX);
        else
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i2dest, NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            NULL_RTX, NULL_RTX);
       }
@@ -3580,10 +3669,10 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
     if (i1dest_in_i1src)
       {
        if (newi2pat && reg_set_p (i1dest, newi2pat))
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i1dest, NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX);
        else
-         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
+         distribute_notes (alloc_reg_note (REG_DEAD, i1dest, NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            NULL_RTX, NULL_RTX);
       }
@@ -3647,43 +3736,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
     if (newi2pat)
       note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
     note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
-
-    /* Set new_direct_jump_p if a new return or simple jump instruction
-       has been created.
-
-       If I3 is now an unconditional jump, ensure that it has a
-       BARRIER following it since it may have initially been a
-       conditional jump.  It may also be the last nonnote insn.  */
-
-    if (returnjump_p (i3) || any_uncondjump_p (i3))
-      {
-       *new_direct_jump_p = 1;
-       mark_jump_label (PATTERN (i3), i3, 0);
-
-       if ((temp = next_nonnote_insn (i3)) == NULL_RTX
-           || !BARRIER_P (temp))
-         emit_barrier_after (i3);
-      }
-
-    if (undobuf.other_insn != NULL_RTX
-       && (returnjump_p (undobuf.other_insn)
-           || any_uncondjump_p (undobuf.other_insn)))
-      {
-       *new_direct_jump_p = 1;
-
-       if ((temp = next_nonnote_insn (undobuf.other_insn)) == NULL_RTX
-           || !BARRIER_P (temp))
-         emit_barrier_after (undobuf.other_insn);
-      }
-
-    /* An NOOP jump does not need barrier, but it does need cleaning up
-       of CFG.  */
-    if (GET_CODE (newpat) == SET
-       && SET_SRC (newpat) == pc_rtx
-       && SET_DEST (newpat) == pc_rtx)
-      *new_direct_jump_p = 1;
   }
-  
+
   if (undobuf.other_insn != NULL_RTX)
     {
       if (dump_file)
@@ -3724,6 +3778,34 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
       df_insn_rescan (i3);
     }
   
+  /* Set new_direct_jump_p if a new return or simple jump instruction
+     has been created.  Adjust the CFG accordingly.  */
+
+  if (returnjump_p (i3) || any_uncondjump_p (i3))
+    {
+      *new_direct_jump_p = 1;
+      mark_jump_label (PATTERN (i3), i3, 0);
+      update_cfg_for_uncondjump (i3);
+    }
+
+  if (undobuf.other_insn != NULL_RTX
+      && (returnjump_p (undobuf.other_insn)
+         || any_uncondjump_p (undobuf.other_insn)))
+    {
+      *new_direct_jump_p = 1;
+      update_cfg_for_uncondjump (undobuf.other_insn);
+    }
+
+  /* A noop might also need cleaning up of CFG, if it comes from the
+     simplification of a jump.  */
+  if (GET_CODE (newpat) == SET
+      && SET_SRC (newpat) == pc_rtx
+      && SET_DEST (newpat) == pc_rtx)
+    {
+      *new_direct_jump_p = 1;
+      update_cfg_for_uncondjump (i3);
+    }
+  
   combine_successes++;
   undo_commit ();
 
@@ -3754,7 +3836,7 @@ undo_all (void)
          *undo->where.i = undo->old_contents.i;
          break;
        case UNDO_MODE:
-         PUT_MODE (*undo->where.r, undo->old_contents.m);
+         adjust_reg_mode (*undo->where.r, undo->old_contents.m);
          break;
        default:
          gcc_unreachable ();
@@ -3839,8 +3921,9 @@ find_split_point (rtx *loc, rtx insn)
          && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
        {
          rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
-         rtx seq = split_insns (gen_rtx_SET (VOIDmode, reg, XEXP (x, 0)),
-                                subst_insn);
+         rtx seq = combine_split_insns (gen_rtx_SET (VOIDmode, reg,
+                                                     XEXP (x, 0)),
+                                        subst_insn);
 
          /* This should have produced two insns, each of which sets our
             placeholder.  If the source of the second is a valid address,
@@ -3894,6 +3977,15 @@ find_split_point (rtx *loc, rtx insn)
                         && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
            return &XEXP (XEXP (x, 0), 0);
        }
+
+      /* If we have a PLUS whose first operand is complex, try computing it
+         separately by making a split there.  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+          && ! memory_address_p (GET_MODE (x), XEXP (x, 0))
+          && ! OBJECT_P (XEXP (XEXP (x, 0), 0))
+          && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
+                && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
+        return &XEXP (XEXP (x, 0), 0);
       break;
 
     case SET:
@@ -4212,7 +4304,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
   enum machine_mode op0_mode = VOIDmode;
   const char *fmt;
   int len, i;
-  rtx new;
+  rtx new_rtx;
 
 /* Two expressions are equal if they are identical copies of a shared
    RTX or if they are both registers with the same register number
@@ -4237,7 +4329,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
 
      So force this insn not to match in this (rare) case.  */
   if (! in_dest && code == REG && REG_P (from)
-      && REGNO (x) == REGNO (from))
+      && reg_overlap_mentioned_p (x, from))
     return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
   /* If this is an object, we are done unless it is a MEM or LO_SUM, both
@@ -4267,14 +4359,14 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
       && GET_CODE (XVECEXP (x, 0, 0)) == SET
       && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS)
     {
-      new = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy);
+      new_rtx = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy);
 
       /* If this substitution failed, this whole thing fails.  */
-      if (GET_CODE (new) == CLOBBER
-         && XEXP (new, 0) == const0_rtx)
-       return new;
+      if (GET_CODE (new_rtx) == CLOBBER
+         && XEXP (new_rtx, 0) == const0_rtx)
+       return new_rtx;
 
-      SUBST (XVECEXP (x, 0, 0), new);
+      SUBST (XVECEXP (x, 0, 0), new_rtx);
 
       for (i = XVECLEN (x, 0) - 1; i >= 1; i--)
        {
@@ -4284,14 +4376,14 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
              && GET_CODE (dest) != CC0
              && GET_CODE (dest) != PC)
            {
-             new = subst (dest, from, to, 0, unique_copy);
+             new_rtx = subst (dest, from, to, 0, unique_copy);
 
              /* If this substitution failed, this whole thing fails.  */
-             if (GET_CODE (new) == CLOBBER
-                 && XEXP (new, 0) == const0_rtx)
-               return new;
+             if (GET_CODE (new_rtx) == CLOBBER
+                 && XEXP (new_rtx, 0) == const0_rtx)
+               return new_rtx;
 
-             SUBST (SET_DEST (XVECEXP (x, 0, i)), new);
+             SUBST (SET_DEST (XVECEXP (x, 0, i)), new_rtx);
            }
        }
     }
@@ -4324,33 +4416,33 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
                {
                  if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from))
                    {
-                     new = (unique_copy && n_occurrences
+                     new_rtx = (unique_copy && n_occurrences
                             ? copy_rtx (to) : to);
                      n_occurrences++;
                    }
                  else
                    {
-                     new = subst (XVECEXP (x, i, j), from, to, 0,
+                     new_rtx = subst (XVECEXP (x, i, j), from, to, 0,
                                   unique_copy);
 
                      /* If this substitution failed, this whole thing
                         fails.  */
-                     if (GET_CODE (new) == CLOBBER
-                         && XEXP (new, 0) == const0_rtx)
-                       return new;
+                     if (GET_CODE (new_rtx) == CLOBBER
+                         && XEXP (new_rtx, 0) == const0_rtx)
+                       return new_rtx;
                    }
 
-                 SUBST (XVECEXP (x, i, j), new);
+                 SUBST (XVECEXP (x, i, j), new_rtx);
                }
            }
          else if (fmt[i] == 'e')
            {
              /* If this is a register being set, ignore it.  */
-             new = XEXP (x, i);
+             new_rtx = XEXP (x, i);
              if (in_dest
                  && i == 0
                  && (((code == SUBREG || code == ZERO_EXTRACT)
-                      && REG_P (new))
+                      && REG_P (new_rtx))
                      || code == STRICT_LOW_PART))
                ;
 
@@ -4391,7 +4483,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 #endif
 
-                 new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
+                 new_rtx = (unique_copy && n_occurrences ? copy_rtx (to) : to);
                  n_occurrences++;
                }
              else
@@ -4403,7 +4495,7 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
                   STRICT_LOW_PART, and ZERO_EXTRACT, which are the only
                   things aside from REG and MEM that should appear in a
                   SET_DEST.  */
-               new = subst (XEXP (x, i), from, to,
+               new_rtx = subst (XEXP (x, i), from, to,
                             (((in_dest
                                && (code == SUBREG || code == STRICT_LOW_PART
                                    || code == ZERO_EXTRACT))
@@ -4416,34 +4508,46 @@ subst (rtx x, rtx from, rtx to, int in_dest, int unique_copy)
                 well as prevent accidents where two CLOBBERs are considered
                 to be equal, thus producing an incorrect simplification.  */
 
-             if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
-               return new;
+             if (GET_CODE (new_rtx) == CLOBBER && XEXP (new_rtx, 0) == const0_rtx)
+               return new_rtx;
 
              if (GET_CODE (x) == SUBREG
-                 && (GET_CODE (new) == CONST_INT
-                     || GET_CODE (new) == CONST_DOUBLE))
+                 && (GET_CODE (new_rtx) == CONST_INT
+                     || GET_CODE (new_rtx) == CONST_DOUBLE))
                {
                  enum machine_mode mode = GET_MODE (x);
 
-                 x = simplify_subreg (GET_MODE (x), new,
+                 x = simplify_subreg (GET_MODE (x), new_rtx,
                                       GET_MODE (SUBREG_REG (x)),
                                       SUBREG_BYTE (x));
                  if (! x)
                    x = gen_rtx_CLOBBER (mode, const0_rtx);
                }
-             else if (GET_CODE (new) == CONST_INT
+             else if (GET_CODE (new_rtx) == CONST_INT
                       && GET_CODE (x) == ZERO_EXTEND)
                {
                  x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
-                                               new, GET_MODE (XEXP (x, 0)));
+                                               new_rtx, GET_MODE (XEXP (x, 0)));
                  gcc_assert (x);
                }
              else
-               SUBST (XEXP (x, i), new);
+               SUBST (XEXP (x, i), new_rtx);
            }
        }
     }
 
+  /* Check if we are loading something from the constant pool via float
+     extension; in this case we would undo compress_float_constant
+     optimization and degenerate constant load to an immediate value.  */
+  if (GET_CODE (x) == FLOAT_EXTEND
+      && MEM_P (XEXP (x, 0))
+      && MEM_READONLY_P (XEXP (x, 0)))
+    {
+      rtx tmp = avoid_constant_pool_reference (x);
+      if (x != tmp)
+        return x;
+    }
+
   /* Try to simplify X.  If the simplification changed the code, it is likely
      that further simplification will help, so loop, but limit the number
      of repetitions that will be performed.  */
@@ -4653,7 +4757,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
        || code == AND || code == IOR || code == XOR
        || code == SMAX || code == SMIN || code == UMAX || code == UMIN)
       && ((INTEGRAL_MODE_P (mode) && code != DIV)
-         || (flag_unsafe_math_optimizations && FLOAT_MODE_P (mode))))
+         || (flag_associative_math && FLOAT_MODE_P (mode))))
     {
       if (GET_CODE (XEXP (x, 0)) == code)
        {
@@ -4802,24 +4906,6 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
        return gen_lowpart (mode, XEXP (x, 0));
       break;
 
-#ifdef HAVE_cc0
-    case COMPARE:
-      /* Convert (compare FOO (const_int 0)) to FOO unless we aren't
-        using cc0, in which case we want to leave it as a COMPARE
-        so we can distinguish it from a register-register-copy.  */
-      if (XEXP (x, 1) == const0_rtx)
-       return XEXP (x, 0);
-
-      /* x - 0 is the same as x unless x's mode has signed zeros and
-        allows rounding towards -infinity.  Under those conditions,
-        0 - 0 is -0.  */
-      if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
-           && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
-         && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
-       return XEXP (x, 0);
-      break;
-#endif
-
     case CONST:
       /* (const (const X)) can become (const X).  Do it this way rather than
         returning the inner CONST since CONST can be shared with a
@@ -4926,7 +5012,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
        }
 
       /* Try simplify a*(b/c) as (a*b)/c.  */
-      if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
+      if (FLOAT_MODE_P (mode) && flag_associative_math 
          && GET_CODE (XEXP (x, 0)) == DIV)
        {
          rtx tem = simplify_binary_operation (MULT, mode,
@@ -5210,11 +5296,17 @@ simplify_if_then_else (rtx x)
 
       if (true_code == EQ && true_val == const0_rtx
          && exact_log2 (nzb = nonzero_bits (from, GET_MODE (from))) >= 0)
-       false_code = EQ, false_val = GEN_INT (nzb);
+       {
+         false_code = EQ;
+         false_val = GEN_INT (trunc_int_for_mode (nzb, GET_MODE (from)));
+       }
       else if (true_code == EQ && true_val == const0_rtx
               && (num_sign_bit_copies (from, GET_MODE (from))
                   == GET_MODE_BITSIZE (GET_MODE (from))))
-       false_code = EQ, false_val = constm1_rtx;
+       {
+         false_code = EQ;
+         false_val = constm1_rtx;
+       }
 
       /* Now simplify an arm if we know the value of the register in the
         branch and it is used in the arm.  Be careful due to the potential
@@ -5288,9 +5380,10 @@ simplify_if_then_else (rtx x)
   /* Look for cases where we have (abs x) or (neg (abs X)).  */
 
   if (GET_MODE_CLASS (mode) == MODE_INT
+      && comparison_p
+      && XEXP (cond, 1) == const0_rtx
       && GET_CODE (false_rtx) == NEG
       && rtx_equal_p (true_rtx, XEXP (false_rtx, 0))
-      && comparison_p
       && rtx_equal_p (true_rtx, XEXP (cond, 0))
       && ! side_effects_p (true_rtx))
     switch (true_code)
@@ -5553,9 +5646,9 @@ simplify_set (rtx x)
          /* Attempt to simplify CC user.  */
          if (GET_CODE (pat) == SET)
            {
-             rtx new = simplify_rtx (SET_SRC (pat));
-             if (new != NULL_RTX)
-               SUBST (SET_SRC (pat), new);
+             rtx new_rtx = simplify_rtx (SET_SRC (pat));
+             if (new_rtx != NULL_RTX)
+               SUBST (SET_SRC (pat), new_rtx);
            }
 
          /* Convert X into a no-op move.  */
@@ -5612,6 +5705,7 @@ simplify_set (rtx x)
        {
          int other_changed_previously = other_changed;
          unsigned HOST_WIDE_INT mask;
+         rtx old_cc_use = *cc_use;
 
          SUBST (*cc_use, gen_rtx_fmt_ee (new_code, GET_MODE (*cc_use),
                                          dest, const0_rtx));
@@ -5634,7 +5728,7 @@ simplify_set (rtx x)
              if ((recog_for_combine (&pat, other_insn, &note) < 0
                   && ! check_asm_operands (pat)))
                {
-                 PUT_CODE (*cc_use, old_code);
+                 *cc_use = old_cc_use;
                  other_changed = 0;
 
                  op0 = simplify_gen_binary (XOR, GET_MODE (op0),
@@ -5646,17 +5740,6 @@ simplify_set (rtx x)
       if (other_changed)
        undobuf.other_insn = other_insn;
 
-#ifdef HAVE_cc0
-      /* If we are now comparing against zero, change our source if
-        needed.  If we do not use cc0, we always have a COMPARE.  */
-      if (op1 == const0_rtx && dest == cc0_rtx)
-       {
-         SUBST (SET_SRC (x), op0);
-         src = op0;
-       }
-      else
-#endif
-
       /* Otherwise, if we didn't previously have a COMPARE in the
         correct mode, we need one.  */
       if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode)
@@ -5754,6 +5837,7 @@ simplify_set (rtx x)
      zero_extend to avoid the reload that would otherwise be required.  */
 
   if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
+      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (src)))
       && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != UNKNOWN
       && SUBREG_BYTE (src) == 0
       && (GET_MODE_SIZE (GET_MODE (src))
@@ -6021,9 +6105,11 @@ expand_compound_operation (rtx x)
       rtx temp2 = expand_compound_operation (temp);
 
       /* Make sure this is a profitable operation.  */
-      if (rtx_cost (x, SET) > rtx_cost (temp2, SET))
+      if (rtx_cost (x, SET, optimize_this_for_speed_p)
+          > rtx_cost (temp2, SET, optimize_this_for_speed_p))
        return temp2;
-      else if (rtx_cost (x, SET) > rtx_cost (temp, SET))
+      else if (rtx_cost (x, SET, optimize_this_for_speed_p)
+               > rtx_cost (temp, SET, optimize_this_for_speed_p))
        return temp;
       else
        return x;
@@ -6130,8 +6216,8 @@ expand_compound_operation (rtx x)
    We half-heartedly support variable positions, but do not at all
    support variable lengths.  */
 
-static rtx
-expand_field_assignment (rtx x)
+static const_rtx
+expand_field_assignment (const_rtx x)
 {
   rtx inner;
   rtx pos;                     /* Always counts from low bit.  */
@@ -6288,7 +6374,7 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   enum machine_mode pos_mode = word_mode;
   enum machine_mode extraction_mode = word_mode;
   enum machine_mode tmode = mode_for_size (len, MODE_INT, 1);
-  rtx new = 0;
+  rtx new_rtx = 0;
   rtx orig_pos_rtx = pos_rtx;
   HOST_WIDE_INT orig_pos;
 
@@ -6312,11 +6398,11 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
         (ashift X (const_int C)), where LEN > C.  Extract the
         least significant (LEN - C) bits of X, giving an rtx
         whose mode is MODE, then shift it left C times.  */
-      new = make_extraction (mode, XEXP (inner, 0),
+      new_rtx = make_extraction (mode, XEXP (inner, 0),
                             0, 0, len - INTVAL (XEXP (inner, 1)),
                             unsignedp, in_dest, in_compare);
-      if (new != 0)
-       return gen_rtx_ASHIFT (mode, new, XEXP (inner, 1));
+      if (new_rtx != 0)
+       return gen_rtx_ASHIFT (mode, new_rtx, XEXP (inner, 1));
     }
 
   inner_mode = GET_MODE (inner);
@@ -6372,7 +6458,7 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
          else
            offset = pos / BITS_PER_UNIT;
 
-         new = adjust_address_nv (inner, tmode, offset);
+         new_rtx = adjust_address_nv (inner, tmode, offset);
        }
       else if (REG_P (inner))
        {
@@ -6402,16 +6488,16 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
                  if (!validate_subreg (tmode, inner_mode, inner, final_word))
                    return NULL_RTX;
 
-                 new = gen_rtx_SUBREG (tmode, inner, final_word);
+                 new_rtx = gen_rtx_SUBREG (tmode, inner, final_word);
                }
              else
-               new = gen_lowpart (tmode, inner);
+               new_rtx = gen_lowpart (tmode, inner);
            }
          else
-           new = inner;
+           new_rtx = inner;
        }
       else
-       new = force_to_mode (inner, tmode,
+       new_rtx = force_to_mode (inner, tmode,
                             len >= HOST_BITS_PER_WIDE_INT
                             ? ~(unsigned HOST_WIDE_INT) 0
                             : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
@@ -6421,34 +6507,35 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
         make a STRICT_LOW_PART unless we made a MEM.  */
 
       if (in_dest)
-       return (MEM_P (new) ? new
-               : (GET_CODE (new) != SUBREG
+       return (MEM_P (new_rtx) ? new_rtx
+               : (GET_CODE (new_rtx) != SUBREG
                   ? gen_rtx_CLOBBER (tmode, const0_rtx)
-                  : gen_rtx_STRICT_LOW_PART (VOIDmode, new)));
+                  : gen_rtx_STRICT_LOW_PART (VOIDmode, new_rtx)));
 
       if (mode == tmode)
-       return new;
+       return new_rtx;
 
-      if (GET_CODE (new) == CONST_INT)
-       return gen_int_mode (INTVAL (new), mode);
+      if (GET_CODE (new_rtx) == CONST_INT)
+       return gen_int_mode (INTVAL (new_rtx), mode);
 
       /* If we know that no extraneous bits are set, and that the high
         bit is not set, convert the extraction to the cheaper of
         sign and zero extension, that are equivalent in these cases.  */
       if (flag_expensive_optimizations
          && (GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
-             && ((nonzero_bits (new, tmode)
+             && ((nonzero_bits (new_rtx, tmode)
                   & ~(((unsigned HOST_WIDE_INT)
                        GET_MODE_MASK (tmode))
                       >> 1))
                  == 0)))
        {
-         rtx temp = gen_rtx_ZERO_EXTEND (mode, new);
-         rtx temp1 = gen_rtx_SIGN_EXTEND (mode, new);
+         rtx temp = gen_rtx_ZERO_EXTEND (mode, new_rtx);
+         rtx temp1 = gen_rtx_SIGN_EXTEND (mode, new_rtx);
 
          /* Prefer ZERO_EXTENSION, since it gives more information to
             backends.  */
-         if (rtx_cost (temp, SET) <= rtx_cost (temp1, SET))
+         if (rtx_cost (temp, SET, optimize_this_for_speed_p)
+             <= rtx_cost (temp1, SET, optimize_this_for_speed_p))
            return temp;
          return temp1;
        }
@@ -6457,7 +6544,7 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
         proper mode.  */
 
       return (gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
-                            mode, new));
+                            mode, new_rtx));
     }
 
   /* Unless this is a COMPARE or we have a funny memory reference,
@@ -6642,7 +6729,8 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
 
          /* Prefer ZERO_EXTENSION, since it gives more information to
             backends.  */
-         if (rtx_cost (temp1, SET) < rtx_cost (temp, SET))
+         if (rtx_cost (temp1, SET, optimize_this_for_speed_p)
+             < rtx_cost (temp, SET, optimize_this_for_speed_p))
            temp = temp1;
        }
       pos_rtx = temp;
@@ -6661,12 +6749,12 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos,
     pos_rtx = GEN_INT (pos);
 
   /* Make the required operation.  See if we can use existing rtx.  */
-  new = gen_rtx_fmt_eee (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT,
+  new_rtx = gen_rtx_fmt_eee (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT,
                         extraction_mode, inner, GEN_INT (len), pos_rtx);
   if (! in_dest)
-    new = gen_lowpart (mode, new);
+    new_rtx = gen_lowpart (mode, new_rtx);
 
-  return new;
+  return new_rtx;
 }
 \f
 /* See if X contains an ASHIFT of COUNT or more bits that can be commuted
@@ -6741,8 +6829,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
   int mode_width = GET_MODE_BITSIZE (mode);
   rtx rhs, lhs;
   enum rtx_code next_code;
-  int i;
-  rtx new = 0;
+  int i, j;
+  rtx new_rtx = 0;
   rtx tem;
   const char *fmt;
 
@@ -6767,8 +6855,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
          && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT
          && INTVAL (XEXP (x, 1)) >= 0)
        {
-         new = make_compound_operation (XEXP (x, 0), next_code);
-         new = gen_rtx_MULT (mode, new,
+         new_rtx = make_compound_operation (XEXP (x, 0), next_code);
+         new_rtx = gen_rtx_MULT (mode, new_rtx,
                              GEN_INT ((HOST_WIDE_INT) 1
                                       << INTVAL (XEXP (x, 1))));
        }
@@ -6785,8 +6873,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
       if (GET_CODE (XEXP (x, 0)) == LSHIFTRT
          && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
        {
-         new = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
-         new = make_extraction (mode, new, 0, XEXP (XEXP (x, 0), 1), i, 1,
+         new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
+         new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1), i, 1,
                                 0, in_code == COMPARE);
        }
 
@@ -6796,9 +6884,9 @@ make_compound_operation (rtx x, enum rtx_code in_code)
               && GET_CODE (SUBREG_REG (XEXP (x, 0))) == LSHIFTRT
               && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
        {
-         new = make_compound_operation (XEXP (SUBREG_REG (XEXP (x, 0)), 0),
+         new_rtx = make_compound_operation (XEXP (SUBREG_REG (XEXP (x, 0)), 0),
                                         next_code);
-         new = make_extraction (GET_MODE (SUBREG_REG (XEXP (x, 0))), new, 0,
+         new_rtx = make_extraction (GET_MODE (SUBREG_REG (XEXP (x, 0))), new_rtx, 0,
                                 XEXP (SUBREG_REG (XEXP (x, 0)), 1), i, 1,
                                 0, in_code == COMPARE);
        }
@@ -6810,12 +6898,12 @@ make_compound_operation (rtx x, enum rtx_code in_code)
               && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
        {
          /* Apply the distributive law, and then try to make extractions.  */
-         new = gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)), mode,
+         new_rtx = gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)), mode,
                                gen_rtx_AND (mode, XEXP (XEXP (x, 0), 0),
                                             XEXP (x, 1)),
                                gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1),
                                             XEXP (x, 1)));
-         new = make_compound_operation (new, in_code);
+         new_rtx = make_compound_operation (new_rtx, in_code);
        }
 
       /* If we are have (and (rotate X C) M) and C is larger than the number
@@ -6826,8 +6914,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
               && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0
               && i <= INTVAL (XEXP (XEXP (x, 0), 1)))
        {
-         new = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
-         new = make_extraction (mode, new,
+         new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
+         new_rtx = make_extraction (mode, new_rtx,
                                 (GET_MODE_BITSIZE (mode)
                                  - INTVAL (XEXP (XEXP (x, 0), 1))),
                                 NULL_RTX, i, 1, 0, in_code == COMPARE);
@@ -6860,7 +6948,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
         If it doesn't end up being a ZERO_EXTEND, we will ignore it unless
         we are in a COMPARE.  */
       else if ((i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
-       new = make_extraction (mode,
+       new_rtx = make_extraction (mode,
                               make_compound_operation (XEXP (x, 0),
                                                        next_code),
                               0, NULL_RTX, i, 1, 0, in_code == COMPARE);
@@ -6869,7 +6957,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
         convert this into the appropriate bit extract.  */
       else if (in_code == COMPARE
               && (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
-       new = make_extraction (mode,
+       new_rtx = make_extraction (mode,
                               make_compound_operation (XEXP (x, 0),
                                                        next_code),
                               i, NULL_RTX, 1, 1, 0, 1);
@@ -6884,7 +6972,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
          && mode_width <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0)
        {
-         new = gen_rtx_ASHIFTRT (mode,
+         new_rtx = gen_rtx_ASHIFTRT (mode,
                                  make_compound_operation (XEXP (x, 0),
                                                           next_code),
                                  XEXP (x, 1));
@@ -6902,10 +6990,11 @@ make_compound_operation (rtx x, enum rtx_code in_code)
       if (GET_CODE (rhs) == CONST_INT
          && GET_CODE (lhs) == ASHIFT
          && GET_CODE (XEXP (lhs, 1)) == CONST_INT
-         && INTVAL (rhs) >= INTVAL (XEXP (lhs, 1)))
+         && INTVAL (rhs) >= INTVAL (XEXP (lhs, 1))
+         && INTVAL (rhs) < mode_width)
        {
-         new = make_compound_operation (XEXP (lhs, 0), next_code);
-         new = make_extraction (mode, new,
+         new_rtx = make_compound_operation (XEXP (lhs, 0), next_code);
+         new_rtx = make_extraction (mode, new_rtx,
                                 INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
                                 NULL_RTX, mode_width - INTVAL (rhs),
                                 code == LSHIFTRT, 0, in_code == COMPARE);
@@ -6922,8 +7011,9 @@ make_compound_operation (rtx x, enum rtx_code in_code)
                && (OBJECT_P (SUBREG_REG (lhs))))
          && GET_CODE (rhs) == CONST_INT
          && INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
-         && (new = extract_left_shift (lhs, INTVAL (rhs))) != 0)
-       new = make_extraction (mode, make_compound_operation (new, next_code),
+         && INTVAL (rhs) < mode_width
+         && (new_rtx = extract_left_shift (lhs, INTVAL (rhs))) != 0)
+       new_rtx = make_extraction (mode, make_compound_operation (new_rtx, next_code),
                               0, NULL_RTX, mode_width - INTVAL (rhs),
                               code == LSHIFTRT, 0, in_code == COMPARE);
 
@@ -6968,9 +7058,9 @@ make_compound_operation (rtx x, enum rtx_code in_code)
       break;
     }
 
-  if (new)
+  if (new_rtx)
     {
-      x = gen_lowpart (mode, new);
+      x = gen_lowpart (mode, new_rtx);
       code = GET_CODE (x);
     }
 
@@ -6979,9 +7069,15 @@ make_compound_operation (rtx x, enum rtx_code in_code)
   for (i = 0; i < GET_RTX_LENGTH (code); i++)
     if (fmt[i] == 'e')
       {
-       new = make_compound_operation (XEXP (x, i), next_code);
-       SUBST (XEXP (x, i), new);
+       new_rtx = make_compound_operation (XEXP (x, i), next_code);
+       SUBST (XEXP (x, i), new_rtx);
       }
+    else if (fmt[i] == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       {
+         new_rtx = make_compound_operation (XVECEXP (x, i, j), next_code);
+         SUBST (XVECEXP (x, i, j), new_rtx);
+       }
 
   /* If this is a commutative operation, the changes to the operands
      may have made it noncanonical.  */
@@ -7221,6 +7317,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
       && (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0)
     return gen_lowpart (mode, x);
 
+  /* The arithmetic simplifications here do the wrong thing on vector modes.  */
+  if (VECTOR_MODE_P (mode) || VECTOR_MODE_P (GET_MODE (x)))
+      return gen_lowpart (mode, x);
+
   switch (code)
     {
     case CLOBBER:
@@ -7291,7 +7391,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
 
              y = simplify_gen_binary (AND, GET_MODE (x),
                                       XEXP (x, 0), GEN_INT (cval));
-             if (rtx_cost (y, SET) < rtx_cost (x, SET))
+             if (rtx_cost (y, SET, optimize_this_for_speed_p)
+                 < rtx_cost (x, SET, optimize_this_for_speed_p))
                x = y;
            }
 
@@ -7989,16 +8090,16 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val)
   else if (code == SUBREG)
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
-      rtx new, r = known_cond (SUBREG_REG (x), cond, reg, val);
+      rtx new_rtx, r = known_cond (SUBREG_REG (x), cond, reg, val);
 
       if (SUBREG_REG (x) != r)
        {
          /* We must simplify subreg here, before we lose track of the
             original inner_mode.  */
-         new = simplify_subreg (GET_MODE (x), r,
+         new_rtx = simplify_subreg (GET_MODE (x), r,
                                 inner_mode, SUBREG_BYTE (x));
-         if (new)
-           return new;
+         if (new_rtx)
+           return new_rtx;
          else
            SUBST (SUBREG_REG (x), r);
        }
@@ -8014,16 +8115,16 @@ known_cond (rtx x, enum rtx_code cond, rtx reg, rtx val)
   else if (code == ZERO_EXTEND)
     {
       enum machine_mode inner_mode = GET_MODE (XEXP (x, 0));
-      rtx new, r = known_cond (XEXP (x, 0), cond, reg, val);
+      rtx new_rtx, r = known_cond (XEXP (x, 0), cond, reg, val);
 
       if (XEXP (x, 0) != r)
        {
          /* We must simplify the zero_extend here, before we lose
             track of the original inner_mode.  */
-         new = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+         new_rtx = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
                                          r, inner_mode);
-         if (new)
-           return new;
+         if (new_rtx)
+           return new_rtx;
          else
            SUBST (XEXP (x, 0), r);
        }
@@ -8435,7 +8536,8 @@ distribute_and_simplify_rtx (rtx x, int n)
   tmp = apply_distributive_law (simplify_gen_binary (inner_code, mode,
                                                     new_op0, new_op1));
   if (GET_CODE (tmp) != outer_code
-      && rtx_cost (tmp, SET) < rtx_cost (x, SET))
+      && rtx_cost (tmp, SET, optimize_this_for_speed_p)
+         < rtx_cost (x, SET, optimize_this_for_speed_p))
     return tmp;
 
   return NULL_RTX;
@@ -8583,33 +8685,35 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
    a shift, AND, or zero_extract, we can do better.  */
 
 static rtx
-reg_nonzero_bits_for_combine (rtx x, enum machine_mode mode,
-                             rtx known_x ATTRIBUTE_UNUSED,
+reg_nonzero_bits_for_combine (const_rtx x, enum machine_mode mode,
+                             const_rtx known_x ATTRIBUTE_UNUSED,
                              enum machine_mode known_mode ATTRIBUTE_UNUSED,
                              unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
                              unsigned HOST_WIDE_INT *nonzero)
 {
   rtx tem;
+  reg_stat_type *rsp;
 
   /* If X is a register whose nonzero bits value is current, use it.
      Otherwise, if X is a register whose value we can find, use that
      value.  Otherwise, use the previously-computed global nonzero bits
      for this register.  */
 
-  if (reg_stat[REGNO (x)].last_set_value != 0
-      && (reg_stat[REGNO (x)].last_set_mode == mode
-         || (GET_MODE_CLASS (reg_stat[REGNO (x)].last_set_mode) == MODE_INT
+  rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
+  if (rsp->last_set_value != 0
+      && (rsp->last_set_mode == mode
+         || (GET_MODE_CLASS (rsp->last_set_mode) == MODE_INT
              && GET_MODE_CLASS (mode) == MODE_INT))
-      && ((reg_stat[REGNO (x)].last_set_label >= label_tick_ebb_start
-          && reg_stat[REGNO (x)].last_set_label < label_tick)
-         || (reg_stat[REGNO (x)].last_set_label == label_tick
-              && DF_INSN_LUID (reg_stat[REGNO (x)].last_set) < subst_low_luid)
+      && ((rsp->last_set_label >= label_tick_ebb_start
+          && rsp->last_set_label < label_tick)
+         || (rsp->last_set_label == label_tick
+              && DF_INSN_LUID (rsp->last_set) < subst_low_luid)
          || (REGNO (x) >= FIRST_PSEUDO_REGISTER
              && REG_N_SETS (REGNO (x)) == 1
              && !REGNO_REG_SET_P
                  (DF_LR_IN (ENTRY_BLOCK_PTR->next_bb), REGNO (x)))))
     {
-      *nonzero &= reg_stat[REGNO (x)].last_set_nonzero_bits;
+      *nonzero &= rsp->last_set_nonzero_bits;
       return NULL;
     }
 
@@ -8639,9 +8743,9 @@ reg_nonzero_bits_for_combine (rtx x, enum machine_mode mode,
 #endif
       return tem;
     }
-  else if (nonzero_sign_valid && reg_stat[REGNO (x)].nonzero_bits)
+  else if (nonzero_sign_valid && rsp->nonzero_bits)
     {
-      unsigned HOST_WIDE_INT mask = reg_stat[REGNO (x)].nonzero_bits;
+      unsigned HOST_WIDE_INT mask = rsp->nonzero_bits;
 
       if (GET_MODE_BITSIZE (GET_MODE (x)) < GET_MODE_BITSIZE (mode))
        /* We don't know anything about the upper bits.  */
@@ -8658,27 +8762,29 @@ reg_nonzero_bits_for_combine (rtx x, enum machine_mode mode,
    be between 1 and the number of bits in MODE.  */
 
 static rtx
-reg_num_sign_bit_copies_for_combine (rtx x, enum machine_mode mode,
-                                    rtx known_x ATTRIBUTE_UNUSED,
+reg_num_sign_bit_copies_for_combine (const_rtx x, enum machine_mode mode,
+                                    const_rtx known_x ATTRIBUTE_UNUSED,
                                     enum machine_mode known_mode
                                     ATTRIBUTE_UNUSED,
                                     unsigned int known_ret ATTRIBUTE_UNUSED,
                                     unsigned int *result)
 {
   rtx tem;
-
-  if (reg_stat[REGNO (x)].last_set_value != 0
-      && reg_stat[REGNO (x)].last_set_mode == mode
-      && ((reg_stat[REGNO (x)].last_set_label >= label_tick_ebb_start
-          && reg_stat[REGNO (x)].last_set_label < label_tick)
-         || (reg_stat[REGNO (x)].last_set_label == label_tick
-              && DF_INSN_LUID (reg_stat[REGNO (x)].last_set) < subst_low_luid)
+  reg_stat_type *rsp;
+
+  rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
+  if (rsp->last_set_value != 0
+      && rsp->last_set_mode == mode
+      && ((rsp->last_set_label >= label_tick_ebb_start
+          && rsp->last_set_label < label_tick)
+         || (rsp->last_set_label == label_tick
+              && DF_INSN_LUID (rsp->last_set) < subst_low_luid)
          || (REGNO (x) >= FIRST_PSEUDO_REGISTER
              && REG_N_SETS (REGNO (x)) == 1
              && !REGNO_REG_SET_P
                  (DF_LR_IN (ENTRY_BLOCK_PTR->next_bb), REGNO (x)))))
     {
-      *result = reg_stat[REGNO (x)].last_set_sign_bit_copies;
+      *result = rsp->last_set_sign_bit_copies;
       return NULL;
     }
 
@@ -8686,9 +8792,9 @@ reg_num_sign_bit_copies_for_combine (rtx x, enum machine_mode mode,
   if (tem != 0)
     return tem;
 
-  if (nonzero_sign_valid && reg_stat[REGNO (x)].sign_bit_copies != 0
+  if (nonzero_sign_valid && rsp->sign_bit_copies != 0
       && GET_MODE_BITSIZE (GET_MODE (x)) == GET_MODE_BITSIZE (mode))
-    *result = reg_stat[REGNO (x)].sign_bit_copies;
+    *result = rsp->sign_bit_copies;
 
   return NULL;
 }
@@ -8705,7 +8811,7 @@ reg_num_sign_bit_copies_for_combine (rtx x, enum machine_mode mode,
    implies that it must be called from a define_split.  */
 
 unsigned int
-extended_count (rtx x, enum machine_mode mode, int unsignedp)
+extended_count (const_rtx x, enum machine_mode mode, int unsignedp)
 {
   if (nonzero_sign_valid == 0)
     return 0;
@@ -8838,13 +8944,13 @@ merge_outer_ops (enum rtx_code *pop0, HOST_WIDE_INT *pconst0, enum rtx_code op1,
           && op0 == AND)
     op0 = UNKNOWN;
 
+  *pop0 = op0;
+
   /* ??? Slightly redundant with the above mask, but not entirely.
      Moving this above means we'd have to sign-extend the mode mask
      for the final test.  */
-  const0 = trunc_int_for_mode (const0, mode);
-
-  *pop0 = op0;
-  *pconst0 = const0;
+  if (op0 != UNKNOWN && op0 != NEG)
+    *pconst0 = trunc_int_for_mode (const0, mode);
 
   return 1;
 }
@@ -8872,7 +8978,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
   enum rtx_code outer_op = UNKNOWN;
   HOST_WIDE_INT outer_const = 0;
   int complement_p = 0;
-  rtx new, x;
+  rtx new_rtx, x;
 
   /* Make sure and truncate the "natural" shift on the way in.  We don't
      want to do this inside the loop as it makes it more difficult to
@@ -8897,11 +9003,6 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
       if (GET_CODE (varop) == CLOBBER)
        return NULL_RTX;
 
-      /* If we discovered we had to complement VAROP, leave.  Making a NOT
-        here would cause an infinite loop.  */
-      if (complement_p)
-       break;
-
       /* Convert ROTATERT to ROTATE.  */
       if (code == ROTATERT)
        {
@@ -8947,6 +9048,11 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
            }
        }
 
+      /* If we discovered we had to complement VAROP, leave.  Making a NOT
+        here would cause an infinite loop.  */
+      if (complement_p)
+       break;
+
       /* An arithmetic right shift of a quantity known to be -1 or 0
         is a no-op.  */
       if (code == ASHIFTRT
@@ -8994,10 +9100,10 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
        case ZERO_EXTEND:
        case SIGN_EXTRACT:
        case ZERO_EXTRACT:
-         new = expand_compound_operation (varop);
-         if (new != varop)
+         new_rtx = expand_compound_operation (varop);
+         if (new_rtx != varop)
            {
-             varop = new;
+             varop = new_rtx;
              continue;
            }
          break;
@@ -9012,12 +9118,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
              && (tmode = mode_for_size (GET_MODE_BITSIZE (mode) - count,
                                         MODE_INT, 1)) != BLKmode)
            {
-             new = adjust_address_nv (varop, tmode,
+             new_rtx = adjust_address_nv (varop, tmode,
                                       BYTES_BIG_ENDIAN ? 0
                                       : count / BITS_PER_UNIT);
 
              varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
-                                    : ZERO_EXTEND, mode, new);
+                                    : ZERO_EXTEND, mode, new_rtx);
              count = 0;
              continue;
            }
@@ -9238,16 +9344,19 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
                   && GET_CODE (XEXP (varop, 0)) == CONST_INT
                   && GET_CODE (XEXP (varop, 1)) != CONST_INT)
            {
-             rtx new = simplify_const_binary_operation (code, mode,
+             rtx new_rtx = simplify_const_binary_operation (code, mode,
                                                         XEXP (varop, 0),
                                                         GEN_INT (count));
-             varop = gen_rtx_fmt_ee (code, mode, new, XEXP (varop, 1));
+             varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1));
              count = 0;
              continue;
            }
          break;
 
        case NOT:
+         if (VECTOR_MODE_P (mode))
+           break;
+
          /* Make this fit the case below.  */
          varop = gen_rtx_XOR (mode, XEXP (varop, 0),
                               GEN_INT (GET_MODE_MASK (mode)));
@@ -9292,12 +9401,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
              && !(code == ASHIFTRT && GET_CODE (varop) == XOR
                   && 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
                                              shift_mode))
-             && (new = simplify_const_binary_operation (code, result_mode,
+             && (new_rtx = simplify_const_binary_operation (code, result_mode,
                                                         XEXP (varop, 1),
                                                         GEN_INT (count))) != 0
-             && GET_CODE (new) == CONST_INT
+             && GET_CODE (new_rtx) == CONST_INT
              && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop),
-                                 INTVAL (new), result_mode, &complement_p))
+                                 INTVAL (new_rtx), result_mode, &complement_p))
            {
              varop = XEXP (varop, 0);
              continue;
@@ -9420,12 +9529,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
          /* (ashift (plus foo C) N) is (plus (ashift foo N) C').  */
          if (code == ASHIFT
              && GET_CODE (XEXP (varop, 1)) == CONST_INT
-             && (new = simplify_const_binary_operation (ASHIFT, result_mode,
+             && (new_rtx = simplify_const_binary_operation (ASHIFT, result_mode,
                                                         XEXP (varop, 1),
                                                         GEN_INT (count))) != 0
-             && GET_CODE (new) == CONST_INT
+             && GET_CODE (new_rtx) == CONST_INT
              && merge_outer_ops (&outer_op, &outer_const, PLUS,
-                                 INTVAL (new), result_mode, &complement_p))
+                                 INTVAL (new_rtx), result_mode, &complement_p))
            {
              varop = XEXP (varop, 0);
              continue;
@@ -9439,12 +9548,12 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
          if (code == LSHIFTRT
              && GET_CODE (XEXP (varop, 1)) == CONST_INT
              && mode_signbit_p (result_mode, XEXP (varop, 1))
-             && (new = simplify_const_binary_operation (code, result_mode,
+             && (new_rtx = simplify_const_binary_operation (code, result_mode,
                                                         XEXP (varop, 1),
                                                         GEN_INT (count))) != 0
-             && GET_CODE (new) == CONST_INT
+             && GET_CODE (new_rtx) == CONST_INT
              && merge_outer_ops (&outer_op, &outer_const, XOR,
-                                 INTVAL (new), result_mode, &complement_p))
+                                 INTVAL (new_rtx), result_mode, &complement_p))
            {
              varop = XEXP (varop, 0);
              continue;
@@ -9564,7 +9673,8 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
 
   if (outer_op != UNKNOWN)
     {
-      if (GET_MODE_BITSIZE (result_mode) < HOST_BITS_PER_WIDE_INT)
+      if (GET_RTX_CLASS (outer_op) != RTX_UNARY
+         && GET_MODE_BITSIZE (result_mode) < HOST_BITS_PER_WIDE_INT)
        outer_const = trunc_int_for_mode (outer_const, result_mode);
 
       if (outer_op == AND)
@@ -9649,6 +9759,14 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pnotes)
   REG_NOTES (insn) = 0;
 
   insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      if (insn_code_number < 0)
+       fputs ("Failed to match this instruction:\n", dump_file);
+      else
+       fputs ("Successfully matched this instruction:\n", dump_file);
+      print_rtl_single (dump_file, pat);
+    }
 
   /* If it isn't, there is the possibility that we previously had an insn
      that clobbered some register as a side effect, but the combined
@@ -9675,6 +9793,14 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pnotes)
 
       PATTERN (insn) = pat;
       insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         if (insn_code_number < 0)
+           fputs ("Failed to match this instruction:\n", dump_file);
+         else
+           fputs ("Successfully matched this instruction:\n", dump_file);
+         print_rtl_single (dump_file, pat);
+       }
     }
   PATTERN (insn) = old_pat;
   REG_NOTES (insn) = old_notes;
@@ -9710,8 +9836,8 @@ recog_for_combine (rtx *pnewpat, rtx insn, rtx *pnotes)
          if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) != SCRATCH) 
            {
              gcc_assert (REG_P (XEXP (XVECEXP (newpat, 0, i), 0)));
-             notes = gen_rtx_EXPR_LIST (REG_UNUSED,
-                                        XEXP (XVECEXP (newpat, 0, i), 0), notes);
+             notes = alloc_reg_note (REG_UNUSED,
+                                     XEXP (XVECEXP (newpat, 0, i), 0), notes);
            }
        }
       pat = newpat;
@@ -9836,7 +9962,7 @@ gen_lowpart_for_combine (enum machine_mode omode, rtx x)
     }
 
  fail:
-  return gen_rtx_CLOBBER (imode, const0_rtx);
+  return gen_rtx_CLOBBER (omode, const0_rtx);
 }
 \f
 /* Simplify a comparison between *POP0 and *POP1 where CODE is the
@@ -10382,7 +10508,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
              && ((unsigned HOST_WIDE_INT) const_op
                  < (((unsigned HOST_WIDE_INT) 1
                      << (GET_MODE_BITSIZE (mode) - 1))))
-             && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+             && have_insn_for (COMPARE, mode))
            {
              op0 = XEXP (op0, 0);
              continue;
@@ -10463,7 +10589,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
              && (unsigned_comparison_p || equality_comparison_p)
              && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
              && ((unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode))
-             && cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+             && have_insn_for (COMPARE, mode))
            {
              op0 = XEXP (op0, 0);
              continue;
@@ -11072,7 +11198,7 @@ count_rtxs (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;
-  int i, ret = 1;
+  int i, j, ret = 1;
 
   if (GET_RTX_CLASS (code) == '2'
       || GET_RTX_CLASS (code) == 'c')
@@ -11102,6 +11228,9 @@ count_rtxs (rtx x)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
       ret += count_rtxs (XEXP (x, i));
+    else if (fmt[i] == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       ret += count_rtxs (XVECEXP (x, i, j));
 
   return ret;
 }
@@ -11115,7 +11244,7 @@ update_table_tick (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt = GET_RTX_FORMAT (code);
-  int i;
+  int i, j;
 
   if (code == REG)
     {
@@ -11124,14 +11253,15 @@ update_table_tick (rtx x)
       unsigned int r;
 
       for (r = regno; r < endregno; r++)
-       reg_stat[r].last_set_table_tick = label_tick;
+       {
+         reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, r);
+         rsp->last_set_table_tick = label_tick;
+       }
 
       return;
     }
 
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    /* Note that we can't have an "E" in values stored; see
-       get_last_value_validate.  */
     if (fmt[i] == 'e')
       {
        /* Check for identical subexpressions.  If x contains
@@ -11168,6 +11298,9 @@ update_table_tick (rtx x)
 
        update_table_tick (XEXP (x, i));
       }
+    else if (fmt[i] == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       update_table_tick (XVECEXP (x, i, j));
 }
 
 /* Record that REG is set to VALUE in insn INSN.  If VALUE is zero, we
@@ -11182,6 +11315,7 @@ record_value_for_reg (rtx reg, rtx insn, rtx value)
   unsigned int regno = REGNO (reg);
   unsigned int endregno = END_REGNO (reg);
   unsigned int i;
+  reg_stat_type *rsp;
 
   /* If VALUE contains REG and we have a previous value for REG, substitute
      the previous value.  */
@@ -11222,15 +11356,17 @@ record_value_for_reg (rtx reg, rtx insn, rtx value)
      register.  */
   for (i = regno; i < endregno; i++)
     {
+      rsp = VEC_index (reg_stat_type, reg_stat, i);
+
       if (insn)
-       reg_stat[i].last_set = insn;
+       rsp->last_set = insn;
 
-      reg_stat[i].last_set_value = 0;
-      reg_stat[i].last_set_mode = 0;
-      reg_stat[i].last_set_nonzero_bits = 0;
-      reg_stat[i].last_set_sign_bit_copies = 0;
-      reg_stat[i].last_death = 0;
-      reg_stat[i].truncated_to_mode = 0;
+      rsp->last_set_value = 0;
+      rsp->last_set_mode = VOIDmode;
+      rsp->last_set_nonzero_bits = 0;
+      rsp->last_set_sign_bit_copies = 0;
+      rsp->last_death = 0;
+      rsp->truncated_to_mode = VOIDmode;
     }
 
   /* Mark registers that are being referenced in this value.  */
@@ -11246,41 +11382,43 @@ record_value_for_reg (rtx reg, rtx insn, rtx value)
 
   for (i = regno; i < endregno; i++)
     {
-      reg_stat[i].last_set_label = label_tick;
+      rsp = VEC_index (reg_stat_type, reg_stat, i);
+      rsp->last_set_label = label_tick;
       if (!insn
-         || (value && reg_stat[i].last_set_table_tick >= label_tick_ebb_start))
-       reg_stat[i].last_set_invalid = 1;
+         || (value && rsp->last_set_table_tick >= label_tick_ebb_start))
+       rsp->last_set_invalid = 1;
       else
-       reg_stat[i].last_set_invalid = 0;
+       rsp->last_set_invalid = 0;
     }
 
   /* The value being assigned might refer to X (like in "x++;").  In that
      case, we must replace it with (clobber (const_int 0)) to prevent
      infinite loops.  */
+  rsp = VEC_index (reg_stat_type, reg_stat, regno);
   if (value && ! get_last_value_validate (&value, insn,
-                                         reg_stat[regno].last_set_label, 0))
+                                         rsp->last_set_label, 0))
     {
       value = copy_rtx (value);
       if (! get_last_value_validate (&value, insn,
-                                    reg_stat[regno].last_set_label, 1))
+                                    rsp->last_set_label, 1))
        value = 0;
     }
 
   /* For the main register being modified, update the value, the mode, the
      nonzero bits, and the number of sign bit copies.  */
 
-  reg_stat[regno].last_set_value = value;
+  rsp->last_set_value = value;
 
   if (value)
     {
       enum machine_mode mode = GET_MODE (reg);
       subst_low_luid = DF_INSN_LUID (insn);
-      reg_stat[regno].last_set_mode = mode;
+      rsp->last_set_mode = mode;
       if (GET_MODE_CLASS (mode) == MODE_INT
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
        mode = nonzero_bits_mode;
-      reg_stat[regno].last_set_nonzero_bits = nonzero_bits (value, mode);
-      reg_stat[regno].last_set_sign_bit_copies
+      rsp->last_set_nonzero_bits = nonzero_bits (value, mode);
+      rsp->last_set_sign_bit_copies
        = num_sign_bit_copies (value, GET_MODE (reg));
     }
 }
@@ -11290,7 +11428,7 @@ record_value_for_reg (rtx reg, rtx insn, rtx value)
    set is occurring.  */
 
 static void
-record_dead_and_set_regs_1 (rtx dest, rtx setter, void *data)
+record_dead_and_set_regs_1 (rtx dest, const_rtx setter, void *data)
 {
   rtx record_dead_insn = (rtx) data;
 
@@ -11353,7 +11491,12 @@ record_dead_and_set_regs (rtx insn)
          unsigned int endregno = END_REGNO (XEXP (link, 0));
 
          for (i = regno; i < endregno; i++)
-           reg_stat[i].last_death = insn;
+           {
+             reg_stat_type *rsp;
+
+             rsp = VEC_index (reg_stat_type, reg_stat, i);
+             rsp->last_death = insn;
+           }
        }
       else if (REG_NOTE_KIND (link) == REG_INC)
        record_value_for_reg (XEXP (link, 0), insn, NULL_RTX);
@@ -11364,14 +11507,17 @@ record_dead_and_set_regs (rtx insn)
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
          {
-           reg_stat[i].last_set_invalid = 1;
-           reg_stat[i].last_set = insn;
-           reg_stat[i].last_set_value = 0;
-           reg_stat[i].last_set_mode = 0;
-           reg_stat[i].last_set_nonzero_bits = 0;
-           reg_stat[i].last_set_sign_bit_copies = 0;
-           reg_stat[i].last_death = 0;
-           reg_stat[i].truncated_to_mode = 0;
+           reg_stat_type *rsp;
+
+           rsp = VEC_index (reg_stat_type, reg_stat, i);
+           rsp->last_set_invalid = 1;
+           rsp->last_set = insn;
+           rsp->last_set_value = 0;
+           rsp->last_set_mode = VOIDmode;
+           rsp->last_set_nonzero_bits = 0;
+           rsp->last_set_sign_bit_copies = 0;
+           rsp->last_death = 0;
+           rsp->truncated_to_mode = VOIDmode;
          }
 
       last_call_luid = mem_last_set = DF_INSN_LUID (insn);
@@ -11407,6 +11553,8 @@ record_promoted_value (rtx insn, rtx subreg)
 
   for (links = LOG_LINKS (insn); links;)
     {
+      reg_stat_type *rsp;
+
       insn = XEXP (links, 0);
       set = single_set (insn);
 
@@ -11418,10 +11566,11 @@ record_promoted_value (rtx insn, rtx subreg)
          continue;
        }
 
-      if (reg_stat[regno].last_set == insn)
+      rsp = VEC_index (reg_stat_type, reg_stat, regno);
+      if (rsp->last_set == insn)
        {
          if (SUBREG_PROMOTED_UNSIGNED_P (subreg) > 0)
-           reg_stat[regno].last_set_nonzero_bits &= GET_MODE_MASK (mode);
+           rsp->last_set_nonzero_bits &= GET_MODE_MASK (mode);
        }
 
       if (REG_P (SET_SRC (set)))
@@ -11440,12 +11589,13 @@ record_promoted_value (rtx insn, rtx subreg)
    an explicit truncation.  */
 
 static bool
-reg_truncated_to_mode (enum machine_mode mode, rtx x)
+reg_truncated_to_mode (enum machine_mode mode, const_rtx x)
 {
-  enum machine_mode truncated = reg_stat[REGNO (x)].truncated_to_mode;
+  reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
+  enum machine_mode truncated = rsp->truncated_to_mode;
 
   if (truncated == 0
-      || reg_stat[REGNO (x)].truncation_label < label_tick_ebb_start)
+      || rsp->truncation_label < label_tick_ebb_start)
     return false;
   if (GET_MODE_SIZE (truncated) <= GET_MODE_SIZE (mode))
     return true;
@@ -11455,14 +11605,17 @@ reg_truncated_to_mode (enum machine_mode mode, rtx x)
   return false;
 }
 
-/* X is a REG or a SUBREG.  If X is some sort of a truncation record
-   it.  For non-TRULY_NOOP_TRUNCATION targets we might be able to turn
-   a truncate into a subreg using this information.  */
+/* Callback for for_each_rtx.  If *P is a hard reg or a subreg record the mode
+   that the register is accessed in.  For non-TRULY_NOOP_TRUNCATION targets we
+   might be able to turn a truncate into a subreg using this information.
+   Return -1 if traversing *P is complete or 0 otherwise.  */
 
-static void
-record_truncated_value (rtx x)
+static int
+record_truncated_value (rtx *p, void *data ATTRIBUTE_UNUSED)
 {
+  rtx x = *p;
   enum machine_mode truncated_mode;
+  reg_stat_type *rsp;
 
   if (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)))
     {
@@ -11470,11 +11623,11 @@ record_truncated_value (rtx x)
       truncated_mode = GET_MODE (x);
 
       if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
-       return;
+       return -1;
 
       if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (truncated_mode),
                                 GET_MODE_BITSIZE (original_mode)))
-       return;
+       return -1;
 
       x = SUBREG_REG (x);
     }
@@ -11483,33 +11636,41 @@ record_truncated_value (rtx x)
   else if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
     truncated_mode = GET_MODE (x);
   else
-    return;
+    return 0;
 
-  if (reg_stat[REGNO (x)].truncated_to_mode == 0
-      || reg_stat[REGNO (x)].truncation_label < label_tick_ebb_start
+  rsp = VEC_index (reg_stat_type, reg_stat, REGNO (x));
+  if (rsp->truncated_to_mode == 0
+      || rsp->truncation_label < label_tick_ebb_start
       || (GET_MODE_SIZE (truncated_mode)
-         < GET_MODE_SIZE (reg_stat[REGNO (x)].truncated_to_mode)))
+         < GET_MODE_SIZE (rsp->truncated_to_mode)))
     {
-      reg_stat[REGNO (x)].truncated_to_mode = truncated_mode;
-      reg_stat[REGNO (x)].truncation_label = label_tick;
+      rsp->truncated_to_mode = truncated_mode;
+      rsp->truncation_label = label_tick;
     }
+
+  return -1;
 }
 
-/* Scan X for promoted SUBREGs and truncated REGs.  For each one
-   found, note what it implies to the registers used in it.  */
+/* Callback for note_uses.  Find hardregs and subregs of pseudos and
+   the modes they are used in.  This can help truning TRUNCATEs into
+   SUBREGs.  */
 
 static void
-check_conversions (rtx insn, rtx x)
+record_truncated_values (rtx *x, void *data ATTRIBUTE_UNUSED)
 {
-  if (GET_CODE (x) == SUBREG || REG_P (x))
-    {
-      if (GET_CODE (x) == SUBREG
-         && SUBREG_PROMOTED_VAR_P (x)
-         && REG_P (SUBREG_REG (x)))
-       record_promoted_value (insn, x);
+  for_each_rtx (x, record_truncated_value, NULL);
+}
 
-      record_truncated_value (x);
-    }
+/* Scan X for promoted SUBREGs.  For each one found,
+   note what it implies to the registers used in it.  */
+
+static void
+check_promoted_subreg (rtx insn, rtx x)
+{
+  if (GET_CODE (x) == SUBREG
+      && SUBREG_PROMOTED_VAR_P (x)
+      && REG_P (SUBREG_REG (x)))
+    record_promoted_value (insn, x);
   else
     {
       const char *format = GET_RTX_FORMAT (GET_CODE (x));
@@ -11519,13 +11680,13 @@ check_conversions (rtx insn, rtx x)
        switch (format[i])
          {
          case 'e':
-           check_conversions (insn, XEXP (x, i));
+           check_promoted_subreg (insn, XEXP (x, i));
            break;
          case 'V':
          case 'E':
            if (XVEC (x, i) != 0)
              for (j = 0; j < XVECLEN (x, i); j++)
-               check_conversions (insn, XVECEXP (x, i, j));
+               check_promoted_subreg (insn, XVECEXP (x, i, j));
            break;
          }
     }
@@ -11547,7 +11708,7 @@ get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
   rtx x = *loc;
   const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
   int len = GET_RTX_LENGTH (GET_CODE (x));
-  int i;
+  int i, j;
 
   if (REG_P (x))
     {
@@ -11556,19 +11717,22 @@ get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
       unsigned int j;
 
       for (j = regno; j < endregno; j++)
-       if (reg_stat[j].last_set_invalid
-           /* If this is a pseudo-register that was only set once and not
-              live at the beginning of the function, it is always valid.  */
-           || (! (regno >= FIRST_PSEUDO_REGISTER
-                  && REG_N_SETS (regno) == 1
-                  && !REGNO_REG_SET_P
-                      (DF_LR_IN (ENTRY_BLOCK_PTR->next_bb), regno))
-               && reg_stat[j].last_set_label > tick))
+       {
+         reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, j);
+         if (rsp->last_set_invalid
+             /* If this is a pseudo-register that was only set once and not
+                live at the beginning of the function, it is always valid.  */
+             || (! (regno >= FIRST_PSEUDO_REGISTER
+                    && REG_N_SETS (regno) == 1
+                    && (!REGNO_REG_SET_P
+                        (DF_LR_IN (ENTRY_BLOCK_PTR->next_bb), regno)))
+                 && rsp->last_set_label > tick))
          {
            if (replace)
              *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
            return replace;
          }
+       }
 
       return 1;
     }
@@ -11622,9 +11786,11 @@ get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
                                       replace) == 0)
            return 0;
        }
-      /* Don't bother with these.  They shouldn't occur anyway.  */
       else if (fmt[i] == 'E')
-       return 0;
+       for (j = 0; j < XVECLEN (x, i); j++)
+         if (get_last_value_validate (&XVECEXP (x, i, j),
+                                      insn, tick, replace) == 0)
+           return 0;
     }
 
   /* If we haven't found a reason for it to be invalid, it is valid.  */
@@ -11636,10 +11802,11 @@ get_last_value_validate (rtx *loc, rtx insn, int tick, int replace)
    is known longer known reliably.  */
 
 static rtx
-get_last_value (rtx x)
+get_last_value (const_rtx x)
 {
   unsigned int regno;
   rtx value;
+  reg_stat_type *rsp;
 
   /* If this is a non-paradoxical SUBREG, get the value of its operand and
      then convert it to the desired mode.  If this is a paradoxical SUBREG,
@@ -11655,7 +11822,8 @@ get_last_value (rtx x)
     return 0;
 
   regno = REGNO (x);
-  value = reg_stat[regno].last_set_value;
+  rsp = VEC_index (reg_stat_type, reg_stat, regno);
+  value = rsp->last_set_value;
 
   /* If we don't have a value, or if it isn't for this basic block and
      it's either a hard register, set more than once, or it's a live
@@ -11668,7 +11836,7 @@ get_last_value (rtx x)
      block.  */
 
   if (value == 0
-      || (reg_stat[regno].last_set_label < label_tick_ebb_start
+      || (rsp->last_set_label < label_tick_ebb_start
          && (regno < FIRST_PSEUDO_REGISTER
              || REG_N_SETS (regno) != 1
              || REGNO_REG_SET_P
@@ -11677,21 +11845,21 @@ get_last_value (rtx x)
 
   /* If the value was set in a later insn than the ones we are processing,
      we can't use it even if the register was only set once.  */
-  if (reg_stat[regno].last_set_label == label_tick
-      && DF_INSN_LUID (reg_stat[regno].last_set) >= subst_low_luid)
+  if (rsp->last_set_label == label_tick
+      && DF_INSN_LUID (rsp->last_set) >= subst_low_luid)
     return 0;
 
   /* If the value has all its registers valid, return it.  */
-  if (get_last_value_validate (&value, reg_stat[regno].last_set,
-                              reg_stat[regno].last_set_label, 0))
+  if (get_last_value_validate (&value, rsp->last_set,
+                              rsp->last_set_label, 0))
     return value;
 
   /* Otherwise, make a copy and replace any invalid register with
      (clobber (const_int 0)).  If that fails for some reason, return 0.  */
 
   value = copy_rtx (value);
-  if (get_last_value_validate (&value, reg_stat[regno].last_set,
-                              reg_stat[regno].last_set_label, 1))
+  if (get_last_value_validate (&value, rsp->last_set,
+                              rsp->last_set_label, 1))
     return value;
 
   return 0;
@@ -11701,7 +11869,7 @@ get_last_value (rtx x)
    that is set in an instruction more recent than FROM_LUID.  */
 
 static int
-use_crosses_set_p (rtx x, int from_luid)
+use_crosses_set_p (const_rtx x, int from_luid)
 {
   const char *fmt;
   int i;
@@ -11719,10 +11887,13 @@ use_crosses_set_p (rtx x, int from_luid)
        return 1;
 #endif
       for (; regno < endreg; regno++)
-       if (reg_stat[regno].last_set
-           && reg_stat[regno].last_set_label == label_tick
-           && DF_INSN_LUID (reg_stat[regno].last_set) > from_luid)
-         return 1;
+       {
+         reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, regno);
+         if (rsp->last_set
+             && rsp->last_set_label == label_tick
+             && DF_INSN_LUID (rsp->last_set) > from_luid)
+           return 1;
+       }
       return 0;
     }
 
@@ -11759,7 +11930,7 @@ static int reg_dead_flag;
    reg_dead_flag to 1 if X is a CLOBBER and to -1 it is a SET.  */
 
 static void
-reg_dead_at_p_1 (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
+reg_dead_at_p_1 (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int regno, endregno;
 
@@ -11802,34 +11973,30 @@ reg_dead_at_p (rtx reg, rtx insn)
          return 0;
     }
 
-  /* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, label, or
-     beginning of function.  */
-  for (; insn && !LABEL_P (insn) && !BARRIER_P (insn);
-       insn = prev_nonnote_insn (insn))
+  /* Scan backwards until we find a REG_DEAD note, SET, CLOBBER, or
+     beginning of basic block.  */
+  block = BLOCK_FOR_INSN (insn);
+  for (;;)
     {
-      note_stores (PATTERN (insn), reg_dead_at_p_1, NULL);
-      if (reg_dead_flag)
-       return reg_dead_flag == 1 ? 1 : 0;
+      if (INSN_P (insn))
+        {
+         note_stores (PATTERN (insn), reg_dead_at_p_1, NULL);
+         if (reg_dead_flag)
+           return reg_dead_flag == 1 ? 1 : 0;
 
-      if (find_regno_note (insn, REG_DEAD, reg_dead_regno))
-       return 1;
-    }
+         if (find_regno_note (insn, REG_DEAD, reg_dead_regno))
+           return 1;
+        }
 
-  /* Get the basic block that we were in.  */
-  if (insn == 0)
-    block = ENTRY_BLOCK_PTR->next_bb;
-  else
-    {
-      FOR_EACH_BB (block)
-       if (insn == BB_HEAD (block))
-         break;
+      if (insn == BB_HEAD (block))
+       break;
 
-      if (block == EXIT_BLOCK_PTR)
-       return 0;
+      insn = PREV_INSN (insn);
     }
 
+  /* Look at live-in sets for the basic block that we were in.  */
   for (i = reg_dead_regno; i < reg_dead_endregno; i++)
-    if (REGNO_REG_SET_P (DF_LIVE_IN (block), i))
+    if (REGNO_REG_SET_P (df_get_live_in (block), i))
       return 0;
 
   return 1;
@@ -11969,7 +12136,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
   if (code == REG)
     {
       unsigned int regno = REGNO (x);
-      rtx where_dead = reg_stat[regno].last_death;
+      rtx where_dead = VEC_index (reg_stat_type, reg_stat, regno)->last_death;
 
       /* Don't move the register if it gets killed in between from and to.  */
       if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn)
@@ -11977,6 +12144,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
        return;
 
       if (where_dead
+         && BLOCK_FOR_INSN (where_dead) == BLOCK_FOR_INSN (to_insn)
          && DF_INSN_LUID (where_dead) >= from_luid
          && DF_INSN_LUID (where_dead) < DF_INSN_LUID (to_insn))
        {
@@ -12002,10 +12170,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
 
              for (i = deadregno; i < deadend; i++)
                if (i < regno || i >= ourend)
-                 REG_NOTES (where_dead)
-                   = gen_rtx_EXPR_LIST (REG_DEAD,
-                                        regno_reg_rtx[i],
-                                        REG_NOTES (where_dead));
+                 add_reg_note (where_dead, REG_DEAD, regno_reg_rtx[i]);
            }
 
          /* If we didn't find any note, or if we found a REG_DEAD note that
@@ -12040,7 +12205,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
              *pnotes = note;
            }
          else
-           *pnotes = gen_rtx_EXPR_LIST (REG_DEAD, x, *pnotes);
+           *pnotes = alloc_reg_note (REG_DEAD, x, *pnotes);
        }
 
       return;
@@ -12291,7 +12456,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
          break;
 
        case REG_INC:
-       case REG_NO_CONFLICT:
          /* These notes say something about how a register is used.  They must
             be present on any use of the register in I2 or I3.  */
          if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3)))
@@ -12306,7 +12470,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
            }
          break;
 
-       case REG_LABEL:
+       case REG_LABEL_TARGET:
+       case REG_LABEL_OPERAND:
          /* This can show up in several ways -- either directly in the
             pattern, or hidden off in the constant pool with (or without?)
             a REG_EQUAL note.  */
@@ -12329,34 +12494,33 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                place = i2;
            }
 
-         /* Don't attach REG_LABEL note to a JUMP_INSN.  Add
-            a JUMP_LABEL instead or decrement LABEL_NUSES.  */
-         if (place && JUMP_P (place))
+         /* For REG_LABEL_TARGET on a JUMP_P, we prefer to put the note
+            as a JUMP_LABEL or decrement LABEL_NUSES if it's already
+            there.  */
+         if (place && JUMP_P (place)
+             && REG_NOTE_KIND (note) == REG_LABEL_TARGET
+             && (JUMP_LABEL (place) == NULL
+                 || JUMP_LABEL (place) == XEXP (note, 0)))
            {
              rtx label = JUMP_LABEL (place);
 
              if (!label)
                JUMP_LABEL (place) = XEXP (note, 0);
-             else
-               {
-                 gcc_assert (label == XEXP (note, 0));
-                 if (LABEL_P (label))
-                   LABEL_NUSES (label)--;
-               }
-             place = 0;
+             else if (LABEL_P (label))
+               LABEL_NUSES (label)--;
            }
-         if (place2 && JUMP_P (place2))
+
+         if (place2 && JUMP_P (place2)
+             && REG_NOTE_KIND (note) == REG_LABEL_TARGET
+             && (JUMP_LABEL (place2) == NULL
+                 || JUMP_LABEL (place2) == XEXP (note, 0)))
            {
              rtx label = JUMP_LABEL (place2);
 
              if (!label)
                JUMP_LABEL (place2) = XEXP (note, 0);
-             else
-               {
-                 gcc_assert (label == XEXP (note, 0));
-                 if (LABEL_P (label))
-                   LABEL_NUSES (label)--;
-               }
+             else if (LABEL_P (label))
+               LABEL_NUSES (label)--;
              place2 = 0;
            }
          break;
@@ -12368,57 +12532,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
             to simply delete it.  */
          break;
 
-       case REG_LIBCALL_ID:
-         /* If the insn previously containing this note still exists,
-            put it back where it was.  Otherwise move it to the previous
-            insn.  */
-         if (!NOTE_P (from_insn))
-           place = from_insn;
-         else
-           place = prev_real_insn (from_insn);
-         break;
-       case REG_RETVAL:
-         /* If the insn previously containing this note still exists,
-            put it back where it was.  Otherwise move it to the previous
-            insn.  Adjust the corresponding REG_LIBCALL note.  */
-         if (!NOTE_P (from_insn))
-           place = from_insn;
-         else
-           {
-             tem = find_reg_note (XEXP (note, 0), REG_LIBCALL, NULL_RTX);
-             place = prev_real_insn (from_insn);
-             if (tem && place)
-               XEXP (tem, 0) = place;
-             /* If we're deleting the last remaining instruction of a
-                libcall sequence, don't add the notes.  */
-             else if (XEXP (note, 0) == from_insn)
-               tem = place = 0;
-             /* Don't add the dangling REG_RETVAL note.  */
-             else if (! tem)
-               place = 0;
-           }
-         break;
-
-       case REG_LIBCALL:
-         /* This is handled similarly to REG_RETVAL.  */
-         if (!NOTE_P (from_insn))
-           place = from_insn;
-         else
-           {
-             tem = find_reg_note (XEXP (note, 0), REG_RETVAL, NULL_RTX);
-             place = next_real_insn (from_insn);
-             if (tem && place)
-               XEXP (tem, 0) = place;
-             /* If we're deleting the last remaining instruction of a
-                libcall sequence, don't add the notes.  */
-             else if (XEXP (note, 0) == from_insn)
-               tem = place = 0;
-             /* Don't add the dangling REG_LIBCALL note.  */
-             else if (! tem)
-               place = 0;
-           }
-         break;
-
        case REG_DEAD:
          /* If we replaced the right hand side of FROM_INSN with a
             REG_EQUAL note, the original use of the dying register
@@ -12532,6 +12645,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                          distribute_links (LOG_LINKS (tem));
 
                          SET_INSN_DELETED (tem);
+                         if (tem == i2)
+                           i2 = NULL_RTX;
 
 #ifdef HAVE_cc0
                          /* Delete the setter too.  */
@@ -12547,6 +12662,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                              distribute_links (LOG_LINKS (cc0_setter));
 
                              SET_INSN_DELETED (cc0_setter);
+                             if (cc0_setter == i2)
+                               i2 = NULL_RTX;
                            }
 #endif
                        }
@@ -12605,7 +12722,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
          if (place && REG_NOTE_KIND (note) == REG_DEAD)
            {
              unsigned int regno = REGNO (XEXP (note, 0));
-
+             reg_stat_type *rsp = VEC_index (reg_stat_type, reg_stat, regno);
 
              if (dead_or_set_p (place, XEXP (note, 0))
                  || reg_bitfield_target_p (XEXP (note, 0), PATTERN (place)))
@@ -12613,12 +12730,12 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                  /* Unless the register previously died in PLACE, clear
                     last_death.  [I no longer understand why this is
                     being done.] */
-                 if (reg_stat[regno].last_death != place)
-                   reg_stat[regno].last_death = 0;
+                 if (rsp->last_death != place)
+                   rsp->last_death = 0;
                  place = 0;
                }
              else
-               reg_stat[regno].last_death = place;
+               rsp->last_death = place;
 
              /* If this is a death note for a hard reg that is occupying
                 multiple registers, ensure that we are still using all
@@ -12657,8 +12774,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                              && ! reg_bitfield_target_p (piece,
                                                          PATTERN (place)))
                            {
-                             rtx new_note
-                               = gen_rtx_EXPR_LIST (REG_DEAD, piece, NULL_RTX);
+                             rtx new_note = alloc_reg_note (REG_DEAD, piece,
+                                                            NULL_RTX);
 
                              distribute_notes (new_note, place, place,
                                                NULL_RTX, NULL_RTX, NULL_RTX);
@@ -12679,9 +12796,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
                                    || reg_bitfield_target_p (piece,
                                                              PATTERN (tem)))
                                  {
-                                   REG_NOTES (tem)
-                                     = gen_rtx_EXPR_LIST (REG_UNUSED, piece,
-                                                          REG_NOTES (tem));
+                                   add_reg_note (tem, REG_UNUSED, piece);
                                    break;
                                  }
                              }
@@ -12707,9 +12822,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
        }
 
       if (place2)
-       REG_NOTES (place2) 
-         = gen_rtx_fmt_ee (GET_CODE (note), REG_NOTE_KIND (note),
-                           XEXP (note, 0), REG_NOTES (place2));
+       add_reg_note (place2, REG_NOTE_KIND (note), XEXP (note, 0));
     }
 }
 \f
@@ -12885,8 +12998,10 @@ rest_of_handle_combine (void)
   return 0;
 }
 
-struct tree_opt_pass pass_combine =
+struct rtl_opt_pass pass_combine =
 {
+ {
+  RTL_PASS,
   "combine",                            /* name */
   gate_handle_combine,                  /* gate */
   rest_of_handle_combine,               /* execute */
@@ -12894,13 +13009,12 @@ struct tree_opt_pass pass_combine =
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
   TV_COMBINE,                           /* tv_id */
-  0,                                    /* properties_required */
+  PROP_cfglayout,                       /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_dump_func |
-  TODO_df_finish |
+  TODO_df_finish | TODO_verify_rtl_sharing |
   TODO_ggc_collect,                     /* todo_flags_finish */
-  'c'                                   /* letter */
+ }
 };
-