OSDN Git Service

Merge in xfails from PR14107.
[pf3gnuchains/gcc-fork.git] / gcc / cse.c
index 266170b..5f1107c 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "except.h"
 #include "target.h"
 #include "params.h"
+#include "rtlhooks-def.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -593,7 +594,7 @@ struct cse_basic_block_data
       /* Whether it should be taken or not.  AROUND is the same as taken
         except that it is used when the destination label is not preceded
        by a BARRIER.  */
-      enum taken {TAKEN, NOT_TAKEN, AROUND} status;
+      enum taken {PATH_TAKEN, PATH_NOT_TAKEN, PATH_AROUND} status;
     } *path;
 };
 
@@ -601,7 +602,7 @@ static bool fixed_base_plus_p (rtx x);
 static int notreg_cost (rtx, enum rtx_code);
 static int approx_reg_cost_1 (rtx *, void *);
 static int approx_reg_cost (rtx);
-static int preferrable (int, int, int, int);
+static int preferable (int, int, int, int);
 static void new_basic_block (void);
 static void make_new_qty (unsigned int, enum machine_mode);
 static void make_regs_eqv (unsigned int, unsigned int);
@@ -639,6 +640,8 @@ static void record_jump_equiv (rtx, int);
 static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
                              int);
 static void cse_insn (rtx, rtx);
+static void cse_end_of_basic_block (rtx, struct cse_basic_block_data *,
+                                   int, int, int);
 static int addr_affects_sp_p (rtx);
 static void invalidate_from_clobbers (rtx);
 static rtx cse_process_notes (rtx, rtx);
@@ -662,6 +665,12 @@ static int cse_change_cc_mode (rtx *, void *);
 static void cse_change_cc_mode_insns (rtx, rtx, rtx);
 static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
 \f
+
+#undef RTL_HOOKS_GEN_LOWPART
+#define RTL_HOOKS_GEN_LOWPART          gen_lowpart_if_possible
+
+static const struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER;
+\f
 /* Nonzero if X has the form (PLUS frame-pointer integer).  We check for
    virtual regs here because the simplify_*_operation routines are called
    by integrate.c, which is called before virtual register instantiation.  */
@@ -761,7 +770,7 @@ approx_reg_cost (rtx x)
    Return a positive value if A is less desirable, or 0 if the two are
    equally good.  */
 static int
-preferrable (int cost_a, int regcost_a, int cost_b, int regcost_b)
+preferable (int cost_a, int regcost_a, int cost_b, int regcost_b)
 {
   /* First, get rid of cases involving expressions that are entirely
      unwanted.  */
@@ -810,109 +819,6 @@ notreg_cost (rtx x, enum rtx_code outer)
          : rtx_cost (x, outer) * 2);
 }
 
-/* Return an estimate of the cost of computing rtx X.
-   One use is in cse, to decide which expression to keep in the hash table.
-   Another is in rtl generation, to pick the cheapest way to multiply.
-   Other uses like the latter are expected in the future.  */
-
-int
-rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED)
-{
-  int i, j;
-  enum rtx_code code;
-  const char *fmt;
-  int total;
-
-  if (x == 0)
-    return 0;
-
-  /* Compute the default costs of certain things.
-     Note that targetm.rtx_costs can override the defaults.  */
-
-  code = GET_CODE (x);
-  switch (code)
-    {
-    case MULT:
-      total = COSTS_N_INSNS (5);
-      break;
-    case DIV:
-    case UDIV:
-    case MOD:
-    case UMOD:
-      total = COSTS_N_INSNS (7);
-      break;
-    case USE:
-      /* Used in loop.c and combine.c as a marker.  */
-      total = 0;
-      break;
-    default:
-      total = COSTS_N_INSNS (1);
-    }
-
-  switch (code)
-    {
-    case REG:
-      return 0;
-
-    case SUBREG:
-      /* If we can't tie these modes, make this expensive.  The larger
-        the mode, the more expensive it is.  */
-      if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
-       return COSTS_N_INSNS (2
-                             + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
-      break;
-
-    default:
-      if ((*targetm.rtx_costs) (x, code, outer_code, &total))
-       return total;
-      break;
-    }
-
-  /* Sum the costs of the sub-rtx's, plus cost of this operation,
-     which is already in total.  */
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    if (fmt[i] == 'e')
-      total += rtx_cost (XEXP (x, i), code);
-    else if (fmt[i] == 'E')
-      for (j = 0; j < XVECLEN (x, i); j++)
-       total += rtx_cost (XVECEXP (x, i, j), code);
-
-  return total;
-}
-\f
-/* Return cost of address expression X.
-   Expect that X is properly formed address reference.  */
-
-int
-address_cost (rtx x, enum machine_mode mode)
-{
-  /* The address_cost target hook does not deal with ADDRESSOF nodes.  But,
-     during CSE, such nodes are present.  Using an ADDRESSOF node which
-     refers to the address of a REG is a good thing because we can then
-     turn (MEM (ADDRESSSOF (REG))) into just plain REG.  */
-
-  if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
-    return -1;
-
-  /* We may be asked for cost of various unusual addresses, such as operands
-     of push instruction.  It is not worthwhile to complicate writing
-     of the target hook by such cases.  */
-
-  if (!memory_address_p (mode, x))
-    return 1000;
-
-  return (*targetm.address_cost) (x);
-}
-
-/* If the target doesn't override, compute the cost as with arithmetic.  */
-
-int
-default_address_cost (rtx x)
-{
-  return rtx_cost (x, MEM);
-}
 \f
 static struct cse_reg_info *
 get_cse_reg_info (unsigned int regno)
@@ -1162,7 +1068,7 @@ mention_regs (rtx x)
       unsigned int regno = REGNO (x);
       unsigned int endregno
        = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-                  : HARD_REGNO_NREGS (regno, GET_MODE (x)));
