Message ID | 87y3o2w1l7.fsf@linaro.org |
---|---|
State | New |
Headers | show |
Series | [08/nn] Add a fixed_size_mode class | expand |
On Mon, Oct 23, 2017 at 1:22 PM, Richard Sandiford <richard.sandiford@linaro.org> wrote: > This patch adds a fixed_size_mode machine_mode wrapper > for modes that are known to have a fixed size. That applies > to all current modes, but future patches will add support for > variable-sized modes. > > The use of this class should be pretty restricted. One important > use case is to hold the mode of static data, which can never be > variable-sized with current file formats. Another is to hold > the modes of registers involved in __builtin_apply and > __builtin_result, since those interfaces don't cope well with > variable-sized data. > > The class can also be useful when reinterpreting the contents of > a fixed-length bit string as a different kind of value. Ok. Richard. > > 2017-10-23 Richard Sandiford <richard.sandiford@linaro.org> > Alan Hayward <alan.hayward@arm.com> > David Sherwood <david.sherwood@arm.com> > > gcc/ > * machmode.h (fixed_size_mode): New class. > * rtl.h (get_pool_mode): Return fixed_size_mode. > * gengtype.c (main): Add fixed_size_mode. > * target.def (get_raw_result_mode): Return a fixed_size_mode. > (get_raw_arg_mode): Likewise. > * doc/tm.texi: Regenerate. > * targhooks.h (default_get_reg_raw_mode): Return a fixed_size_mode. > * targhooks.c (default_get_reg_raw_mode): Likewise. > * config/ia64/ia64.c (ia64_get_reg_raw_mode): Likewise. > * config/mips/mips.c (mips_get_reg_raw_mode): Likewise. > * config/msp430/msp430.c (msp430_get_raw_arg_mode): Likewise. > (msp430_get_raw_result_mode): Likewise. > * config/avr/avr-protos.h (regmask): Use as_a <fixed_side_mode> > * dbxout.c (dbxout_parms): Require fixed-size modes. > * expr.c (copy_blkmode_from_reg, copy_blkmode_to_reg): Likewise. > * gimple-ssa-store-merging.c (encode_tree_to_bitpos): Likewise. > * omp-low.c (lower_oacc_reductions): Likewise. > * simplify-rtx.c (simplify_immed_subreg): Take fixed_size_modes. > (simplify_subreg): Update accordingly. > * varasm.c (constant_descriptor_rtx::mode): Change to fixed_size_mode. > (force_const_mem): Update accordingly. Return NULL_RTX for modes > that aren't fixed-size. > (get_pool_mode): Return a fixed_size_mode. > (output_constant_pool_2): Take a fixed_size_mode. > > Index: gcc/machmode.h > =================================================================== > --- gcc/machmode.h 2017-09-15 14:47:33.184331588 +0100 > +++ gcc/machmode.h 2017-10-23 11:42:52.014721093 +0100 > @@ -652,6 +652,39 @@ 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]) > > +/* Represents a machine mode that must have a fixed size. The main > + use of this class is to represent the modes of objects that always > + have static storage duration, such as constant pool entries. > + (No current target supports the concept of variable-size static data.) */ > +class fixed_size_mode > +{ > +public: > + typedef mode_traits<fixed_size_mode>::from_int from_int; > + > + ALWAYS_INLINE fixed_size_mode () {} > + ALWAYS_INLINE fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {} > + ALWAYS_INLINE fixed_size_mode (const scalar_mode &m) : m_mode (m) {} > + ALWAYS_INLINE fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {} > + ALWAYS_INLINE fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {} > + ALWAYS_INLINE fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {} > + ALWAYS_INLINE fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {} > + ALWAYS_INLINE fixed_size_mode (const complex_mode &m) : m_mode (m) {} > + ALWAYS_INLINE operator machine_mode () const { return m_mode; } > + > + static bool includes_p (machine_mode); > + > +protected: > + machine_mode m_mode; > +}; > + > +/* Return true if MODE has a fixed size. */ > + > +inline bool > +fixed_size_mode::includes_p (machine_mode) > +{ > + return true; > +} > + > 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 > Index: gcc/rtl.h > =================================================================== > --- gcc/rtl.h 2017-10-23 11:42:47.297720974 +0100 > +++ gcc/rtl.h 2017-10-23 11:42:52.015721094 +0100 > @@ -3020,7 +3020,7 @@ extern rtx force_const_mem (machine_mode > struct function; > extern rtx get_pool_constant (const_rtx); > extern rtx get_pool_constant_mark (rtx, bool *); > -extern machine_mode get_pool_mode (const_rtx); > +extern fixed_size_mode get_pool_mode (const_rtx); > extern rtx simplify_subtraction (rtx); > extern void decide_function_section (tree); > > Index: gcc/gengtype.c > =================================================================== > --- gcc/gengtype.c 2017-05-23 19:29:56.919436344 +0100 > +++ gcc/gengtype.c 2017-10-23 11:42:52.014721093 +0100 > @@ -5197,6 +5197,7 @@ #define POS_HERE(Call) do { pos.file = t > POS_HERE (do_scalar_typedef ("JCF_u2", &pos)); > POS_HERE (do_scalar_typedef ("void", &pos)); > POS_HERE (do_scalar_typedef ("machine_mode", &pos)); > + POS_HERE (do_scalar_typedef ("fixed_size_mode", &pos)); > POS_HERE (do_typedef ("PTR", > create_pointer (resolve_typedef ("void", &pos)), > &pos)); > Index: gcc/target.def > =================================================================== > --- gcc/target.def 2017-10-23 11:41:23.134456913 +0100 > +++ gcc/target.def 2017-10-23 11:42:52.017721094 +0100 > @@ -5021,7 +5021,7 @@ DEFHOOK > "This target hook returns the mode to be used when accessing raw return\ > registers in @code{__builtin_return}. Define this macro if the value\ > in @var{reg_raw_mode} is not correct.", > - machine_mode, (int regno), > + fixed_size_mode, (int regno), > default_get_reg_raw_mode) > > /* Return a mode wide enough to copy any argument value that might be > @@ -5031,7 +5031,7 @@ DEFHOOK > "This target hook returns the mode to be used when accessing raw argument\ > registers in @code{__builtin_apply_args}. Define this macro if the value\ > in @var{reg_raw_mode} is not correct.", > - machine_mode, (int regno), > + fixed_size_mode, (int regno), > default_get_reg_raw_mode) > > HOOK_VECTOR_END (calls) > Index: gcc/doc/tm.texi > =================================================================== > --- gcc/doc/tm.texi 2017-10-23 11:41:22.175925023 +0100 > +++ gcc/doc/tm.texi 2017-10-23 11:42:52.012721093 +0100 > @@ -4536,11 +4536,11 @@ This macro has effect in @option{-fpcc-s > nothing when you use @option{-freg-struct-return} mode. > @end defmac > > -@deftypefn {Target Hook} machine_mode TARGET_GET_RAW_RESULT_MODE (int @var{regno}) > +@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_RESULT_MODE (int @var{regno}) > This target hook returns the mode to be used when accessing raw return registers in @code{__builtin_return}. Define this macro if the value in @var{reg_raw_mode} is not correct. > @end deftypefn > > -@deftypefn {Target Hook} machine_mode TARGET_GET_RAW_ARG_MODE (int @var{regno}) > +@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_ARG_MODE (int @var{regno}) > This target hook returns the mode to be used when accessing raw argument registers in @code{__builtin_apply_args}. Define this macro if the value in @var{reg_raw_mode} is not correct. > @end deftypefn > > Index: gcc/targhooks.h > =================================================================== > --- gcc/targhooks.h 2017-10-02 09:08:43.318933786 +0100 > +++ gcc/targhooks.h 2017-10-23 11:42:52.017721094 +0100 > @@ -233,7 +233,7 @@ extern int default_jump_align_max_skip ( > extern section * default_function_section(tree decl, enum node_frequency freq, > bool startup, bool exit); > extern machine_mode default_dwarf_frame_reg_mode (int); > -extern machine_mode default_get_reg_raw_mode (int); > +extern fixed_size_mode default_get_reg_raw_mode (int); > extern bool default_keep_leaf_when_profiled (); > > extern void *default_get_pch_validity (size_t *); > Index: gcc/targhooks.c > =================================================================== > --- gcc/targhooks.c 2017-10-23 11:41:23.195392846 +0100 > +++ gcc/targhooks.c 2017-10-23 11:42:52.017721094 +0100 > @@ -1834,10 +1834,12 @@ default_dwarf_frame_reg_mode (int regno) > /* To be used by targets where reg_raw_mode doesn't return the right > mode for registers used in apply_builtin_return and apply_builtin_arg. */ > > -machine_mode > +fixed_size_mode > default_get_reg_raw_mode (int regno) > { > - return reg_raw_mode[regno]; > + /* Targets must override this hook if the underlying register is > + variable-sized. */ > + return as_a <fixed_size_mode> (reg_raw_mode[regno]); > } > > /* Return true if a leaf function should stay leaf even with profiling > Index: gcc/config/ia64/ia64.c > =================================================================== > --- gcc/config/ia64/ia64.c 2017-10-23 11:41:32.363050263 +0100 > +++ gcc/config/ia64/ia64.c 2017-10-23 11:42:52.009721093 +0100 > @@ -329,7 +329,7 @@ static tree ia64_fold_builtin (tree, int > static tree ia64_builtin_decl (unsigned, bool); > > static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t); > -static machine_mode ia64_get_reg_raw_mode (int regno); > +static fixed_size_mode ia64_get_reg_raw_mode (int regno); > static section * ia64_hpux_function_section (tree, enum node_frequency, > bool, bool); > > @@ -11328,7 +11328,7 @@ ia64_dconst_0_375 (void) > return ia64_dconst_0_375_rtx; > } > > -static machine_mode > +static fixed_size_mode > ia64_get_reg_raw_mode (int regno) > { > if (FR_REGNO_P (regno)) > Index: gcc/config/mips/mips.c > =================================================================== > --- gcc/config/mips/mips.c 2017-10-23 11:41:32.365050264 +0100 > +++ gcc/config/mips/mips.c 2017-10-23 11:42:52.010721093 +0100 > @@ -1132,7 +1132,6 @@ static rtx mips_find_pic_call_symbol (rt > static int mips_register_move_cost (machine_mode, reg_class_t, > reg_class_t); > static unsigned int mips_function_arg_boundary (machine_mode, const_tree); > -static machine_mode mips_get_reg_raw_mode (int regno); > static rtx mips_gen_const_int_vector_shuffle (machine_mode, int); > > /* This hash table keeps track of implicit "mips16" and "nomips16" attributes > @@ -6111,7 +6110,7 @@ mips_function_arg_boundary (machine_mode > > /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ > > -static machine_mode > +static fixed_size_mode > mips_get_reg_raw_mode (int regno) > { > if (TARGET_FLOATXX && FP_REG_P (regno)) > Index: gcc/config/msp430/msp430.c > =================================================================== > --- gcc/config/msp430/msp430.c 2017-10-23 11:41:23.047405581 +0100 > +++ gcc/config/msp430/msp430.c 2017-10-23 11:42:52.011721093 +0100 > @@ -1398,16 +1398,17 @@ msp430_return_in_memory (const_tree ret_ > #undef TARGET_GET_RAW_ARG_MODE > #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode > > -static machine_mode > +static fixed_size_mode > msp430_get_raw_arg_mode (int regno) > { > - return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode; > + return as_a <fixed_size_mode> (regno == ARG_POINTER_REGNUM > + ? VOIDmode : Pmode); > } > > #undef TARGET_GET_RAW_RESULT_MODE > #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode > > -static machine_mode > +static fixed_size_mode > msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED) > { > return Pmode; > Index: gcc/config/avr/avr-protos.h > =================================================================== > --- gcc/config/avr/avr-protos.h 2017-10-23 11:41:22.812366984 +0100 > +++ gcc/config/avr/avr-protos.h 2017-10-23 11:42:52.007721093 +0100 > @@ -132,7 +132,7 @@ extern bool avr_casei_sequence_check_ope > static inline unsigned > regmask (machine_mode mode, unsigned regno) > { > - return ((1u << GET_MODE_SIZE (mode)) - 1) << regno; > + return ((1u << GET_MODE_SIZE (as_a <fixed_size_mode> (mode))) - 1) << regno; > } > > extern void avr_fix_inputs (rtx*, unsigned, unsigned); > Index: gcc/dbxout.c > =================================================================== > --- gcc/dbxout.c 2017-10-10 17:55:22.088175460 +0100 > +++ gcc/dbxout.c 2017-10-23 11:42:52.011721093 +0100 > @@ -3393,12 +3393,16 @@ dbxout_parms (tree parms) > { > ++debug_nesting; > emit_pending_bincls_if_required (); > + fixed_size_mode rtl_mode, type_mode; > > for (; parms; parms = DECL_CHAIN (parms)) > if (DECL_NAME (parms) > && TREE_TYPE (parms) != error_mark_node > && DECL_RTL_SET_P (parms) > - && DECL_INCOMING_RTL (parms)) > + && DECL_INCOMING_RTL (parms) > + /* We can't represent variable-sized types in this format. */ > + && is_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (parms)), &type_mode) > + && is_a <fixed_size_mode> (GET_MODE (DECL_RTL (parms)), &rtl_mode)) > { > tree eff_type; > char letter; > @@ -3555,10 +3559,9 @@ dbxout_parms (tree parms) > /* Make a big endian correction if the mode of the type of the > parameter is not the same as the mode of the rtl. */ > if (BYTES_BIG_ENDIAN > - && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms)) > - && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD) > - number += (GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))) > - - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)))); > + && type_mode != rtl_mode > + && GET_MODE_SIZE (type_mode) < UNITS_PER_WORD) > + number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode); > } > else > /* ??? We don't know how to represent this argument. */ > Index: gcc/expr.c > =================================================================== > --- gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 > +++ gcc/expr.c 2017-10-23 11:42:52.013721093 +0100 > @@ -2628,9 +2628,10 @@ copy_blkmode_from_reg (rtx target, rtx s > rtx src = NULL, dst = NULL; > unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD); > unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0; > - machine_mode mode = GET_MODE (srcreg); > - machine_mode tmode = GET_MODE (target); > - machine_mode copy_mode; > + /* No current ABI uses variable-sized modes to pass a BLKmnode type. */ > + fixed_size_mode mode = as_a <fixed_size_mode> (GET_MODE (srcreg)); > + fixed_size_mode tmode = as_a <fixed_size_mode> (GET_MODE (target)); > + fixed_size_mode copy_mode; > > /* BLKmode registers created in the back-end shouldn't have survived. */ > gcc_assert (mode != BLKmode); > @@ -2728,19 +2729,21 @@ copy_blkmode_from_reg (rtx target, rtx s > } > } > > -/* Copy BLKmode value SRC into a register of mode MODE. Return the > +/* Copy BLKmode value SRC into a register of mode MODE_IN. Return the > register if it contains any data, otherwise return null. > > This is used on targets that return BLKmode values in registers. */ > > rtx > -copy_blkmode_to_reg (machine_mode mode, tree src) > +copy_blkmode_to_reg (machine_mode mode_in, tree src) > { > int i, n_regs; > unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0, bytes; > unsigned int bitsize; > rtx *dst_words, dst, x, src_word = NULL_RTX, dst_word = NULL_RTX; > - machine_mode dst_mode; > + /* No current ABI uses variable-sized modes to pass a BLKmnode type. */ > + fixed_size_mode mode = as_a <fixed_size_mode> (mode_in); > + fixed_size_mode dst_mode; > > gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode); > > Index: gcc/gimple-ssa-store-merging.c > =================================================================== > --- gcc/gimple-ssa-store-merging.c 2017-10-09 11:50:52.446411111 +0100 > +++ gcc/gimple-ssa-store-merging.c 2017-10-23 11:42:52.014721093 +0100 > @@ -401,8 +401,11 @@ encode_tree_to_bitpos (tree expr, unsign > The awkwardness comes from the fact that bitpos is counted from the > most significant bit of a byte. */ > > + /* We must be dealing with fixed-size data at this point, since the > + total size is also fixed. */ > + fixed_size_mode mode = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr))); > /* Allocate an extra byte so that we have space to shift into. */ > - unsigned int byte_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) + 1; > + unsigned int byte_size = GET_MODE_SIZE (mode) + 1; > unsigned char *tmpbuf = XALLOCAVEC (unsigned char, byte_size); > memset (tmpbuf, '\0', byte_size); > /* The store detection code should only have allowed constants that are > Index: gcc/omp-low.c > =================================================================== > --- gcc/omp-low.c 2017-10-10 17:55:22.100175459 +0100 > +++ gcc/omp-low.c 2017-10-23 11:42:52.015721094 +0100 > @@ -5067,8 +5067,10 @@ lower_oacc_reductions (location_t loc, t > v1 = v2 = v3 = var; > > /* Determine position in reduction buffer, which may be used > - by target. */ > - machine_mode mode = TYPE_MODE (TREE_TYPE (var)); > + by target. The parser has ensured that this is not a > + variable-sized type. */ > + fixed_size_mode mode > + = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var))); > unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; > offset = (offset + align - 1) & ~(align - 1); > tree off = build_int_cst (sizetype, offset); > Index: gcc/simplify-rtx.c > =================================================================== > --- gcc/simplify-rtx.c 2017-10-23 11:41:41.550050496 +0100 > +++ gcc/simplify-rtx.c 2017-10-23 11:42:52.016721094 +0100 > @@ -48,8 +48,6 @@ #define HWI_SIGN_EXTEND(low) \ > static rtx neg_const_int (machine_mode, const_rtx); > static bool plus_minus_operand_p (const_rtx); > static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx); > -static rtx simplify_immed_subreg (machine_mode, rtx, machine_mode, > - unsigned int); > static rtx simplify_associative_operation (enum rtx_code, machine_mode, > rtx, rtx); > static rtx simplify_relational_operation_1 (enum rtx_code, machine_mode, > @@ -5802,8 +5800,8 @@ simplify_ternary_operation (enum rtx_cod > and then repacking them again for OUTERMODE. */ > > static rtx > -simplify_immed_subreg (machine_mode outermode, rtx op, > - machine_mode innermode, unsigned int byte) > +simplify_immed_subreg (fixed_size_mode outermode, rtx op, > + fixed_size_mode innermode, unsigned int byte) > { > enum { > value_bit = 8, > @@ -6171,7 +6169,18 @@ simplify_subreg (machine_mode outermode, > || CONST_DOUBLE_AS_FLOAT_P (op) > || GET_CODE (op) == CONST_FIXED > || GET_CODE (op) == CONST_VECTOR) > - return simplify_immed_subreg (outermode, op, innermode, byte); > + { > + /* simplify_immed_subreg deconstructs OP into bytes and constructs > + the result from bytes, so it only works if the sizes of the modes > + are known at compile time. Cases that apply to general modes > + should be handled here before calling simplify_immed_subreg. */ > + fixed_size_mode fs_outermode, fs_innermode; > + if (is_a <fixed_size_mode> (outermode, &fs_outermode) > + && is_a <fixed_size_mode> (innermode, &fs_innermode)) > + return simplify_immed_subreg (fs_outermode, op, fs_innermode, byte); > + > + return NULL_RTX; > + } > > /* Changing mode twice with SUBREG => just change it once, > or not at all if changing back op starting mode. */ > Index: gcc/varasm.c > =================================================================== > --- gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 > +++ gcc/varasm.c 2017-10-23 11:42:52.018721094 +0100 > @@ -3584,7 +3584,7 @@ struct GTY((chain_next ("%h.next"), for_ > rtx constant; > HOST_WIDE_INT offset; > hashval_t hash; > - machine_mode mode; > + fixed_size_mode mode; > unsigned int align; > int labelno; > int mark; > @@ -3760,10 +3760,11 @@ simplify_subtraction (rtx x) > } > > /* Given a constant rtx X, make (or find) a memory constant for its value > - and return a MEM rtx to refer to it in memory. */ > + and return a MEM rtx to refer to it in memory. IN_MODE is the mode > + of X. */ > > rtx > -force_const_mem (machine_mode mode, rtx x) > +force_const_mem (machine_mode in_mode, rtx x) > { > struct constant_descriptor_rtx *desc, tmp; > struct rtx_constant_pool *pool; > @@ -3772,6 +3773,11 @@ force_const_mem (machine_mode mode, rtx > hashval_t hash; > unsigned int align; > constant_descriptor_rtx **slot; > + fixed_size_mode mode; > + > + /* We can't force variable-sized objects to memory. */ > + if (!is_a <fixed_size_mode> (in_mode, &mode)) > + return NULL_RTX; > > /* If we're not allowed to drop X into the constant pool, don't. */ > if (targetm.cannot_force_const_mem (mode, x)) > @@ -3881,7 +3887,7 @@ get_pool_constant_mark (rtx addr, bool * > > /* Similar, return the mode. */ > > -machine_mode > +fixed_size_mode > get_pool_mode (const_rtx addr) > { > return SYMBOL_REF_CONSTANT (addr)->mode; > @@ -3901,7 +3907,7 @@ constant_pool_empty_p (void) > in MODE with known alignment ALIGN. */ > > static void > -output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align) > +output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align) > { > switch (GET_MODE_CLASS (mode)) > {
Index: gcc/machmode.h =================================================================== --- gcc/machmode.h 2017-09-15 14:47:33.184331588 +0100 +++ gcc/machmode.h 2017-10-23 11:42:52.014721093 +0100 @@ -652,6 +652,39 @@ 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]) +/* Represents a machine mode that must have a fixed size. The main + use of this class is to represent the modes of objects that always + have static storage duration, such as constant pool entries. + (No current target supports the concept of variable-size static data.) */ +class fixed_size_mode +{ +public: + typedef mode_traits<fixed_size_mode>::from_int from_int; + + ALWAYS_INLINE fixed_size_mode () {} + ALWAYS_INLINE fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {} + ALWAYS_INLINE fixed_size_mode (const scalar_mode &m) : m_mode (m) {} + ALWAYS_INLINE fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {} + ALWAYS_INLINE fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {} + ALWAYS_INLINE fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {} + ALWAYS_INLINE fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {} + ALWAYS_INLINE fixed_size_mode (const complex_mode &m) : m_mode (m) {} + ALWAYS_INLINE operator machine_mode () const { return m_mode; } + + static bool includes_p (machine_mode); + +protected: + machine_mode m_mode; +}; + +/* Return true if MODE has a fixed size. */ + +inline bool +fixed_size_mode::includes_p (machine_mode) +{ + return true; +} + 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 Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2017-10-23 11:42:47.297720974 +0100 +++ gcc/rtl.h 2017-10-23 11:42:52.015721094 +0100 @@ -3020,7 +3020,7 @@ extern rtx force_const_mem (machine_mode struct function; extern rtx get_pool_constant (const_rtx); extern rtx get_pool_constant_mark (rtx, bool *); -extern machine_mode get_pool_mode (const_rtx); +extern fixed_size_mode get_pool_mode (const_rtx); extern rtx simplify_subtraction (rtx); extern void decide_function_section (tree); Index: gcc/gengtype.c =================================================================== --- gcc/gengtype.c 2017-05-23 19:29:56.919436344 +0100 +++ gcc/gengtype.c 2017-10-23 11:42:52.014721093 +0100 @@ -5197,6 +5197,7 @@ #define POS_HERE(Call) do { pos.file = t POS_HERE (do_scalar_typedef ("JCF_u2", &pos)); POS_HERE (do_scalar_typedef ("void", &pos)); POS_HERE (do_scalar_typedef ("machine_mode", &pos)); + POS_HERE (do_scalar_typedef ("fixed_size_mode", &pos)); POS_HERE (do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos)); Index: gcc/target.def =================================================================== --- gcc/target.def 2017-10-23 11:41:23.134456913 +0100 +++ gcc/target.def 2017-10-23 11:42:52.017721094 +0100 @@ -5021,7 +5021,7 @@ DEFHOOK "This target hook returns the mode to be used when accessing raw return\ registers in @code{__builtin_return}. Define this macro if the value\ in @var{reg_raw_mode} is not correct.", - machine_mode, (int regno), + fixed_size_mode, (int regno), default_get_reg_raw_mode) /* Return a mode wide enough to copy any argument value that might be @@ -5031,7 +5031,7 @@ DEFHOOK "This target hook returns the mode to be used when accessing raw argument\ registers in @code{__builtin_apply_args}. Define this macro if the value\ in @var{reg_raw_mode} is not correct.", - machine_mode, (int regno), + fixed_size_mode, (int regno), default_get_reg_raw_mode) HOOK_VECTOR_END (calls) Index: gcc/doc/tm.texi =================================================================== --- gcc/doc/tm.texi 2017-10-23 11:41:22.175925023 +0100 +++ gcc/doc/tm.texi 2017-10-23 11:42:52.012721093 +0100 @@ -4536,11 +4536,11 @@ This macro has effect in @option{-fpcc-s nothing when you use @option{-freg-struct-return} mode. @end defmac -@deftypefn {Target Hook} machine_mode TARGET_GET_RAW_RESULT_MODE (int @var{regno}) +@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_RESULT_MODE (int @var{regno}) This target hook returns the mode to be used when accessing raw return registers in @code{__builtin_return}. Define this macro if the value in @var{reg_raw_mode} is not correct. @end deftypefn -@deftypefn {Target Hook} machine_mode TARGET_GET_RAW_ARG_MODE (int @var{regno}) +@deftypefn {Target Hook} fixed_size_mode TARGET_GET_RAW_ARG_MODE (int @var{regno}) This target hook returns the mode to be used when accessing raw argument registers in @code{__builtin_apply_args}. Define this macro if the value in @var{reg_raw_mode} is not correct. @end deftypefn Index: gcc/targhooks.h =================================================================== --- gcc/targhooks.h 2017-10-02 09:08:43.318933786 +0100 +++ gcc/targhooks.h 2017-10-23 11:42:52.017721094 +0100 @@ -233,7 +233,7 @@ extern int default_jump_align_max_skip ( extern section * default_function_section(tree decl, enum node_frequency freq, bool startup, bool exit); extern machine_mode default_dwarf_frame_reg_mode (int); -extern machine_mode default_get_reg_raw_mode (int); +extern fixed_size_mode default_get_reg_raw_mode (int); extern bool default_keep_leaf_when_profiled (); extern void *default_get_pch_validity (size_t *); Index: gcc/targhooks.c =================================================================== --- gcc/targhooks.c 2017-10-23 11:41:23.195392846 +0100 +++ gcc/targhooks.c 2017-10-23 11:42:52.017721094 +0100 @@ -1834,10 +1834,12 @@ default_dwarf_frame_reg_mode (int regno) /* To be used by targets where reg_raw_mode doesn't return the right mode for registers used in apply_builtin_return and apply_builtin_arg. */ -machine_mode +fixed_size_mode default_get_reg_raw_mode (int regno) { - return reg_raw_mode[regno]; + /* Targets must override this hook if the underlying register is + variable-sized. */ + return as_a <fixed_size_mode> (reg_raw_mode[regno]); } /* Return true if a leaf function should stay leaf even with profiling Index: gcc/config/ia64/ia64.c =================================================================== --- gcc/config/ia64/ia64.c 2017-10-23 11:41:32.363050263 +0100 +++ gcc/config/ia64/ia64.c 2017-10-23 11:42:52.009721093 +0100 @@ -329,7 +329,7 @@ static tree ia64_fold_builtin (tree, int static tree ia64_builtin_decl (unsigned, bool); static reg_class_t ia64_preferred_reload_class (rtx, reg_class_t); -static machine_mode ia64_get_reg_raw_mode (int regno); +static fixed_size_mode ia64_get_reg_raw_mode (int regno); static section * ia64_hpux_function_section (tree, enum node_frequency, bool, bool); @@ -11328,7 +11328,7 @@ ia64_dconst_0_375 (void) return ia64_dconst_0_375_rtx; } -static machine_mode +static fixed_size_mode ia64_get_reg_raw_mode (int regno) { if (FR_REGNO_P (regno)) Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2017-10-23 11:41:32.365050264 +0100 +++ gcc/config/mips/mips.c 2017-10-23 11:42:52.010721093 +0100 @@ -1132,7 +1132,6 @@ static rtx mips_find_pic_call_symbol (rt static int mips_register_move_cost (machine_mode, reg_class_t, reg_class_t); static unsigned int mips_function_arg_boundary (machine_mode, const_tree); -static machine_mode mips_get_reg_raw_mode (int regno); static rtx mips_gen_const_int_vector_shuffle (machine_mode, int); /* This hash table keeps track of implicit "mips16" and "nomips16" attributes @@ -6111,7 +6110,7 @@ mips_function_arg_boundary (machine_mode /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ -static machine_mode +static fixed_size_mode mips_get_reg_raw_mode (int regno) { if (TARGET_FLOATXX && FP_REG_P (regno)) Index: gcc/config/msp430/msp430.c =================================================================== --- gcc/config/msp430/msp430.c 2017-10-23 11:41:23.047405581 +0100 +++ gcc/config/msp430/msp430.c 2017-10-23 11:42:52.011721093 +0100 @@ -1398,16 +1398,17 @@ msp430_return_in_memory (const_tree ret_ #undef TARGET_GET_RAW_ARG_MODE #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode -static machine_mode +static fixed_size_mode msp430_get_raw_arg_mode (int regno) { - return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode; + return as_a <fixed_size_mode> (regno == ARG_POINTER_REGNUM + ? VOIDmode : Pmode); } #undef TARGET_GET_RAW_RESULT_MODE #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode -static machine_mode +static fixed_size_mode msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED) { return Pmode; Index: gcc/config/avr/avr-protos.h =================================================================== --- gcc/config/avr/avr-protos.h 2017-10-23 11:41:22.812366984 +0100 +++ gcc/config/avr/avr-protos.h 2017-10-23 11:42:52.007721093 +0100 @@ -132,7 +132,7 @@ extern bool avr_casei_sequence_check_ope static inline unsigned regmask (machine_mode mode, unsigned regno) { - return ((1u << GET_MODE_SIZE (mode)) - 1) << regno; + return ((1u << GET_MODE_SIZE (as_a <fixed_size_mode> (mode))) - 1) << regno; } extern void avr_fix_inputs (rtx*, unsigned, unsigned); Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c 2017-10-10 17:55:22.088175460 +0100 +++ gcc/dbxout.c 2017-10-23 11:42:52.011721093 +0100 @@ -3393,12 +3393,16 @@ dbxout_parms (tree parms) { ++debug_nesting; emit_pending_bincls_if_required (); + fixed_size_mode rtl_mode, type_mode; for (; parms; parms = DECL_CHAIN (parms)) if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node && DECL_RTL_SET_P (parms) - && DECL_INCOMING_RTL (parms)) + && DECL_INCOMING_RTL (parms) + /* We can't represent variable-sized types in this format. */ + && is_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (parms)), &type_mode) + && is_a <fixed_size_mode> (GET_MODE (DECL_RTL (parms)), &rtl_mode)) { tree eff_type; char letter; @@ -3555,10 +3559,9 @@ dbxout_parms (tree parms) /* Make a big endian correction if the mode of the type of the parameter is not the same as the mode of the rtl. */ if (BYTES_BIG_ENDIAN - && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms)) - && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD) - number += (GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))) - - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)))); + && type_mode != rtl_mode + && GET_MODE_SIZE (type_mode) < UNITS_PER_WORD) + number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode); } else /* ??? We don't know how to represent this argument. */ Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 +++ gcc/expr.c 2017-10-23 11:42:52.013721093 +0100 @@ -2628,9 +2628,10 @@ copy_blkmode_from_reg (rtx target, rtx s rtx src = NULL, dst = NULL; unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD); unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0; - machine_mode mode = GET_MODE (srcreg); - machine_mode tmode = GET_MODE (target); - machine_mode copy_mode; + /* No current ABI uses variable-sized modes to pass a BLKmnode type. */ + fixed_size_mode mode = as_a <fixed_size_mode> (GET_MODE (srcreg)); + fixed_size_mode tmode = as_a <fixed_size_mode> (GET_MODE (target)); + fixed_size_mode copy_mode; /* BLKmode registers created in the back-end shouldn't have survived. */ gcc_assert (mode != BLKmode); @@ -2728,19 +2729,21 @@ copy_blkmode_from_reg (rtx target, rtx s } } -/* Copy BLKmode value SRC into a register of mode MODE. Return the +/* Copy BLKmode value SRC into a register of mode MODE_IN. Return the register if it contains any data, otherwise return null. This is used on targets that return BLKmode values in registers. */ rtx -copy_blkmode_to_reg (machine_mode mode, tree src) +copy_blkmode_to_reg (machine_mode mode_in, tree src) { int i, n_regs; unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0, bytes; unsigned int bitsize; rtx *dst_words, dst, x, src_word = NULL_RTX, dst_word = NULL_RTX; - machine_mode dst_mode; + /* No current ABI uses variable-sized modes to pass a BLKmnode type. */ + fixed_size_mode mode = as_a <fixed_size_mode> (mode_in); + fixed_size_mode dst_mode; gcc_assert (TYPE_MODE (TREE_TYPE (src)) == BLKmode); Index: gcc/gimple-ssa-store-merging.c =================================================================== --- gcc/gimple-ssa-store-merging.c 2017-10-09 11:50:52.446411111 +0100 +++ gcc/gimple-ssa-store-merging.c 2017-10-23 11:42:52.014721093 +0100 @@ -401,8 +401,11 @@ encode_tree_to_bitpos (tree expr, unsign The awkwardness comes from the fact that bitpos is counted from the most significant bit of a byte. */ + /* We must be dealing with fixed-size data at this point, since the + total size is also fixed. */ + fixed_size_mode mode = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (expr))); /* Allocate an extra byte so that we have space to shift into. */ - unsigned int byte_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr))) + 1; + unsigned int byte_size = GET_MODE_SIZE (mode) + 1; unsigned char *tmpbuf = XALLOCAVEC (unsigned char, byte_size); memset (tmpbuf, '\0', byte_size); /* The store detection code should only have allowed constants that are Index: gcc/omp-low.c =================================================================== --- gcc/omp-low.c 2017-10-10 17:55:22.100175459 +0100 +++ gcc/omp-low.c 2017-10-23 11:42:52.015721094 +0100 @@ -5067,8 +5067,10 @@ lower_oacc_reductions (location_t loc, t v1 = v2 = v3 = var; /* Determine position in reduction buffer, which may be used - by target. */ - machine_mode mode = TYPE_MODE (TREE_TYPE (var)); + by target. The parser has ensured that this is not a + variable-sized type. */ + fixed_size_mode mode + = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var))); unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT; offset = (offset + align - 1) & ~(align - 1); tree off = build_int_cst (sizetype, offset); Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c 2017-10-23 11:41:41.550050496 +0100 +++ gcc/simplify-rtx.c 2017-10-23 11:42:52.016721094 +0100 @@ -48,8 +48,6 @@ #define HWI_SIGN_EXTEND(low) \ static rtx neg_const_int (machine_mode, const_rtx); static bool plus_minus_operand_p (const_rtx); static rtx simplify_plus_minus (enum rtx_code, machine_mode, rtx, rtx); -static rtx simplify_immed_subreg (machine_mode, rtx, machine_mode, - unsigned int); static rtx simplify_associative_operation (enum rtx_code, machine_mode, rtx, rtx); static rtx simplify_relational_operation_1 (enum rtx_code, machine_mode, @@ -5802,8 +5800,8 @@ simplify_ternary_operation (enum rtx_cod and then repacking them again for OUTERMODE. */ static rtx -simplify_immed_subreg (machine_mode outermode, rtx op, - machine_mode innermode, unsigned int byte) +simplify_immed_subreg (fixed_size_mode outermode, rtx op, + fixed_size_mode innermode, unsigned int byte) { enum { value_bit = 8, @@ -6171,7 +6169,18 @@ simplify_subreg (machine_mode outermode, || CONST_DOUBLE_AS_FLOAT_P (op) || GET_CODE (op) == CONST_FIXED || GET_CODE (op) == CONST_VECTOR) - return simplify_immed_subreg (outermode, op, innermode, byte); + { + /* simplify_immed_subreg deconstructs OP into bytes and constructs + the result from bytes, so it only works if the sizes of the modes + are known at compile time. Cases that apply to general modes + should be handled here before calling simplify_immed_subreg. */ + fixed_size_mode fs_outermode, fs_innermode; + if (is_a <fixed_size_mode> (outermode, &fs_outermode) + && is_a <fixed_size_mode> (innermode, &fs_innermode)) + return simplify_immed_subreg (fs_outermode, op, fs_innermode, byte); + + return NULL_RTX; + } /* Changing mode twice with SUBREG => just change it once, or not at all if changing back op starting mode. */ Index: gcc/varasm.c =================================================================== --- gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 +++ gcc/varasm.c 2017-10-23 11:42:52.018721094 +0100 @@ -3584,7 +3584,7 @@ struct GTY((chain_next ("%h.next"), for_ rtx constant; HOST_WIDE_INT offset; hashval_t hash; - machine_mode mode; + fixed_size_mode mode; unsigned int align; int labelno; int mark; @@ -3760,10 +3760,11 @@ simplify_subtraction (rtx x) } /* Given a constant rtx X, make (or find) a memory constant for its value - and return a MEM rtx to refer to it in memory. */ + and return a MEM rtx to refer to it in memory. IN_MODE is the mode + of X. */ rtx -force_const_mem (machine_mode mode, rtx x) +force_const_mem (machine_mode in_mode, rtx x) { struct constant_descriptor_rtx *desc, tmp; struct rtx_constant_pool *pool; @@ -3772,6 +3773,11 @@ force_const_mem (machine_mode mode, rtx hashval_t hash; unsigned int align; constant_descriptor_rtx **slot; + fixed_size_mode mode; + + /* We can't force variable-sized objects to memory. */ + if (!is_a <fixed_size_mode> (in_mode, &mode)) + return NULL_RTX; /* If we're not allowed to drop X into the constant pool, don't. */ if (targetm.cannot_force_const_mem (mode, x)) @@ -3881,7 +3887,7 @@ get_pool_constant_mark (rtx addr, bool * /* Similar, return the mode. */ -machine_mode +fixed_size_mode get_pool_mode (const_rtx addr) { return SYMBOL_REF_CONSTANT (addr)->mode; @@ -3901,7 +3907,7 @@ constant_pool_empty_p (void) in MODE with known alignment ALIGN. */ static void -output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align) +output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align) { switch (GET_MODE_CLASS (mode)) {