Make mode_for_size return an opt_mode
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 5 Sep 2017 19:57:18 +0000 (19:57 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 5 Sep 2017 19:57:18 +0000 (19:57 +0000)
...to make it consistent with int_mode_for_size etc.

require () seems like the right choice in replace_reg_with_saved_mem
because we use the chosen mode for saving and restoring registers,
which cannot be done in BLKmode.  Similarly require () seems like
the right choice in calls related to secondary memory reloads (the ones
in config/, and in get_secondary_mem) because the reload must always
have a defined mode, which e.g. determines the size of the slot.

We can use require () in simplify_subreg_concatn and assemble_integer
because it isn't meaningful to create a subreg with BLKmode (for one
thing, we couldn't tell then whether it was partial, paradoxical, etc.).

make_fract_type and make_accum_type must find a mode because that's
what distinguishes accumulator FIXED_POINT_TYPEs from fractional
FIXED_POINT_TYPEs.

2017-09-05  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* machmode.h (opt_machine_mode): New type.
(opt_mode<T>): Allow construction from anything that can be
converted to a T.
(is_a, as_a, dyn_cast): Add overloads for opt_mode.
(mode_for_size): Return an opt_machine_mode.
* stor-layout.c (mode_for_size): Likewise.
(mode_for_size_tree): Update call accordingly.
(bitwise_mode_for_mode): Likewise.
(make_fract_type): Likewise.
(make_accum_type): Likewise.
* caller-save.c (replace_reg_with_saved_mem): Update call
accordingly.
* config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
* config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
* config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
* config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
* expmed.c (extract_bit_field_1): Likewise.
* reload.c (get_secondary_mem): Likewise.
* varasm.c (assemble_integer): Likewise.
* lower-subreg.c (simplify_subreg_concatn): Likewise.  Move
early-out.

From-SVN: r251728

12 files changed:
gcc/ChangeLog
gcc/caller-save.c
gcc/config/alpha/alpha.h
gcc/config/i386/i386.h
gcc/config/s390/s390.h
gcc/config/sparc/sparc.h
gcc/expmed.c
gcc/lower-subreg.c
gcc/machmode.h
gcc/reload.c
gcc/stor-layout.c
gcc/varasm.c

index 7fbade74ed75ac18dfc14346cae5f9fa58163f81..4a7f676a1437080994f18c0d351b15f47c66cac4 100644 (file)
@@ -1,3 +1,27 @@
+2017-09-05  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * machmode.h (opt_machine_mode): New type.
+       (opt_mode<T>): Allow construction from anything that can be
+       converted to a T.
+       (is_a, as_a, dyn_cast): Add overloads for opt_mode.
+       (mode_for_size): Return an opt_machine_mode.
+       * stor-layout.c (mode_for_size): Likewise.
+       (mode_for_size_tree): Update call accordingly.
+       (bitwise_mode_for_mode): Likewise.
+       (make_fract_type): Likewise.
+       (make_accum_type): Likewise.
+       * caller-save.c (replace_reg_with_saved_mem): Update call
+       accordingly.
+       * config/alpha/alpha.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
+       * config/i386/i386.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
+       * config/s390/s390.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
+       * config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED_MODE): Likewise.
+       * expmed.c (extract_bit_field_1): Likewise.
+       * reload.c (get_secondary_mem): Likewise.
+       * varasm.c (assemble_integer): Likewise.
+       * lower-subreg.c (simplify_subreg_concatn): Likewise.  Move
+       early-out.
+
 2017-09-05  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * machmode.h (decimal_float_mode_for_size): New function.
index 5e6b92b0b8d4fe0fcfd242c7492a81bfe155c545..619dac9a6894b0645db89ea9c0d3c7a81eb51c46 100644 (file)
@@ -1161,7 +1161,7 @@ replace_reg_with_saved_mem (rtx *loc,
            gcc_assert (smode != VOIDmode);
            if (hard_regno_nregs [regno][smode] > 1)
              smode = mode_for_size (GET_MODE_SIZE (mode) / nregs,
-                                    GET_MODE_CLASS (mode), 0);
+                                    GET_MODE_CLASS (mode), 0).require ();
            XVECEXP (mem, 0, i) = gen_rtx_REG (smode, regno + i);
          }
     }