+                  : hard_regno_nregs[regno][GET_MODE (x)]);
       unsigned int i;
 
       for (i = regno; i < endregno; i++)
@@ -1214,7 +1120,7 @@ mention_regs (rtx x)
      call that expensive function in the most common case where the only
      use of the register is in the comparison.  */
 
-  if (code == COMPARE || GET_RTX_CLASS (code) == '<')
+  if (code == COMPARE || COMPARISON_P (x))
     {
       if (GET_CODE (XEXP (x, 0)) == REG
          && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))
@@ -1513,7 +1419,7 @@ lookup_as_function (rtx x, enum rtx_code code)
    If necessary, update table showing constant values of quantities.  */
 
 #define CHEAPER(X, Y) \
- (preferrable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
+ (preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
 
 static struct table_elt *
 insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode)
@@ -1529,7 +1435,7 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
   if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
     {
       unsigned int regno = REGNO (x);
-      unsigned int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+      unsigned int endregno = regno + hard_regno_nregs[regno][GET_MODE (x)];
       unsigned int i;
 
       for (i = regno; i < endregno; i++)
@@ -1628,7 +1534,7 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
       int exp_q = REG_QTY (REGNO (classp->exp));
       struct qty_table_elem *exp_ent = &qty_table[exp_q];
 
-      exp_ent->const_rtx = gen_lowpart_if_possible (exp_ent->mode, x);
+      exp_ent->const_rtx = gen_lowpart (exp_ent->mode, x);
       exp_ent->const_insn = this_insn;
     }
 
@@ -1647,7 +1553,7 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
              struct qty_table_elem *x_ent = &qty_table[x_q];
 
              x_ent->const_rtx
-               = gen_lowpart_if_possible (GET_MODE (x), p->exp);
+               = gen_lowpart (GET_MODE (x), p->exp);
              x_ent->const_insn = this_insn;
              break;
            }
@@ -1842,7 +1748,7 @@ invalidate (rtx x, enum machine_mode full_mode)
            HOST_WIDE_INT in_table
              = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
            unsigned int endregno
-             = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+             = regno + hard_regno_nregs[regno][GET_MODE (x)];
            unsigned int tregno, tendregno, rn;
            struct table_elt *p, *next;
 
@@ -1869,7 +1775,7 @@ invalidate (rtx x, enum machine_mode full_mode)
 
                    tregno = REGNO (p->exp);
                    tendregno
-                     = tregno + HARD_REGNO_NREGS (tregno, GET_MODE (p->exp));
+                     = tregno + hard_regno_nregs[tregno][GET_MODE (p->exp)];
                    if (tendregno > regno && tregno < endregno)
                      remove_from_table (p, hash);
                  }
@@ -2081,7 +1987,7 @@ invalidate_for_call (void)
            continue;
 
          regno = REGNO (p->exp);
-         endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (p->exp));
+         endregno = regno + hard_regno_nregs[regno][GET_MODE (p->exp)];
 
          for (i = regno; i < endregno; i++)
            if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
@@ -2540,7 +2446,7 @@ exp_equiv_p (rtx x, rtx y, int validate, int equal_values)
        unsigned int regno = REGNO (y);
        unsigned int endregno
          = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-                    : HARD_REGNO_NREGS (regno, GET_MODE (y)));
