Use vec<> in build_vector
[gcc.git] / gcc / combine.c
index 5eeeeda55b607b18b2de7f2d95e9a3abc52f7f30..1832c3cb2bca0c1caa115a9761263090efccf538 100644 (file)
@@ -370,7 +370,7 @@ static int label_tick_ebb_start;
 /* Mode used to compute significance in reg_stat[].nonzero_bits.  It is the
    largest integer mode that can fit in HOST_BITS_PER_WIDE_INT.  */
 
-static machine_mode nonzero_bits_mode;
+static scalar_int_mode nonzero_bits_mode;
 
 /* Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can
    be safely used.  It is zero while computing them and after combine has
@@ -414,13 +414,12 @@ static struct undobuf undobuf;
 
 static int n_occurrences;
 
-static rtx reg_nonzero_bits_for_combine (const_rtx, machine_mode, const_rtx,
-                                        machine_mode,
-                                        unsigned HOST_WIDE_INT,
+static rtx reg_nonzero_bits_for_combine (const_rtx, scalar_int_mode,
+                                        scalar_int_mode,
                                         unsigned HOST_WIDE_INT *);
-static rtx reg_num_sign_bit_copies_for_combine (const_rtx, machine_mode, const_rtx,
-                                               machine_mode,
-                                               unsigned int, unsigned int *);
+static rtx reg_num_sign_bit_copies_for_combine (const_rtx, scalar_int_mode,
+                                               scalar_int_mode,
+                                               unsigned int *);
 static void do_SUBST (rtx *, rtx);
 static void do_SUBST_INT (int *, int);
 static void init_reg_last (void);
@@ -1158,7 +1157,7 @@ combine_instructions (rtx_insn *f, unsigned int nregs)
   uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
   gcc_obstack_init (&insn_link_obstack);
 
-  nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
+  nonzero_bits_mode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
 
   /* Don't use reg_stat[].nonzero_bits when computing it.  This can cause
      problems when, for example, we have j <<= 1 in a loop.  */
@@ -2012,7 +2011,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
 
       if (REG_P (src)
          && ((REGNO (dest) < FIRST_PSEUDO_REGISTER
-              && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest)))
+              && !targetm.hard_regno_mode_ok (REGNO (dest), GET_MODE (dest)))
              /* Don't extend the life of a hard register unless it is
                 user variable (if we have few registers) or it can't
                 fit into the desired register (meaning something special
@@ -2021,7 +2020,8 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
                 reload can't handle a conflict with constraints of other
                 inputs.  */
              || (REGNO (src) < FIRST_PSEUDO_REGISTER
-                 && ! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)))))
+                 && !targetm.hard_regno_mode_ok (REGNO (src),
+                                                 GET_MODE (src)))))
        return 0;
     }
   else if (GET_CODE (dest) != CC0)
@@ -2211,8 +2211,8 @@ combinable_i3pat (rtx_insn *i3, rtx *loc, rtx i2dest, rtx i1dest, rtx i0dest,
 
          || (REG_P (inner_dest)
              && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
-             && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
-                                       GET_MODE (inner_dest))))
+             && !targetm.hard_regno_mode_ok (REGNO (inner_dest),
+                                             GET_MODE (inner_dest)))
          || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src))
          || (i0_not_in_src && reg_overlap_mentioned_p (i0dest, src)))
        return 0;
