OSDN Git Service

2009-02-27 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index a6cff36..3aca075 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -297,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.  */
@@ -793,10 +794,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;
     }
@@ -811,7 +812,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 (newotherpat);
+      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;
@@ -899,7 +900,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 ());
 
@@ -924,7 +925,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;
 
@@ -978,7 +979,7 @@ create_log_links (void)
 
           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
@@ -1068,6 +1069,7 @@ combine_instructions (rtx f, unsigned int nregs)
   create_log_links ();
   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++;
@@ -1090,7 +1092,8 @@ 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));
@@ -1109,9 +1112,11 @@ combine_instructions (rtx f, unsigned int nregs)
 
   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++;
+      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))
@@ -1268,6 +1273,7 @@ combine_instructions (rtx f, unsigned int nregs)
        }
     }
 
+  default_rtl_profile ();
   clear_log_links ();
   clear_bb_flags ();
   new_direct_jump_p |= purge_all_dead_edges ();
@@ -1340,8 +1346,7 @@ setup_incoming_promotions (rtx first)
          function lie within the current compilation unit.  (This does
         take into account the exporting of a function via taking its
         address, and so forth.)  */
-      if (flag_unit_at_a_time)
-       strictly_local = cgraph_local_info (current_function_decl)->local;
+      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).  */
@@ -2204,6 +2209,7 @@ 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;
@@ -2891,14 +2897,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;
        }
     }
 
@@ -3371,6 +3370,16 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p)
       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.  */
 
@@ -4278,7 +4287,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
@@ -4333,14 +4342,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--)
        {
@@ -4350,14 +4359,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);
            }
        }
     }
@@ -4390,33 +4399,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))
                ;
 
@@ -4457,7 +4466,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
@@ -4469,7 +4478,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))
@@ -4482,30 +4491,30 @@ 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);
            }
        }
     }
@@ -5638,9 +5647,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.  */
@@ -5697,6 +5706,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));
@@ -5719,7 +5729,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),
@@ -5839,6 +5849,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))
@@ -6106,9 +6117,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;
@@ -6373,7 +6386,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;
 
@@ -6397,11 +6410,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);
@@ -6457,7 +6470,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))
        {
@@ -6487,16 +6500,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,
@@ -6506,34 +6519,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;
        }
@@ -6542,7 +6556,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,
@@ -6727,7 +6741,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;
@@ -6746,12 +6761,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
@@ -6826,8 +6841,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;
 
@@ -6852,8 +6867,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))));
        }
@@ -6870,8 +6885,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);
        }
 
@@ -6881,9 +6896,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);
        }
@@ -6895,12 +6910,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
@@ -6911,8 +6926,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);
@@ -6945,7 +6960,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);
@@ -6954,7 +6969,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);
@@ -6969,7 +6984,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));
@@ -6987,10 +7002,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);
@@ -7007,8 +7023,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);
 
@@ -7053,9 +7070,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);
     }
 
@@ -7064,9 +7081,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.  */
@@ -7306,6 +7329,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:
@@ -7376,7 +7403,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;
            }
 
@@ -8074,16 +8102,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);
        }
@@ -8099,16 +8127,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);
        }
@@ -8520,7 +8548,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;
@@ -8961,7 +8990,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
@@ -8986,11 +9015,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)
        {
@@ -9036,6 +9060,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
@@ -9083,10 +9112,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;
@@ -9101,12 +9130,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;
            }
@@ -9327,10 +9356,10 @@ 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;
            }
@@ -9384,12 +9413,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;
@@ -9512,12 +9541,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;
@@ -9531,12 +9560,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;
@@ -11180,7 +11209,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')
@@ -11210,6 +11239,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;
 }
@@ -11223,7 +11255,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)
     {
@@ -11241,8 +11273,6 @@ update_table_tick (rtx x)
     }
 
   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
@@ -11279,6 +11309,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
@@ -11686,7 +11719,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))
     {
@@ -11764,9 +11797,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.  */
@@ -12624,6 +12659,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.  */
@@ -12639,6 +12676,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
                        }