+                    : hard_regno_nregs[regno][GET_MODE (y)]);
        unsigned int i;
 
        /* If the quantities are not the same, the expressions are not
@@ -2953,8 +2859,7 @@ find_best_addr (rtx insn, rtx *loc, enum machine_mode mode)
      code on the Alpha for unaligned byte stores.  */
 
   if (flag_expensive_optimizations
-      && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
-         || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
+      && ARITHMETIC_P (*loc)
       && GET_CODE (XEXP (*loc, 0)) == REG)
     {
       rtx op1 = XEXP (*loc, 1);
@@ -3068,7 +2973,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
       /* If ARG1 is a comparison operator and CODE is testing for
         STORE_FLAG_VALUE, get the inner arguments.  */
 
-      else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
+      else if (COMPARISON_P (arg1))
        {
 #ifdef FLOAT_STORE_FLAG_VALUE
          REAL_VALUE_TYPE fsfv;
@@ -3157,7 +3062,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
                           REAL_VALUE_NEGATIVE (fsfv)))
 #endif
                   )
-                 && GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
+                 && COMPARISON_P (p->exp)))
            {
              x = p->exp;
              break;
@@ -3177,7 +3082,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
                            REAL_VALUE_NEGATIVE (fsfv)))
 #endif
                    )
-                  && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
+                  && COMPARISON_P (p->exp))
            {
              reverse_code = 1;
              x = p->exp;
@@ -3210,7 +3115,7 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
          else
            code = reversed;
        }
-      else if (GET_RTX_CLASS (GET_CODE (x)) == '<')
+      else if (COMPARISON_P (x))
        code = GET_CODE (x);
       arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
     }
@@ -3391,9 +3296,9 @@ fold_rtx (rtx x, rtx insn)
                enum rtx_code eltcode = GET_CODE (elt->exp);
 
                /* Just check for unary and binary operations.  */
-               if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1'
-                   && GET_CODE (elt->exp) != SIGN_EXTEND
-                   && GET_CODE (elt->exp) != ZERO_EXTEND
+               if (UNARY_P (elt->exp)
+                   && eltcode != SIGN_EXTEND
+                   && eltcode != ZERO_EXTEND
                    && GET_CODE (XEXP (elt->exp, 0)) == SUBREG
                    && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode
                    && (GET_MODE_CLASS (mode)
@@ -3409,8 +3314,7 @@ fold_rtx (rtx x, rtx insn)
                      new = simplify_unary_operation (GET_CODE (elt->exp), mode,
                                                      op0, mode);
                  }
-               else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2'
-                         || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c')
+               else if (ARITHMETIC_P (elt->exp)
                         && eltcode != DIV && eltcode != MOD
                         && eltcode != UDIV && eltcode != UMOD
                         && eltcode != ASHIFTRT && eltcode != LSHIFTRT
@@ -3577,7 +3481,7 @@ fold_rtx (rtx x, rtx insn)
            if (((BYTES_BIG_ENDIAN
                  && offset == GET_MODE_SIZE (GET_MODE (constant)) - 1)
                 || (! BYTES_BIG_ENDIAN && offset == 0))
-               && (new = gen_lowpart_if_possible (mode, constant)) != 0)
+               && (new = gen_lowpart (mode, constant)) != 0)
              return new;
          }
 
@@ -3683,7 +3587,7 @@ fold_rtx (rtx x, rtx insn)
                    && GET_CODE (arg_ent->const_rtx) != REG
                    && GET_CODE (arg_ent->const_rtx) != PLUS)
                  const_arg
-                   = gen_lowpart_if_possible (GET_MODE (arg),
+                   = gen_lowpart (GET_MODE (arg),
                                               arg_ent->const_rtx);
              }
            break;
@@ -3765,12 +3669,28 @@ fold_rtx (rtx x, rtx insn)
                || (new_cost == old_cost && CONSTANT_P (XEXP (x, i))))
              break;
 
+           /* It's not safe to substitute the operand of a conversion
+              operator with a constant, as the conversion's identity
+              depends upon the mode of it's operand.  This optimization
+              is handled by the call to simplify_unary_operation.  */
+           if (GET_RTX_CLASS (code) == RTX_UNARY
+               && GET_MODE (replacements[j]) != mode_arg0
+               && (code == ZERO_EXTEND
+                   || code == SIGN_EXTEND
+                   || code == TRUNCATE
+                   || code == FLOAT_TRUNCATE
+                   || code == FLOAT_EXTEND
+                   || code == FLOAT
+                   || code == FIX
+                   || code == UNSIGNED_FLOAT
+                   || code == UNSIGNED_FIX))
+             continue;
+
            if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
              break;
 