@@ -2225,9 +2225,7 @@ combinable_i3pat (rtx_insn *i3, rtx *loc, rtx i2dest, rtx i1dest, rtx i0dest,
         STACK_POINTER_REGNUM, since these are always considered to be
         live.  Similarly for ARG_POINTER_REGNUM if it is fixed.  */
       subdest = dest;
-      if (GET_CODE (subdest) == SUBREG
-         && (GET_MODE_SIZE (GET_MODE (subdest))
-             >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (subdest)))))
+      if (GET_CODE (subdest) == SUBREG && !partial_subreg_p (subdest))
        subdest = SUBREG_REG (subdest);
       if (pi3dest_killed
          && REG_P (subdest)
@@ -2457,8 +2455,8 @@ can_change_dest_mode (rtx x, int added_sets, machine_mode mode)
   /* Allow hard registers if the new mode is legal, and occupies no more
      registers than the old mode.  */
   if (regno < FIRST_PSEUDO_REGISTER)
-    return (HARD_REGNO_MODE_OK (regno, mode)
-           && REG_NREGS (x) >= hard_regno_nregs[regno][mode]);
+    return (targetm.hard_regno_mode_ok (regno, mode)
+           && REG_NREGS (x) >= hard_regno_nregs (regno, mode));
 
   /* Or a pseudo that is only used once.  */
   return (regno < reg_n_sets_max
@@ -2646,6 +2644,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
   rtx other_pat = 0;
   rtx new_other_notes;
   int i;
+  scalar_int_mode dest_mode, temp_mode;
 
   /* Immediately return if any of I0,I1,I2 are the same insn (I3 can
      never be).  */
@@ -2848,33 +2847,40 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
      constant.  */
   if (i1 == 0
       && (temp_expr = single_set (i2)) != 0
+      && is_a <scalar_int_mode> (GET_MODE (SET_DEST (temp_expr)), &temp_mode)
       && CONST_SCALAR_INT_P (SET_SRC (temp_expr))
       && GET_CODE (PATTERN (i3)) == SET
       && CONST_SCALAR_INT_P (SET_SRC (PATTERN (i3)))
       && reg_subword_p (SET_DEST (PATTERN (i3)), SET_DEST (temp_expr)))
     {
       rtx dest = SET_DEST (PATTERN (i3));
+      rtx temp_dest = SET_DEST (temp_expr);
       int offset = -1;
       int width = 0;
-      
+
       if (GET_CODE (dest) == ZERO_EXTRACT)
        {
          if (CONST_INT_P (XEXP (dest, 1))
-             && CONST_INT_P (XEXP (dest, 2)))
+             && CONST_INT_P (XEXP (dest, 2))
+             && is_a <scalar_int_mode> (GET_MODE (XEXP (dest, 0)),
+                                        &dest_mode))
            {
              width = INTVAL (XEXP (dest, 1));
              offset = INTVAL (XEXP (dest, 2));
              dest = XEXP (dest, 0);
              if (BITS_BIG_ENDIAN)
-               offset = GET_MODE_PRECISION (GET_MODE (dest)) - width - offset;
+               offset = GET_MODE_PRECISION (dest_mode) - width - offset;
            }
        }
       else
        {
          if (GET_CODE (dest) == STRICT_LOW_PART)
            dest = XEXP (dest, 0);
-         width = GET_MODE_PRECISION (GET_MODE (dest));
-         offset = 0;
+         if (is_a <scalar_int_mode> (GET_MODE (dest), &dest_mode))
+           {
+             width = GET_MODE_PRECISION (dest_mode);
+             offset = 0;
+           }
        }
 
       if (offset >= 0)
@@ -2883,9 +2889,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
          if (subreg_lowpart_p (dest))
            ;
          /* Handle the case where inner is twice the size of outer.  */
-         else if (GET_MODE_PRECISION (GET_MODE (SET_DEST (temp_expr)))
-                  == 2 * GET_MODE_PRECISION (GET_MODE (dest)))
-           offset += GET_MODE_PRECISION (GET_MODE (dest));
+         else if (GET_MODE_PRECISION (temp_mode)
+                  == 2 * GET_MODE_PRECISION (dest_mode))
+           offset += GET_MODE_PRECISION (dest_mode);
          /* Otherwise give up for now.  */
          else
            offset = -1;
@@ -2896,23 +2902,22 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
          rtx inner = SET_SRC (PATTERN (i3));
          rtx outer = SET_SRC (temp_expr);
 
-         wide_int o
-           = wi::insert (rtx_mode_t (outer, GET_MODE (SET_DEST (temp_expr))),
-                         rtx_mode_t (inner, GET_MODE (dest)),
-                         offset, width);
+         wide_int o = wi::insert (rtx_mode_t (outer, temp_mode),
+                                  rtx_mode_t (inner, dest_mode),
+                                  offset, width);
 
          combine_merges++;
          subst_insn = i3;
          subst_low_luid = DF_INSN_LUID (i2);
          added_sets_2 = added_sets_1 = added_sets_0 = 0;
-         i2dest = SET_DEST (temp_expr);
+         i2dest = temp_dest;
          i2dest_killed = dead_or_set_p (i2, i2dest);
 
          /* Replace the source in I2 with the new constant and make the
             resulting insn the new pattern for I3.  Then skip to where we
             validate the pattern.  Everything was set up above.  */
          SUBST (SET_SRC (temp_expr),
-                immed_wide_int_const (o, GET_MODE (SET_DEST (temp_expr))));
+                immed_wide_int_const (o, temp_mode));
 
          newpat = PATTERN (i2);
 
@@ -3484,7 +3489,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
      i3, and one from i2.  Combining then splitting the parallel results
      in the original i2 again plus an invalid insn (which we delete).
      The net effect is only to move instructions around, which makes
-     debug info less accurate.  */
+     debug info less accurate.
+
+     If the remaining SET came from I2 its destination should not be used
+     between I2 and I3.  See PR82024.  */
 
   if (!(added_sets_2 && i1 == 0)
       && is_parallel_of_n_reg_sets (newpat, 2)
@@ -3513,11 +3521,17 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
               && insn_nothrow_p (i3)
               && !side_effects_p (SET_SRC (set0)))
        {
-         newpat = set1;
-         insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+         rtx dest = SET_DEST (set1);
+         if (GET_CODE (dest) == SUBREG)
+           dest = SUBREG_REG (dest);
+         if (!reg_used_between_p (dest, i2, i3))
+           {
+             newpat = set1;
+             insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
 
-         if (insn_code_number >= 0)
-           changed_i3_dest = 1;
+             if (insn_code_number >= 0)
+               changed_i3_dest = 1;
+           }
        }
 
       if (insn_code_number < 0)
@@ -5433,11 +5447,11 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy)
                     FROM to CC0.  */
 
                  if (GET_CODE (to) == SUBREG
-                     && ! MODES_TIEABLE_P (GET_MODE (to),
-                                           GET_MODE (SUBREG_REG (to)))
+                     && !targetm.modes_tieable_p (GET_MODE (to),
+                                                  GET_MODE (SUBREG_REG (to)))
                      && ! (code == SUBREG
-                           && MODES_TIEABLE_P (GET_MODE (x),
-                                               GET_MODE (SUBREG_REG (to))))
+                           && (targetm.modes_tieable_p
+                               (GET_MODE (x), GET_MODE (SUBREG_REG (to)))))
                      && (!HAVE_cc0
                          || (! (code == SET
                                 && i == 1
@@ -6488,7 +6502,7 @@ simplify_if_then_else (rtx x)
       rtx cond_op0 = XEXP (cond, 0);
       rtx cond_op1 = XEXP (cond, 1);
       enum rtx_code op = UNKNOWN, extend_op = UNKNOWN;
-      machine_mode m = int_mode;
+      scalar_int_mode m = int_mode;
       rtx z = 0, c1 = NULL_RTX;
 
       if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
@@ -6876,10 +6890,8 @@ simplify_set (rtx x)
   /* If we have (set (cc0) (subreg ...)), we try to remove the subreg
      in SRC.  */
   if (dest == cc0_rtx
-      && GET_CODE (src) == SUBREG
-      && subreg_lowpart_p (src)
-      && (GET_MODE_PRECISION (GET_MODE (src))
-         < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (src)))))
+      && partial_subreg_p (src)
+      && subreg_lowpart_p (src))
     {
       rtx inner = SUBREG_REG (src);
       machine_mode inner_mode = GET_MODE (inner);
@@ -7421,9 +7433,9 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
      ignore the POS lowest bits, etc.  */
   machine_mode is_mode = GET_MODE (inner);
   machine_mode inner_mode;
-  machine_mode wanted_inner_mode;
-  machine_mode wanted_inner_reg_mode = word_mode;
-  machine_mode pos_mode = word_mode;
+  scalar_int_mode wanted_inner_mode;
+  scalar_int_mode wanted_inner_reg_mode = word_mode;
+  scalar_int_mode pos_mode = word_mode;
   machine_mode extraction_mode = word_mode;
   rtx new_rtx = 0;
   rtx orig_pos_rtx = pos_rtx;
@@ -7628,7 +7640,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   /* Never narrow an object, since that might not be safe.  */
 
   if (mode != VOIDmode
-      && GET_MODE_SIZE (extraction_mode) < GET_MODE_SIZE (mode))
+      && partial_subreg_p (extraction_mode, mode))
     extraction_mode = mode;
 
   if (!MEM_P (inner))
