diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-08-30 11:09:01 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-08-30 11:09:01 +0000 |
commit | 490d0f6c91c0c4fef57a5ffe438629b0687113de (patch) | |
tree | 2c5b1e4319507b30cf23a863c8d44ac6e10e3d57 /gcc/machmode.h | |
parent | ec35d57225c9cd7f69ab1b25982b90bfc0f878e7 (diff) | |
download | gcc-490d0f6c91c0c4fef57a5ffe438629b0687113de.zip gcc-490d0f6c91c0c4fef57a5ffe438629b0687113de.tar.gz gcc-490d0f6c91c0c4fef57a5ffe438629b0687113de.tar.bz2 |
[6/77] Make GET_MODE_WIDER return an opt_mode
GET_MODE_WIDER previously returned VOIDmode if no wider mode existed.
That would cause problems with stricter mode classes, since VOIDmode
isn't for example a valid scalar integer or floating-point mode.
This patch instead makes it return a new opt_mode<T> class, which
holds either a T or nothing.
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* coretypes.h (opt_mode): New class.
* machmode.h (opt_mode): Likewise.
(opt_mode::else_void): New function.
(opt_mode::require): Likewise.
(opt_mode::exists): Likewise.
(GET_MODE_WIDER_MODE): Turn into a function and return an opt_mode.
(GET_MODE_2XWIDER_MODE): Likewise.
(mode_iterator::get_wider): Update accordingly.
(mode_iterator::get_2xwider): Likewise.
(mode_iterator::get_known_wider): Likewise, turning into a template.
* combine.c (make_extraction): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
* config/cr16/cr16.h (LONG_REG_P): Likewise.
* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.
* config/c6x/c6x.c (c6x_rtx_costs): Update use of
GET_MODE_2XWIDER_MODE, forcing a wider mode to exist.
* lower-subreg.c (init_lower_subreg): Likewise.
* optabs-libfuncs.c (init_sync_libfuncs_1): Likewise, but not
on the final iteration.
* config/i386/i386.c (ix86_expand_set_or_movmem): Check whether
a wider mode exists before asking for a move pattern.
(get_mode_wider_vector): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
(expand_vselect_vconcat): Update use of GET_MODE_2XWIDER_MODE,
returning false if no such mode exists.
* config/ia64/ia64.c (expand_vselect_vconcat): Likewise.
* config/mips/mips.c (mips_expand_vselect_vconcat): Likewise.
* expmed.c (init_expmed_one_mode): Update use of GET_MODE_WIDER_MODE.
Avoid checking for a MODE_INT if we already know the mode is not a
SCALAR_INT_MODE_P.
(extract_high_half): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
(expmed_mult_highpart_optab): Likewise.
(expmed_mult_highpart): Likewise.
* expr.c (expand_expr_real_2): Update use of GET_MODE_WIDER_MODE,
using else_void.
* lto-streamer-in.c (lto_input_mode_table): Likewise.
* optabs-query.c (find_widening_optab_handler_and_mode): Likewise.
* stor-layout.c (bit_field_mode_iterator::next_mode): Likewise.
* internal-fn.c (expand_mul_overflow): Update use of
GET_MODE_2XWIDER_MODE.
* omp-low.c (omp_clause_aligned_alignment): Likewise.
* tree-ssa-math-opts.c (convert_mult_to_widen): Update use of
GET_MODE_WIDER_MODE.
(convert_plusminus_to_widen): Likewise.
* tree-switch-conversion.c (array_value_type): Likewise.
* var-tracking.c (emit_note_insn_var_location): Likewise.
* tree-vrp.c (simplify_float_conversion_using_ranges): Likewise.
Return false inside rather than outside the loop if no wider mode
exists
* optabs.c (expand_binop): Update use of GET_MODE_WIDER_MODE
and GET_MODE_2XWIDER_MODE
(can_compare_p): Use else_void.
* gdbhooks.py (OptMachineModePrinter): New class.
(build_pretty_printer): Use it for opt_mode.
gcc/ada/
* gcc-interface/decl.c (validate_size): Update use of
GET_MODE_WIDER_MODE, forcing a wider mode to exist.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251457
Diffstat (limited to 'gcc/machmode.h')
-rw-r--r-- | gcc/machmode.h | 92 |
1 files changed, 83 insertions, 9 deletions
diff --git a/gcc/machmode.h b/gcc/machmode.h index c272888..3b06f6d 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -221,6 +221,71 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES]; #define POINTER_BOUNDS_MODE_P(MODE) \ (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS) +/* An optional T (i.e. a T or nothing), where T is some form of mode class. */ +template<typename T> +class opt_mode +{ +public: + enum from_int { dummy = MAX_MACHINE_MODE }; + + ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {} + ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {} + ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {} + + machine_mode else_void () const; + T require () const; + + bool exists () const; + template<typename U> bool exists (U *) const; + +private: + machine_mode m_mode; +}; + +/* If the object contains a T, return its enum value, otherwise return + E_VOIDmode. */ + +template<typename T> +ALWAYS_INLINE machine_mode +opt_mode<T>::else_void () const +{ + return m_mode; +} + +/* Assert that the object contains a T and return it. */ + +template<typename T> +inline T +opt_mode<T>::require () const +{ + gcc_checking_assert (m_mode != E_VOIDmode); + return typename mode_traits<T>::from_int (m_mode); +} + +/* Return true if the object contains a T rather than nothing. */ + +template<typename T> +ALWAYS_INLINE bool +opt_mode<T>::exists () const +{ + return m_mode != E_VOIDmode; +} + +/* Return true if the object contains a T, storing it in *MODE if so. */ + +template<typename T> +template<typename U> +inline bool +opt_mode<T>::exists (U *mode) const +{ + if (m_mode != E_VOIDmode) + { + *mode = T (typename mode_traits<T>::from_int (m_mode)); + return true; + } + return false; +} + /* Return the base GET_MODE_SIZE value for MODE. */ ALWAYS_INLINE unsigned short @@ -352,13 +417,22 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES]; /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */ -extern const unsigned char mode_wider[NUM_MACHINE_MODES]; -#define GET_MODE_WIDER_MODE(MODE) ((machine_mode) mode_wider[MODE]) +template<typename T> +ALWAYS_INLINE opt_mode<T> +GET_MODE_WIDER_MODE (const T &m) +{ + return typename opt_mode<T>::from_int (mode_wider[m]); +} /* For scalars, this is a mode with twice the precision. For vectors, this is a mode with the same inner mode but with twice the elements. */ -extern const unsigned char mode_2xwider[NUM_MACHINE_MODES]; -#define GET_MODE_2XWIDER_MODE(MODE) ((machine_mode) mode_2xwider[MODE]) + +template<typename T> +ALWAYS_INLINE opt_mode<T> +GET_MODE_2XWIDER_MODE (const T &m) +{ + return typename opt_mode<T>::from_int (mode_2xwider[m]); +} /* Get the complex mode from the component mode. */ extern const unsigned char mode_complex[NUM_MACHINE_MODES]; @@ -497,17 +571,17 @@ namespace mode_iterator inline void get_wider (machine_mode *iter) { - *iter = GET_MODE_WIDER_MODE (*iter); + *iter = GET_MODE_WIDER_MODE (*iter).else_void (); } /* Set mode iterator *ITER to the next widest mode in the same class. Such a mode is known to exist. */ + template<typename T> inline void - get_known_wider (machine_mode *iter) + get_known_wider (T *iter) { - *iter = GET_MODE_WIDER_MODE (*iter); - gcc_checking_assert (*iter != VOIDmode); + *iter = GET_MODE_WIDER_MODE (*iter).require (); } /* Set mode iterator *ITER to the mode that is two times wider than the @@ -516,7 +590,7 @@ namespace mode_iterator inline void get_2xwider (machine_mode *iter) { - *iter = GET_MODE_2XWIDER_MODE (*iter); + *iter = GET_MODE_2XWIDER_MODE (*iter).else_void (); } } |