-           if (code == NE || code == EQ || GET_RTX_CLASS (code) == 'c'
-               || code == LTGT || code == UNEQ || code == ORDERED
-               || code == UNORDERED)
+           if (GET_RTX_CLASS (code) == RTX_COMM_COMPARE
+               || GET_RTX_CLASS (code) == RTX_COMM_ARITH)
              {
                validate_change (insn, &XEXP (x, i), XEXP (x, 1 - i), 1);
                validate_change (insn, &XEXP (x, 1 - i), replacements[j], 1);
@@ -3802,9 +3722,7 @@ fold_rtx (rtx x, rtx insn)
      operand unless the first operand is also a constant integer.  Otherwise,
      place any constant second unless the first operand is also a constant.  */
 
-  if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c'
-      || code == LTGT || code == UNEQ || code == ORDERED
-      || code == UNORDERED)
+  if (COMMUTATIVE_P (x))
     {
       if (must_swap
          || swap_commutative_operands_p (const_arg0 ? const_arg0
@@ -3834,7 +3752,7 @@ fold_rtx (rtx x, rtx insn)
 
   switch (GET_RTX_CLASS (code))
     {
-    case '1':
+    case RTX_UNARY:
       {
        int is_const = 0;
 
@@ -3857,7 +3775,8 @@ fold_rtx (rtx x, rtx insn)
       }
       break;
 
-    case '<':
+    case RTX_COMPARE:
+    case RTX_COMM_COMPARE:
       /* See what items are actually being compared and set FOLDED_ARG[01]
         to those values and CODE to the actual comparison code.  If any are
         constant, set CONST_ARG0 and CONST_ARG1 appropriately.  We needn't
@@ -4012,35 +3931,15 @@ fold_rtx (rtx x, rtx insn)
            }
        }
 
-      new = simplify_relational_operation (code,
-                                          (mode_arg0 != VOIDmode
-                                           ? mode_arg0
-                                           : (GET_MODE (const_arg0
-                                                        ? const_arg0
-                                                        : folded_arg0)
-                                              != VOIDmode)
-                                           ? GET_MODE (const_arg0
-                                                       ? const_arg0
-                                                       : folded_arg0)
-                                           : GET_MODE (const_arg1
-                                                       ? const_arg1
-                                                       : folded_arg1)),
-                                          const_arg0 ? const_arg0 : folded_arg0,
-                                          const_arg1 ? const_arg1 : folded_arg1);
-#ifdef FLOAT_STORE_FLAG_VALUE
-      if (new != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT)
-       {
-         if (new == const0_rtx)
-           new = CONST0_RTX (mode);
-         else
-           new = (CONST_DOUBLE_FROM_REAL_VALUE
-                  (FLOAT_STORE_FLAG_VALUE (mode), mode));
-       }
-#endif
+      {
+       rtx op0 = const_arg0 ? const_arg0 : folded_arg0;
+       rtx op1 = const_arg1 ? const_arg1 : folded_arg1;
+        new = simplify_relational_operation (code, mode, mode_arg0, op0, op1);
+      }
       break;
 
-    case '2':
-    case 'c':
+    case RTX_BIN_ARITH:
+    case RTX_COMM_ARITH:
       switch (code)
        {
        case PLUS:
@@ -4245,7 +4144,7 @@ fold_rtx (rtx x, rtx insn)
                                       const_arg1 ? const_arg1 : folded_arg1);
       break;
 
-    case 'o':
+    case RTX_OBJ:
       /* (lo_sum (high X) X) is simply X.  */
       if (code == LO_SUM && const_arg0 != 0
          && GET_CODE (const_arg0) == HIGH
@@ -4253,23 +4152,15 @@ fold_rtx (rtx x, rtx insn)
        return const_arg1;
       break;
 
-    case '3':
-    case 'b':
+    case RTX_TERNARY:
+    case RTX_BITFIELD_OPS:
       new = simplify_ternary_operation (code, mode, mode_arg0,
                                        const_arg0 ? const_arg0 : folded_arg0,
                                        const_arg1 ? const_arg1 : folded_arg1,
                                        const_arg2 ? const_arg2 : XEXP (x, 2));
       break;
 
-    case 'x':
-      /* Eliminate CONSTANT_P_RTX if its constant.  */
-      if (code == CONSTANT_P_RTX)
-       {
-         if (const_arg0)
-           return const1_rtx;
-         if (optimize == 0 || !flag_gcse)
-           return const0_rtx;
-       }
+    default:
       break;
     }
 
@@ -4289,7 +4180,7 @@ equiv_constant (rtx x)
       struct qty_table_elem *x_ent = &qty_table[x_q];
 
       if (x_ent->const_rtx)
-       x = gen_lowpart_if_possible (GET_MODE (x), x_ent->const_rtx);
+       x = gen_lowpart (GET_MODE (x), x_ent->const_rtx);
     }
 
   if (x == 0 || CONSTANT_P (x))
@@ -4327,7 +4218,7 @@ equiv_constant (rtx x)
 
    If the requested operation cannot be done, 0 is returned.
 
-   This is similar to gen_lowpart in emit-rtl.c.  */
+   This is similar to gen_lowpart_general in emit-rtl.c.  */
 
 rtx
 gen_lowpart_if_possible (enum machine_mode mode, rtx x)
@@ -4361,7 +4252,7 @@ gen_lowpart_if_possible (enum machine_mode mode, rtx x)
     return 0;
 }
 \f
-/* Given INSN, a jump insn, TAKEN indicates if we are following the "taken"
+/* Given INSN, a jump insn, PATH_TAKEN indicates if we are following the "taken"
    branch.  It will be zero if not.
 
    In certain cases, this can cause us to add an equivalence.  For example,
@@ -4442,7 +4333,7 @@ record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-      rtx tem = gen_lowpart_if_possible (inner_mode, op1);
+      rtx tem = gen_lowpart (inner_mode, op1);
 
       record_jump_cond (code, mode, SUBREG_REG (op0),
                        tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
@@ -4454,7 +4345,7 @@ record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
-      rtx tem = gen_lowpart_if_possible (inner_mode, op0);
+      rtx tem = gen_lowpart (inner_mode, op0);
 
       record_jump_cond (code, mode, SUBREG_REG (op1),
                        tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
@@ -4474,7 +4365,7 @@ record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-      rtx tem = gen_lowpart_if_possible (inner_mode, op1);
+      rtx tem = gen_lowpart (inner_mode, op1);
 
       record_jump_cond (code, mode, SUBREG_REG (op0),
                        tem ? tem : gen_rtx_SUBREG (inner_mode, op1, 0),
@@ -4487,7 +4378,7 @@ record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
     {
       enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
-      rtx tem = gen_lowpart_if_possible (inner_mode, op0);
+      rtx tem = gen_lowpart (inner_mode, op0);
 
       record_jump_cond (code, mode, SUBREG_REG (op1),
                        tem ? tem : gen_rtx_SUBREG (inner_mode, op0, 0),
@@ -5031,7 +4922,7 @@ cse_insn (rtx insn, rtx libcall_insn)
       /* It is no longer clear why we used to do this, but it doesn't
         appear to still be needed.  So let's try without it since this
         code hurts cse'ing widened ops.  */
-      /* If source is a perverse subreg (such as QI treated as an SI),
+      /* If source is a paradoxical subreg (such as QI treated as an SI),
         treat it as volatile.  It may do the work of an SI in one context
         where the extra bits are not being used, but cannot replace an SI
         in general.  */
@@ -5176,7 +5067,7 @@ cse_insn (rtx insn, rtx libcall_insn)
                   const_elt; const_elt = const_elt->next_same_value)
                if (GET_CODE (const_elt->exp) == REG)
                  {
-                   src_related = gen_lowpart_if_possible (mode,
+                   src_related = gen_lowpart (mode,
                                                           const_elt->exp);
                    break;
                  }
@@ -5200,7 +5091,7 @@ cse_insn (rtx insn, rtx libcall_insn)
               GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
               tmode = GET_MODE_WIDER_MODE (tmode))
            {
-             rtx inner = gen_lowpart_if_possible (tmode, XEXP (src, 0));
+             rtx inner = gen_lowpart (tmode, XEXP (src, 0));
              struct table_elt *larger_elt;
 
              if (inner)
@@ -5216,7 +5107,7 @@ cse_insn (rtx insn, rtx libcall_insn)
                    if (GET_CODE (larger_elt->exp) == REG)
                      {
                        src_related
-                         = gen_lowpart_if_possible (mode, larger_elt->exp);
+                         = gen_lowpart (mode, larger_elt->exp);
                        break;
                      }
 
@@ -5230,7 +5121,7 @@ cse_insn (rtx insn, rtx libcall_insn)
       /* See if a MEM has already been loaded with a widening operation;
         if it has, we can use a subreg of that.  Many CISC machines
         also have such operations, but this is only likely to be
-        beneficial these machines.  */
+        beneficial on these machines.  */
 
       if (flag_expensive_optimizations && src_related == 0
          && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
@@ -5261,7 +5152,7 @@ cse_insn (rtx insn, rtx libcall_insn)
                   larger_elt; larger_elt = larger_elt->next_same_value)
                if (GET_CODE (larger_elt->exp) == REG)
                  {
-                   src_related = gen_lowpart_if_possible (mode,
+                   src_related = gen_lowpart (mode,
                                                           larger_elt->exp);
                    break;
                  }
@@ -5424,14 +5315,14 @@ cse_insn (rtx insn, rtx libcall_insn)
             of equal cost, use this order:
             src_folded, src, src_eqv, src_related and hash table entry.  */
          if (src_folded
-             && preferrable (src_folded_cost, src_folded_regcost,
-                             src_cost, src_regcost) <= 0
-             && preferrable (src_folded_cost, src_folded_regcost,
-                             src_eqv_cost, src_eqv_regcost) <= 0
-             && preferrable (src_folded_cost, src_folded_regcost,
-                             src_related_cost, src_related_regcost) <= 0
-             && preferrable (src_folded_cost, src_folded_regcost,
-                             src_elt_cost, src_elt_regcost) <= 0)
+             && preferable (src_folded_cost, src_folded_regcost,
+                            src_cost, src_regcost) <= 0
+             && preferable (src_folded_cost, src_folded_regcost,
+                            src_eqv_cost, src_eqv_regcost) <= 0
+             && preferable (src_folded_cost, src_folded_regcost,
+                            src_related_cost, src_related_regcost) <= 0
+             && preferable (src_folded_cost, src_folded_regcost,
+                            src_elt_cost, src_elt_regcost) <= 0)
            {
              trial = src_folded, src_folded_cost = MAX_COST;
              if (src_folded_force_flag)
@@ -5442,22 +5333,22 @@ cse_insn (rtx insn, rtx libcall_insn)
                }
            }
          else if (src
-                  && preferrable (src_cost, src_regcost,
-                                  src_eqv_cost, src_eqv_regcost) <= 0
-                  && preferrable (src_cost, src_regcost,
-                                  src_related_cost, src_related_regcost) <= 0
-                  && preferrable (src_cost, src_regcost,
-                                  src_elt_cost, src_elt_regcost) <= 0)
+                  && preferable (src_cost, src_regcost,
+                                 src_eqv_cost, src_eqv_regcost) <= 0
+                  && preferable (src_cost, src_regcost,
+                                 src_related_cost, src_related_regcost) <= 0
+                  && preferable (src_cost, src_regcost,
+                                 src_elt_cost, src_elt_regcost) <= 0)
            trial = src, src_cost = MAX_COST;
          else if (src_eqv_here
-                  && preferrable (src_eqv_cost, src_eqv_regcost,
-                                  src_related_cost, src_related_regcost) <= 0
-                  && preferrable (src_eqv_cost, src_eqv_regcost,
-                                  src_elt_cost, src_elt_regcost) <= 0)
+                  && preferable (src_eqv_cost, src_eqv_regcost,
+                                 src_related_cost, src_related_regcost) <= 0
+                  && preferable (src_eqv_cost, src_eqv_regcost,
+                                 src_elt_cost, src_elt_regcost) <= 0)
            trial = copy_rtx (src_eqv_here), src_eqv_cost = MAX_COST;
          else if (src_related
-                  && preferrable (src_related_cost, src_related_regcost,
-                                  src_elt_cost, src_elt_regcost) <= 0)
+                  && preferable (src_related_cost, src_related_regcost,
+                                 src_elt_cost, src_elt_regcost) <= 0)
            trial = copy_rtx (src_related), src_related_cost = MAX_COST;
          else
            {
@@ -5497,8 +5388,13 @@ cse_insn (rtx insn, rtx libcall_insn)
                  && (GET_CODE (sets[i].orig_src) == REG
                      || GET_CODE (sets[i].orig_src) == SUBREG
                      || GET_CODE (sets[i].orig_src) == MEM))