@@ -7675,7 +7687,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   if (wanted_inner_mode != VOIDmode
       && inner_mode != wanted_inner_mode
       && ! pos_rtx
-      && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode)
+      && partial_subreg_p (wanted_inner_mode, is_mode)
       && MEM_P (inner)
       && ! mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner))
       && ! MEM_VOLATILE_P (inner))
@@ -7964,8 +7976,8 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
          && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
        {
          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);
+         new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1),
+                                    i, 1, 0, in_code == COMPARE);
        }
 
       /* Same as previous, but for (subreg (lshiftrt ...)) in first op.  */
@@ -8004,10 +8016,10 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
        {
          /* Apply the distributive law, and then try to make extractions.  */
          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)));
+                                   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_rtx = make_compound_operation (new_rtx, in_code);
        }
 
@@ -8021,9 +8033,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
        {
          new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
          new_rtx = make_extraction (mode, new_rtx,
-                                (GET_MODE_PRECISION (mode)
-                                 - INTVAL (XEXP (XEXP (x, 0), 1))),
-                                NULL_RTX, i, 1, 0, in_code == COMPARE);
+                                    (GET_MODE_PRECISION (mode)
+                                     - INTVAL (XEXP (XEXP (x, 0), 1))),
+                                    NULL_RTX, i, 1, 0, in_code == COMPARE);
        }
 
       /* On machines without logical shifts, if the operand of the AND is
@@ -8043,8 +8055,10 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
          if ((INTVAL (XEXP (x, 1)) & ~mask) == 0)
            SUBST (XEXP (x, 0),
                   gen_rtx_ASHIFTRT (mode,
-                                    make_compound_operation
-                                    (XEXP (XEXP (x, 0), 0), next_code),
+                                    make_compound_operation (XEXP (XEXP (x,
+                                                                         0),
+                                                                   0),
+                                                             next_code),
                                     XEXP (XEXP (x, 0), 1)));
        }
 
@@ -8054,9 +8068,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
         we are in a COMPARE.  */
       else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
        new_rtx = make_extraction (mode,
-                              make_compound_operation (XEXP (x, 0),
-                                                       next_code),
-                              0, NULL_RTX, i, 1, 0, in_code == COMPARE);
+                                  make_compound_operation (XEXP (x, 0),
+                                                           next_code),
+                                  0, NULL_RTX, i, 1, 0, in_code == COMPARE);
 
       /* If we are in a comparison and this is an AND with a power of two,
         convert this into the appropriate bit extract.  */
