This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [4/9] Make mode_for_size return an opt_mode
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Richard Sandiford <richard dot sandiford at linaro dot org>
- Date: Tue, 5 Sep 2017 13:25:43 +0200
- Subject: Re: [4/9] Make mode_for_size return an opt_mode
- Authentication-results: sourceware.org; auth=none
- References: <87tw0iiu51.fsf@linaro.org> <87d176itmx.fsf@linaro.org>
On Mon, Sep 4, 2017 at 1:35 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...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.
Ok.
Richard.
> 2017-09-04 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.
>
> Index: gcc/machmode.h
> ===================================================================
> --- gcc/machmode.h 2017-09-04 12:18:47.820398622 +0100
> +++ gcc/machmode.h 2017-09-04 12:18:50.674859598 +0100
> @@ -20,6 +20,8 @@ Software Foundation; either version 3, o
> #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 @@ #define POINTER_BOUNDS_MODE_P(MODE)
>
> 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: gcc/stor-layout.c
> ===================================================================
> --- gcc/stor-layout.c 2017-09-04 12:18:44.944553324 +0100
> +++ gcc/stor-layout.c 2017-09-04 12:18:50.675762071 +0100
> @@ -291,19 +291,19 @@ finalize_size_functions (void)
> vec_free (size_functions);
> }
>
> -/* 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 m
> && 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, enu
> 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 unsi
> 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 unsi
> 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: gcc/caller-save.c
> ===================================================================
> --- gcc/caller-save.c 2017-09-04 11:49:42.884500727 +0100
> +++ gcc/caller-save.c 2017-09-04 12:18:50.672152181 +0100
> @@ -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: gcc/config/alpha/alpha.h
> ===================================================================
> --- gcc/config/alpha/alpha.h 2017-09-04 11:50:08.504926375 +0100
> +++ gcc/config/alpha/alpha.h 2017-09-04 12:18:50.672152181 +0100
> @@ -508,7 +508,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,C
> #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: gcc/config/i386/i386.h
> ===================================================================
> --- gcc/config/i386/i386.h 2017-09-04 11:50:08.515731048 +0100
> +++ gcc/config/i386/i386.h 2017-09-04 12:18:50.672152181 +0100
> @@ -1548,7 +1548,7 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
> 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: gcc/config/s390/s390.h
> ===================================================================
> --- gcc/config/s390/s390.h 2017-09-04 11:50:24.561571751 +0100
> +++ gcc/config/s390/s390.h 2017-09-04 12:18:50.673054653 +0100
> @@ -624,9 +624,9 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
>
> /* 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: gcc/config/sparc/sparc.h
> ===================================================================
> --- gcc/config/sparc/sparc.h 2017-09-04 11:50:24.563372530 +0100
> +++ gcc/config/sparc/sparc.h 2017-09-04 12:18:50.673054653 +0100
> @@ -1077,13 +1077,13 @@ #define SECONDARY_MEMORY_NEEDED(CLASS1,
> /* 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: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c 2017-09-04 11:50:08.544543511 +0100
> +++ gcc/expmed.c 2017-09-04 12:18:50.673054653 +0100
> @@ -1711,14 +1711,9 @@ extract_bit_field_1 (rtx str_rtx, unsign
>
> /* 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: gcc/reload.c
> ===================================================================
> --- gcc/reload.c 2017-09-04 11:49:42.941500722 +0100
> +++ gcc/reload.c 2017-09-04 12:18:50.675762071 +0100
> @@ -578,7 +578,8 @@ get_secondary_mem (rtx x ATTRIBUTE_UNUSE
> 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: gcc/varasm.c
> ===================================================================
> --- gcc/varasm.c 2017-09-04 11:49:42.944500722 +0100
> +++ gcc/varasm.c 2017-09-04 12:18:50.676664544 +0100
> @@ -2780,8 +2780,8 @@ assemble_integer (rtx x, unsigned int si
> 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)
> {
> Index: gcc/lower-subreg.c
> ===================================================================
> --- gcc/lower-subreg.c 2017-09-04 12:18:41.572976650 +0100
> +++ gcc/lower-subreg.c 2017-09-04 12:18:50.674859598 +0100
> @@ -616,20 +616,18 @@ simplify_subreg_concatn (machine_mode ou
> 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);
> }