-               simplify_replace_rtx (REG_NOTES (libcall_insn),
-                                     sets[i].orig_src, copy_rtx (new));
+               {
+                 rtx note = find_reg_equal_equiv_note (libcall_insn);
+                 if (note != 0)
+                   XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0),
+                                                          sets[i].orig_src,
+                                                          copy_rtx (new));
+               }
 
              /* The result of apply_change_group can be ignored; see
                 canon_reg.  */
@@ -5647,7 +5543,7 @@ cse_insn (rtx insn, rtx libcall_insn)
 #ifdef PUSH_ROUNDING
          /* Stack pushes invalidate the stack pointer.  */
          rtx addr = XEXP (dest, 0);
-         if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
+         if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
              && XEXP (addr, 0) == stack_pointer_rtx)
            invalidate (stack_pointer_rtx, Pmode);
 #endif
@@ -5719,10 +5615,20 @@ cse_insn (rtx insn, rtx libcall_insn)
             and hope for the best.  */
          if (n_sets == 1)
            {
-             rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
+             rtx new, note;
 
+             new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
              JUMP_LABEL (new) = XEXP (src, 0);
              LABEL_NUSES (XEXP (src, 0))++;
+
+             /* Make sure to copy over REG_NON_LOCAL_GOTO.  */
+             note = find_reg_note (insn, REG_NON_LOCAL_GOTO, 0);
+             if (note)
+               {
+                 XEXP (note, 1) = NULL_RTX;
+                 REG_NOTES (new) = note;
+               }
+
              delete_insn (insn);
              insn = new;
 
@@ -5734,8 +5640,6 @@ cse_insn (rtx insn, rtx libcall_insn)
          else
            INSN_CODE (insn) = -1;
 
-         never_reached_warning (insn, NULL);
-
          /* Do not bother deleting any unreachable code,
             let jump/flow do that.  */
 
@@ -5974,7 +5878,7 @@ cse_insn (rtx insn, rtx libcall_insn)
              unsigned int regno = REGNO (x);
              unsigned int endregno
                = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
-                          : HARD_REGNO_NREGS (regno, GET_MODE (x)));
+                          : hard_regno_nregs[regno][GET_MODE (x)]);
              unsigned int i;
 
              for (i = regno; i < endregno; i++)