@@ -8107,9 +8121,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
          && (nonzero_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0)
        {
          new_rtx = gen_rtx_ASHIFTRT (mode,
-                                 make_compound_operation (XEXP (x, 0),
-                                                          next_code),
-                                 XEXP (x, 1));
+                                     make_compound_operation (XEXP (x, 0),
+                                                              next_code),
+                                     XEXP (x, 1));
          break;
        }
 
@@ -8130,9 +8144,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
        {
          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);
+                                    INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
+                                    NULL_RTX, mode_width - INTVAL (rhs),
+                                    code == LSHIFTRT, 0, in_code == COMPARE);
          break;
        }
 
@@ -8149,9 +8163,10 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
          && INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
          && INTVAL (rhs) < mode_width
          && (new_rtx = extract_left_shift (mode, 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);
+       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);
 
       break;
 
@@ -8195,7 +8210,7 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
                   to (subreg:QI (lshiftrt:SI (reg:SI) (const_int 7)) 0).  */
                || (GET_CODE (inner) == AND
                    && CONST_INT_P (XEXP (inner, 1))
-                   && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+                   && partial_subreg_p (x)
                    && exact_log2 (UINTVAL (XEXP (inner, 1)))
                       >= GET_MODE_BITSIZE (mode) - 1)))
          subreg_code = SET;