index b9fee20ef6528e137bdd20c849e2ff367a769da5..8bca5b3408b61c712a60df50c2c3894704cca2ac 100644 (file)
@@ -508,7 +508,7 @@ enum reg_class {
 #define SECONDARY_MEMORY_NEEDED_MODE(MODE)             \
   (GET_MODE_CLASS (MODE) == MODE_FLOAT ? (MODE)                \
    : GET_MODE_SIZE (MODE) >= 4 ? (MODE)                        \
-   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0))
+   : mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require ())
 
 /* Return the class of registers that cannot change mode from FROM to TO.  */
 
index 8f9a2ad4d7309d1d16f2c04601147590cd5a5366..873122caa2b86602aad2980c8fcae08959a07fdb 100644 (file)
@@ -1548,7 +1548,7 @@ enum reg_class
    for integral modes that can be moved using 32 bit move.  */
 #define SECONDARY_MEMORY_NEEDED_MODE(MODE)                     \
   (GET_MODE_BITSIZE (MODE) < 32 && INTEGRAL_MODE_P (MODE)      \
-   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)              \
+   ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()   \
    : MODE)
 
 /* Return a class of registers that cannot change FROM mode to TO mode.  */
index 34fffb4a277eee8a977fe6fa21e7f8d624d31401..a52f866628af664556ec5668d849f5ba34e0c7ab 100644 (file)
@@ -624,9 +624,9 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
 
 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
    because the movsi and movsf patterns don't handle r/f moves.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE)             \
- (GET_MODE_BITSIZE (MODE) < 32                         \
-  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)       \
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE)                     \
+ (GET_MODE_BITSIZE (MODE) < 32                                 \
+  ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()    \
   : (MODE))
 
 
index 36f7667100eca31d84f8b0bc919640d26419500f..3c71a3fe1566a3698be0f99a22d1da24f71f9e3f 100644 (file)
@@ -1077,13 +1077,13 @@ extern char leaf_reg_remap[];
 /* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
    because the movsi and movsf patterns don't handle r/f moves.
    For v8 we copy the default definition.  */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
-  (TARGET_ARCH64                                               \
-   ? (GET_MODE_BITSIZE (MODE) < 32                             \
-      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0)           \
-      : MODE)                                                  \
-   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD                  \
-      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0)        \
+#define SECONDARY_MEMORY_NEEDED_MODE(MODE)                                \
+  (TARGET_ARCH64                                                          \
+   ? (GET_MODE_BITSIZE (MODE) < 32                                        \
+      ? mode_for_size (32, GET_MODE_CLASS (MODE), 0).require ()                   \
+      : MODE)                                                             \
+   : (GET_MODE_BITSIZE (MODE) < BITS_PER_WORD                             \
+      ? mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (MODE), 0).require () \
       : MODE))
 
 /* Return the maximum number of consecutive registers
index fa223165e906763631cd903fc54bba1cfe58c63f..894e3698b32997730e902281f2b1a7e531d3e9c5 100644 (file)
@@ -1711,14 +1711,9 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Get the mode of the field to use for atomic access or subreg
      conversion.  */
-  mode1 = mode;
-  if (SCALAR_INT_MODE_P (tmode))
-    {
-      machine_mode try_mode = mode_for_size (bitsize,
-                                                 GET_MODE_CLASS (tmode), 0);
-      if (try_mode != BLKmode)
-       mode1 = try_mode;
-    }
+  if (!SCALAR_INT_MODE_P (tmode)
+      || !mode_for_size (bitsize, GET_MODE_CLASS (tmode), 0).exists (&mode1))
+    mode1 = mode;
   gcc_assert (mode1 != BLKmode);
 
   /* Extraction of a full MODE1 value can be done with a subreg as long
index 43b6cd0f6500cc1b32c800b4da92c67a1ea53693..e34746b3fe4a66f472692299db53b6d452dea95c 100644 (file)
@@ -616,20 +616,18 @@ simplify_subreg_concatn (machine_mode outermode, rtx op,
   part = XVECEXP (op, 0, byte / inner_size);
   partmode = GET_MODE (part);
 
+  final_offset = byte % inner_size;
+  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
+    return NULL_RTX;
+
   /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of
      regular CONST_VECTORs.  They have vector or integer modes, depending
      on the capabilities of the target.  Cope with them.  */
   if (partmode == VOIDmode && VECTOR_MODE_P (innermode))
     partmode = GET_MODE_INNER (innermode);
   else if (partmode == VOIDmode)