@@ -6087,8 +5991,8 @@ cse_insn (rtx insn, rtx libcall_insn)
           we are also doing (set (reg:m2 foo) (subreg:m2 (bar:m1) 0)) so
           make that equivalence as well.
 
-          However, BAR may have equivalences for which gen_lowpart_if_possible
-          will produce a simpler value than gen_lowpart_if_possible applied to
+          However, BAR may have equivalences for which gen_lowpart
+          will produce a simpler value than gen_lowpart applied to
           BAR (e.g., if BAR was ZERO_EXTENDed from M2), so we will scan all
           BAR's equivalences.  If we don't get a simplified form, make
           the SUBREG.  It will not be used in an equivalence, but will
@@ -6303,7 +6207,7 @@ invalidate_memory (void)
 static int
 addr_affects_sp_p (rtx addr)
 {
-  if (GET_RTX_CLASS (GET_CODE (addr)) == 'a'
+  if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
       && GET_CODE (XEXP (addr, 0)) == REG
       && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
     {
@@ -6433,7 +6337,7 @@ cse_process_notes (rtx x, rtx object)
              && (CONSTANT_P (ent->const_rtx)
                  || GET_CODE (ent->const_rtx) == REG))
            {
-             rtx new = gen_lowpart_if_possible (GET_MODE (x), ent->const_rtx);
+             rtx new = gen_lowpart (GET_MODE (x), ent->const_rtx);
              if (new)
                return new;
            }
@@ -6750,7 +6654,7 @@ cse_set_around_loop (rtx x, rtx insn, rtx loop_start)
    the current block.  The incoming structure's branch path, if any, is used
    to construct the output branch path.  */
 
-void
+static void
 cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
                        int follow_jumps, int after_loop, int skip_blocks)
 {
@@ -6763,14 +6667,15 @@ cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
   int i;
 
   /* Update the previous branch path, if any.  If the last branch was
-     previously TAKEN, mark it NOT_TAKEN.  If it was previously NOT_TAKEN,
+     previously PATH_TAKEN, mark it PATH_NOT_TAKEN.
+     If it was previously PATH_NOT_TAKEN,
      shorten the path by one and look at the previous branch.  We know that
      at least one branch must have been taken if PATH_SIZE is nonzero.  */
   while (path_size > 0)
     {
-      if (data->path[path_size - 1].status != NOT_TAKEN)
+      if (data->path[path_size - 1].status != PATH_NOT_TAKEN)
        {
-         data->path[path_size - 1].status = NOT_TAKEN;
+         data->path[path_size - 1].status = PATH_NOT_TAKEN;
          break;
        }
       else
@@ -6832,7 +6737,7 @@ cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
         take it, do so.  */
       if (path_entry < path_size && data->path[path_entry].branch == p)
        {
-         if (data->path[path_entry].status != NOT_TAKEN)
+         if (data->path[path_entry].status != PATH_NOT_TAKEN)
            p = JUMP_LABEL (p);
 
          /* Point to next entry in path, if any.  */
@@ -6886,7 +6791,7 @@ cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
                break;
 
              data->path[path_entry].branch = p;
-             data->path[path_entry++].status = TAKEN;
+             data->path[path_entry++].status = PATH_TAKEN;
 
              /* This branch now ends our path.  It was possible that we
                 didn't see this branch the last time around (when the
@@ -6925,7 +6830,7 @@ cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
              if (tmp == q)
                {
                  data->path[path_entry].branch = p;
-                 data->path[path_entry++].status = AROUND;
+                 data->path[path_entry++].status = PATH_AROUND;
 
                  path_size = path_entry;
 
@@ -6946,7 +6851,7 @@ cse_end_of_basic_block (rtx insn, struct cse_basic_block_data *data,
   /* If all jumps in the path are not taken, set our path length to zero
      so a rescan won't be done.  */
   for (i = path_size - 1; i >= 0; i--)
-    if (data->path[i].status != NOT_TAKEN)
+    if (data->path[i].status != PATH_NOT_TAKEN)
       break;
 
   if (i == -1)
@@ -6983,6 +6888,7 @@ cse_main (rtx f, int nregs, int after_loop, FILE *file)
   constant_pool_entries_cost = 0;
   constant_pool_entries_regcost = 0;
   val.path_size = 0;
+  rtl_hooks = cse_rtl_hooks;
 
   init_recog ();
   init_alias_analysis ();
@@ -7102,6 +7008,7 @@ cse_main (rtx f, int nregs, int after_loop, FILE *file)
   free (uid_cuid);
   free (reg_eqv_table);
   free (val.path);
+  rtl_hooks = general_rtl_hooks;
 
   return cse_jumps_altered || recorded_label_ref;
 }
@@ -7160,9 +7067,9 @@ cse_basic_block (rtx from, rtx to, struct branch_path *next_branch,
       if (next_branch->branch == insn)
        {
          enum taken status = next_branch++->status;
-         if (status != NOT_TAKEN)
+         if (status != PATH_NOT_TAKEN)
            {
-             if (status == TAKEN)
+             if (status == PATH_TAKEN)
                record_jump_equiv (insn, 1);
              else
                invalidate_skipped_block (NEXT_INSN (insn));
@@ -7181,7 +7088,7 @@ cse_basic_block (rtx from, rtx to, struct branch_path *next_branch,
       if (GET_MODE (insn) == QImode)
        PUT_MODE (insn, VOIDmode);
 
-      if (GET_RTX_CLASS (code) == 'i')
+      if (GET_RTX_CLASS (code) == RTX_INSN)
        {
          rtx p;
 
@@ -7660,8 +7567,8 @@ delete_trivially_dead_insns (rtx insns, int nreg)
     }
   while (ndead != nlastdead);
 
-  if (rtl_dump_file && ndead)
-    fprintf (rtl_dump_file, "Deleted %i trivially dead insns; %i iterations\n",
+  if (dump_file && ndead)
+    fprintf (dump_file, "Deleted %i trivially dead insns; %i iterations\n",
             ndead, niterations);
   /* Clean up.  */
   free (counts);
@@ -7692,7 +7599,7 @@ cse_change_cc_mode (rtx *loc, void *data)
 
 /* Change the mode of any reference to the register REGNO (NEWREG) to
    GET_MODE (NEWREG), starting at START.  Stop before END.  Stop at
-   any instruction after START which modifies NEWREG.  */
+   any instruction which modifies NEWREG.  */
 
 static void
 cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
@@ -7704,7 +7611,7 @@ cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
       if (! INSN_P (insn))
        continue;
 
-      if (insn != start && reg_set_p (newreg, insn))
+      if (reg_set_p (newreg, insn))
        return;
 
       for_each_rtx (&PATTERN (insn), cse_change_cc_mode, newreg);
@@ -7797,7 +7704,7 @@ cse_cc_succs (basic_block bb, rtx cc_reg, rtx cc_src, bool can_change_mode)
                                       XEXP (SET_SRC (set), 1)))
                           
                {
-                 comp_mode = (*targetm.cc_modes_compatible) (mode, set_mode);
+                 comp_mode = targetm.cc_modes_compatible (mode, set_mode);
                  if (comp_mode != VOIDmode
                      && (can_change_mode || comp_mode == mode))
                    found = true;
@@ -7915,7 +7822,7 @@ cse_condition_code_reg (void)
   rtx cc_reg_2;
   basic_block bb;
 
-  if (! (*targetm.fixed_condition_code_regs) (&cc_regno_1, &cc_regno_2))
+  if (! targetm.fixed_condition_code_regs (&cc_regno_1, &cc_regno_2))
     return;
 
   cc_reg_1 = gen_rtx_REG (CCmode, cc_regno_1);
@@ -7996,8 +7903,22 @@ cse_condition_code_reg (void)
          if (mode != GET_MODE (cc_src))
            abort ();
          if (mode != orig_mode)
-           cse_change_cc_mode_insns (cc_src_insn, NEXT_INSN (last_insn),
-                                     gen_rtx_REG (mode, REGNO (cc_reg)));
+           {
+             rtx newreg = gen_rtx_REG (mode, REGNO (cc_reg));
+
+             /* Change the mode of CC_REG in CC_SRC_INSN to
+                GET_MODE (NEWREG).  */
+             for_each_rtx (&PATTERN (cc_src_insn), cse_change_cc_mode,
+                           newreg);
+             for_each_rtx (&REG_NOTES (cc_src_insn), cse_change_cc_mode,
+                           newreg);
+
+             /* Do the same in the following insns that use the
+                current value of CC_REG within BB.  */
+             cse_change_cc_mode_insns (NEXT_INSN (cc_src_insn),
+                                       NEXT_INSN (last_insn),
+                                       newreg);
+           }
        }
     }
 }