@@ -8208,7 +8223,7 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
          tem = simplified;
 
        if (GET_CODE (tem) != GET_CODE (inner)
-           && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+           && partial_subreg_p (x)
            && subreg_lowpart_p (x))
          {
            rtx newer
@@ -8219,8 +8234,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
            if (GET_CODE (newer) != SUBREG)
              newer = make_compound_operation (newer, in_code);
 
-           /* force_to_mode can expand compounds.  If it just re-expanded the
-              compound, use gen_lowpart to convert to the desired mode.  */
+           /* force_to_mode can expand compounds.  If it just re-expanded
+              the compound, use gen_lowpart to convert to the desired
+              mode.  */
            if (rtx_equal_p (newer, x)
                /* Likewise if it re-expanded the compound only partially.
                   This happens for SUBREG of ZERO_EXTRACT if they extract
@@ -8462,7 +8478,7 @@ static rtx
 gen_lowpart_or_truncate (machine_mode mode, rtx x)
 {
   if (!CONST_INT_P (x)
-      && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))
+      && partial_subreg_p (mode, GET_MODE (x))
       && !TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x))
       && !(REG_P (x) && reg_truncated_to_mode (mode, x)))
     {
@@ -8517,7 +8533,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
   /* It is not valid to do a right-shift in a narrower mode
      than the one it came in with.  */
   if ((code == LSHIFTRT || code == ASHIFTRT)
-      && GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (x)))
+      && partial_subreg_p (mode, GET_MODE (x)))
     op_mode = GET_MODE (x);
 
   /* Truncate MASK to fit OP_MODE.  */
@@ -8554,8 +8570,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
      if the constant masks to zero all the bits the mode doesn't have.  */
   if (GET_CODE (x) == SUBREG
       && subreg_lowpart_p (x)
-      && ((GET_MODE_SIZE (GET_MODE (x))
-          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+      && (partial_subreg_p (x)
          || (0 == (mask
                    & GET_MODE_MASK (GET_MODE (x))
                    & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))))))
@@ -9549,8 +9564,7 @@ make_field_assignment (rtx x)
 
   if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG
       && subreg_lowpart_p (XEXP (src, 0))
-      && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
-         < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0)))))
+      && partial_subreg_p (XEXP (src, 0))
       && GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE
       && CONST_INT_P (XEXP (SUBREG_REG (XEXP (src, 0)), 0))
       && INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2
@@ -10035,17 +10049,15 @@ simplify_and_const_int (rtx x, scalar_int_mode mode, rtx varop,
   return x;
 }
 \f
-/* Given a REG, X, compute which bits in X can be nonzero.
+/* Given a REG X of mode XMODE, compute which bits in X can be nonzero.
    We don't care about bits outside of those defined in MODE.
 
    For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
    a shift, AND, or zero_extract, we can do better.  */
 
 static rtx
-reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
-                             const_rtx known_x ATTRIBUTE_UNUSED,
-                             machine_mode known_mode ATTRIBUTE_UNUSED,
-                             unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
+reg_nonzero_bits_for_combine (const_rtx x, scalar_int_mode xmode,
+                             scalar_int_mode mode,
                              unsigned HOST_WIDE_INT *nonzero)
 {
   rtx tem;
@@ -10086,8 +10098,7 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
   if (tem)
     {
       if (SHORT_IMMEDIATES_SIGN_EXTEND)
-       tem = sign_extend_short_imm (tem, GET_MODE (x),
-                                    GET_MODE_PRECISION (mode));
+       tem = sign_extend_short_imm (tem, xmode, GET_MODE_PRECISION (mode));
 
       return tem;
     }
@@ -10096,9 +10107,9 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
     {
       unsigned HOST_WIDE_INT mask = rsp->nonzero_bits;
 
-      if (GET_MODE_PRECISION (GET_MODE (x)) < GET_MODE_PRECISION (mode))
+      if (GET_MODE_PRECISION (xmode) < GET_MODE_PRECISION (mode))
        /* We don't know anything about the upper bits.  */
-       mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (GET_MODE (x));
+       mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (xmode);
 
       *nonzero &= mask;
     }
@@ -10106,17 +10117,14 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
   return NULL;
 }
 
-/* Return the number of bits at the high-order end of X that are known to
-   be equal to the sign bit.  X will be used in mode MODE; if MODE is
-   VOIDmode, X will be used in its own mode.  The returned value  will always
-   be between 1 and the number of bits in MODE.  */
+/* Given a reg X of mode XMODE, return the number of bits at the high-order
+   end of X that are known to be equal to the sign bit.  X will be used
+   in mode MODE; the returned value will always be between 1 and the
+   number of bits in MODE.  */
 
 static rtx