-    {
-      enum mode_class mclass = GET_MODE_CLASS (innermode);
-      partmode = mode_for_size (inner_size * BITS_PER_UNIT, mclass, 0);
-    }
-
-  final_offset = byte % inner_size;
-  if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
-    return NULL_RTX;
+    partmode = mode_for_size (inner_size * BITS_PER_UNIT,
+                             GET_MODE_CLASS (innermode), 0).require ();
 
   return simplify_gen_subreg (outermode, part, partmode, final_offset);
 }
index d8344a9636996716a7057007dbc8a1c0dbecaffe..956e2c086f164242678e043f9b8e938c2e97cabb 100644 (file)
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef HAVE_MACHINE_MODES
 #define HAVE_MACHINE_MODES
 
+typedef opt_mode<machine_mode> opt_machine_mode;
+
 extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
 extern const unsigned short mode_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_inner[NUM_MACHINE_MODES];
@@ -237,6 +239,8 @@ public:
 
   ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
   ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
+  template<typename U>
+  ALWAYS_INLINE opt_mode (const U &m) : m_mode (T (m)) {}
   ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
 
   machine_mode else_void () const;
@@ -325,6 +329,13 @@ is_a (machine_mode m)
   return T::includes_p (m);
 }
 
+template<typename T, typename U>
+inline bool
+is_a (const opt_mode<U> &m)
+{
+  return T::includes_p (m.else_void ());
+}
+
 /* Assert that mode M has type T, and return it in that form.  */
 
 template<typename T>
@@ -335,6 +346,13 @@ as_a (machine_mode m)
   return typename mode_traits<T>::from_int (m);
 }
 
+template<typename T, typename U>
+inline T
+as_a (const opt_mode<U> &m)
+{
+  return as_a <T> (m.else_void ());
+}
+
 /* Convert M to an opt_mode<T>.  */
 
 template<typename T>
@@ -346,6 +364,13 @@ dyn_cast (machine_mode m)
   return opt_mode<T> ();
 }
 
+template<typename T, typename U>
+inline opt_mode<T>
+dyn_cast (const opt_mode<U> &m)
+{
+  return dyn_cast <T> (m.else_void ());
+}
+
 /* Return true if mode M has type T, storing it as a T in *RESULT
    if so.  */
 
@@ -627,11 +652,7 @@ GET_MODE_2XWIDER_MODE (const T &m)
 extern const unsigned char mode_complex[NUM_MACHINE_MODES];
 #define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
 
-/* Return the mode for data of a given size SIZE and mode class CLASS.
-   If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
-   The value is BLKmode if no other mode is found.  */
-
-extern machine_mode mode_for_size (unsigned int, enum mode_class, int);
+extern opt_machine_mode mode_for_size (unsigned int, enum mode_class, int);
 
 /* Return the machine mode to use for a MODE_INT of SIZE bits, if one
    exists.  If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
index f10a88b3e90c03cd823cb948deb767d4d9397e2b..9d96700209ff0da12146c479edc3e9c2128df6da 100644 (file)
@@ -578,7 +578,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSED, machine_mode mode,
   mode = SECONDARY_MEMORY_NEEDED_MODE (mode);
 #else
   if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD && INTEGRAL_MODE_P (mode))
-    mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
+    mode = mode_for_size (BITS_PER_WORD,
+                         GET_MODE_CLASS (mode), 0).require ();
 #endif
 
   /* If we already have made a MEM for this operand in MODE, return it.  */
index 27a1eba497568e2cc6b62db86846f6f494c08f43..f9a28e7c849636ea1bf0a14fb07d37be4c458f27 100644 (file)
@@ -291,19 +291,19 @@ finalize_size_functions (void)
   vec_free (size_functions);
 }
 \f
-/* Return the machine mode to use for a nonscalar of SIZE bits.  The
-   mode must be in class MCLASS, and have exactly that many value bits;
-   it may have padding as well.  If LIMIT is nonzero, modes of wider
-   than MAX_FIXED_MODE_SIZE will not be used.  */
+/* Return a machine mode of class MCLASS with SIZE bits of precision,
+   if one exists.  The mode may have padding bits as well the SIZE
+   value bits.  If LIMIT is nonzero, disregard modes wider than
+   MAX_FIXED_MODE_SIZE.  */
 
-machine_mode
+opt_machine_mode
 mode_for_size (unsigned int size, enum mode_class mclass, int limit)
 {
   machine_mode mode;
   int i;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
-    return BLKmode;
+    return opt_machine_mode ();
 
   /* Get the first mode which has this size, in the specified class.  */
   FOR_EACH_MODE_IN_CLASS (mode, mclass)
@@ -316,7 +316,7 @@ mode_for_size (unsigned int size, enum mode_class mclass, int limit)
          && int_n_enabled_p[i])
        return int_n_data[i].m;
 
-  return BLKmode;
+  return opt_machine_mode ();
 }
 
 /* Similar, except passed a tree node.  */
@@ -333,11 +333,11 @@ mode_for_size_tree (const_tree size, enum mode_class mclass, int limit)
   ui = uhwi;
   if (uhwi != ui)
     return BLKmode;
-  return mode_for_size (ui, mclass, limit);
+  return mode_for_size (ui, mclass, limit).else_blk ();
 }
 
-/* Similar, but never return BLKmode; return the narrowest mode that
-   contains at least the requested number of value bits.  */
+/* Return the narrowest mode of class MCLASS that contains at least
+   SIZE bits.  Abort if no such mode exists.  */
 
 machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class mclass)
@@ -426,9 +426,8 @@ bitwise_mode_for_mode (machine_mode mode)
   if (COMPLEX_MODE_P (mode))
     {
       machine_mode trial = mode;
-      if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT)
-       trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_COMPLEX_INT
+          || mode_for_size (bitsize, MODE_COMPLEX_INT, false).exists (&trial))
          && have_regs_of_mode[GET_MODE_INNER (trial)])
        return trial;
     }
@@ -438,16 +437,15 @@ bitwise_mode_for_mode (machine_mode mode)
   if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE)
     {
       machine_mode trial = mode;
-      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
-       trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0);
-      if (trial != BLKmode
+      if ((GET_MODE_CLASS (trial) == MODE_VECTOR_INT
+          || mode_for_size (bitsize, MODE_VECTOR_INT, 0).exists (&trial))
          && have_regs_of_mode[trial]
          && targetm.vector_mode_supported_p (trial))
        return trial;
     }
 
   /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE.  */
-  return mode_for_size (bitsize, MODE_INT, true);
+  return mode_for_size (bitsize, MODE_INT, true).else_blk ();
 }
 
 /* Find a type that can be used for efficient bitwise operations on MODE.
@@ -2543,13 +2541,9 @@ make_fract_type (int precision, int unsignedp, int satp)
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UFRACT, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_FRACT, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
@@ -2569,13 +2563,9 @@ make_accum_type (int precision, int unsignedp, int satp)
     TYPE_SATURATING (type) = 1;
 
   /* Lay out the type: set its alignment, size, etc.  */
-  if (unsignedp)
-    {
-      TYPE_UNSIGNED (type) = 1;
-      SET_TYPE_MODE (type, mode_for_size (precision, MODE_UACCUM, 0));
-    }
-  else
-    SET_TYPE_MODE (type, mode_for_size (precision, MODE_ACCUM, 0));
+  TYPE_UNSIGNED (type) = unsignedp;
+  enum mode_class mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
+  SET_TYPE_MODE (type, mode_for_size (precision, mclass, 0).require ());
   layout_type (type);
 
   return type;
index 476efcfb786fc19166b6b5ffb7f6f6c59b5ecfdd..f2a12f0495f229ac608cc21cf88aae980eaea416 100644 (file)
@@ -2780,8 +2780,8 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
       else
        mclass = MODE_INT;
 
-      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0);
-      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0);
+      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0).require ();
+      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0).require ();
 
       for (i = 0; i < size; i += subsize)
        {