-reg_num_sign_bit_copies_for_combine (const_rtx x, machine_mode mode,
-                                    const_rtx known_x ATTRIBUTE_UNUSED,
-                                    machine_mode known_mode
-                                    ATTRIBUTE_UNUSED,
-                                    unsigned int known_ret ATTRIBUTE_UNUSED,
+reg_num_sign_bit_copies_for_combine (const_rtx x, scalar_int_mode xmode,
+                                    scalar_int_mode mode,
                                     unsigned int *result)
 {
   rtx tem;
@@ -10145,7 +10153,7 @@ reg_num_sign_bit_copies_for_combine (const_rtx x, machine_mode mode,
     return tem;
 
   if (nonzero_sign_valid && rsp->sign_bit_copies != 0
-      && GET_MODE_PRECISION (GET_MODE (x)) == GET_MODE_PRECISION (mode))
+      && GET_MODE_PRECISION (xmode) == GET_MODE_PRECISION (mode))
     *result = rsp->sign_bit_copies;
 
   return NULL;
@@ -10316,9 +10324,9 @@ merge_outer_ops (enum rtx_code *pop0, HOST_WIDE_INT *pconst0, enum rtx_code op1,
    result of the shift is subject to operation OUTER_CODE with operand
    OUTER_CONST.  */
 
-static machine_mode
+static scalar_int_mode
 try_widen_shift_mode (enum rtx_code code, rtx op, int count,
-                     machine_mode orig_mode, machine_mode mode,
+                     scalar_int_mode orig_mode, scalar_int_mode mode,
                      enum rtx_code outer_code, HOST_WIDE_INT outer_const)
 {
   gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode));
@@ -13325,7 +13333,7 @@ reg_truncated_to_mode (machine_mode mode, const_rtx x)
   if (truncated == 0
       || rsp->truncation_label < label_tick_ebb_start)
     return false;
-  if (GET_MODE_SIZE (truncated) <= GET_MODE_SIZE (mode))
+  if (!partial_subreg_p (mode, truncated))
     return true;
   if (TRULY_NOOP_TRUNCATION_MODES_P (mode, truncated))
     return true;
@@ -13348,9 +13356,10 @@ record_truncated_value (rtx x)
       machine_mode original_mode = GET_MODE (SUBREG_REG (x));
       truncated_mode = GET_MODE (x);
 
-      if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
+      if (!partial_subreg_p (truncated_mode, original_mode))
        return true;
 
+      truncated_mode = GET_MODE (x);
       if (TRULY_NOOP_TRUNCATION_MODES_P (truncated_mode, original_mode))
        return true;
 
@@ -13366,8 +13375,7 @@ record_truncated_value (rtx x)
   rsp = &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 (rsp->truncated_to_mode)))
+      || partial_subreg_p (truncated_mode, rsp->truncated_to_mode))
     {
       rsp->truncated_to_mode = truncated_mode;
       rsp->truncation_label = label_tick;
@@ -13891,8 +13899,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
             the remaining registers in place of NOTE.  */
 
          if (note != 0 && regno < FIRST_PSEUDO_REGISTER
-             && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
-                 > GET_MODE_SIZE (GET_MODE (x))))
+             && partial_subreg_p (GET_MODE (x), GET_MODE (XEXP (note, 0))))
            {
              unsigned int deadregno = REGNO (XEXP (note, 0));
              unsigned int deadend = END_REGNO (XEXP (note, 0));
@@ -13911,8 +13918,8 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
             their own REG_DEAD notes lying around.  */
          else if ((note == 0
                    || (note != 0
-                       && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
-                           < GET_MODE_SIZE (GET_MODE (x)))))
+                       && partial_subreg_p (GET_MODE (XEXP (note, 0)),
+                                            GET_MODE (x))))
                   && regno < FIRST_PSEUDO_REGISTER
                   && REG_NREGS (x) > 1)
            {
@@ -13921,7 +13928,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
              rtx oldnotes = 0;
 
              if (note)
-               offset = hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))];
+               offset = hard_regno_nregs (regno, GET_MODE (XEXP (note, 0)));
              else
                offset = 1;
 
@@ -14533,7 +14540,7 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
                         not already dead or set.  */
 
                      for (i = regno; i < endregno;
-                          i += hard_regno_nregs[i][reg_raw_mode[i]])
+                          i += hard_regno_nregs (i, reg_raw_mode[i]))
                        {
                          rtx piece = regno_reg_rtx[i];
                          basic_block bb = this_basic_block;