From 28ebc73c5fceae97d0e902a0b8055cc12c934f44 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 30 Aug 2017 11:09:01 +0000 Subject: [PATCH] [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 class, which holds either a T or nothing. 2017-08-30 Richard Sandiford Alan Hayward David Sherwood 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251457 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 60 +++++++++++++++++++++++++++++ gcc/ada/ChangeLog | 7 ++++ gcc/ada/gcc-interface/decl.c | 2 +- gcc/combine.c | 5 +-- gcc/config/c6x/c6x.c | 2 +- gcc/config/cr16/cr16.h | 4 +- gcc/config/i386/i386.c | 12 +++--- gcc/config/ia64/ia64.c | 3 +- gcc/config/mips/mips.c | 3 +- gcc/coretypes.h | 1 + gcc/expmed.c | 15 ++++---- gcc/expr.c | 2 +- gcc/gdbhooks.py | 15 ++++++++ gcc/internal-fn.c | 6 +-- gcc/lower-subreg.c | 2 +- gcc/lto-streamer-in.c | 2 +- gcc/machmode.h | 92 +++++++++++++++++++++++++++++++++++++++----- gcc/omp-low.c | 4 +- gcc/optabs-libfuncs.c | 3 +- gcc/optabs-query.c | 2 +- gcc/optabs.c | 20 +++++----- gcc/rtlanal.c | 6 ++- gcc/stor-layout.c | 5 ++- gcc/tree-ssa-math-opts.c | 8 ++-- gcc/tree-switch-conversion.c | 3 +- gcc/tree-vrp.c | 9 ++--- gcc/var-tracking.c | 3 +- 27 files changed, 225 insertions(+), 71 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8765c3cc7a3..9d8c1f0d74d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -2,6 +2,66 @@ Alan Hayward David Sherwood + * 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. + +2017-08-30 Richard Sandiford + Alan Hayward + David Sherwood + * tree-switch-conversion.c (array_value_type): Only read TYPE_MODE once. Use get_narrowest_mode instead of GET_CLASS_NARROWEST_MODE. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4f7d2bd5ef9..769546c43ac 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,4 +1,11 @@ 2017-08-30 Richard Sandiford + Alan Hayward + David Sherwood + + * gcc-interface/decl.c (validate_size): Update use of + GET_MODE_WIDER_MODE, forcing a wider mode to exist. + +2017-08-30 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 83b9d0749fe..83c582ff64f 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -8576,7 +8576,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object, { machine_mode p_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); while (!targetm.valid_pointer_mode (p_mode)) - p_mode = GET_MODE_WIDER_MODE (p_mode); + p_mode = GET_MODE_WIDER_MODE (p_mode).require (); type_size = bitsize_int (GET_MODE_BITSIZE (p_mode)); } diff --git a/gcc/combine.c b/gcc/combine.c index 46212c5ea84..1a6eda609ed 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7604,10 +7604,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos, wanted_inner_mode = smallest_mode_for_size (len, MODE_INT); while (pos % GET_MODE_BITSIZE (wanted_inner_mode) + len > GET_MODE_BITSIZE (wanted_inner_mode)) - { - wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode); - gcc_assert (wanted_inner_mode != VOIDmode); - } + wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode).require (); } orig_pos = pos; diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c index 4f64df262ca..d92b8782c49 100644 --- a/gcc/config/c6x/c6x.c +++ b/gcc/config/c6x/c6x.c @@ -6066,7 +6066,7 @@ c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total, /* Recognize a mult_highpart operation. */ if ((mode == HImode || mode == SImode) && GET_CODE (XEXP (x, 0)) == LSHIFTRT - && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode) + && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode).require () && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode)) diff --git a/gcc/config/cr16/cr16.h b/gcc/config/cr16/cr16.h index e2a678ea1ee..eba92544aa3 100644 --- a/gcc/config/cr16/cr16.h +++ b/gcc/config/cr16/cr16.h @@ -197,9 +197,7 @@ while (0) /* Returns 1 if the register is longer than word size, 0 otherwise. */ #define LONG_REG_P(REGNO) \ - (HARD_REGNO_NREGS (REGNO, \ - GET_MODE_WIDER_MODE (smallest_mode_for_size \ - (BITS_PER_WORD, MODE_INT))) == 1) + (HARD_REGNO_NREGS (REGNO, GET_MODE_WIDER_MODE (word_mode).require ()) == 1) #define HARD_REGNO_NREGS(REGNO, MODE) \ ((REGNO >= CR16_FIRST_DWORD_REGISTER) \ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f087bce291b..88850bde786 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -28534,6 +28534,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, bool need_zero_guard = false; bool noalign; machine_mode move_mode = VOIDmode; + machine_mode wider_mode; int unroll_factor = 1; /* TODO: Once value ranges are available, fill in proper data. */ unsigned HOST_WIDE_INT min_size = 0; @@ -28627,9 +28628,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, unroll_factor = 4; /* Find the widest supported mode. */ move_mode = word_mode; - while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode)) - != CODE_FOR_nothing) - move_mode = GET_MODE_WIDER_MODE (move_mode); + while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode) + && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing) + move_mode = wider_mode; /* Find the corresponding vector mode with the same size as MOVE_MODE. MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */ @@ -43502,7 +43503,7 @@ static inline machine_mode get_mode_wider_vector (machine_mode o) { /* ??? Rely on the ordering that genmodes.c gives to vectors. */ - machine_mode n = GET_MODE_WIDER_MODE (o); + machine_mode n = GET_MODE_WIDER_MODE (o).require (); gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2); gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n)); return n; @@ -46865,7 +46866,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1, if (vselect_insn == NULL_RTX) init_vselect_insn (); - v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0)); + if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode)) + return false; x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0); PUT_MODE (x, v2mode); XEXP (x, 0) = op0; diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 455b50e1fb8..720c16bd003 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -11298,7 +11298,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1, machine_mode v2mode; rtx x; - v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0)); + if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode)) + return false; x = gen_rtx_VEC_CONCAT (v2mode, op0, op1); return expand_vselect (target, x, perm, nelt); } diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index af7cd184a66..d646f612591 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -21105,7 +21105,8 @@ mips_expand_vselect_vconcat (rtx target, rtx op0, rtx op1, machine_mode v2mode; rtx x; - v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0)); + if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode)) + return false; x = gen_rtx_VEC_CONCAT (v2mode, op0, op1); return mips_expand_vselect (target, x, perm, nelt); } diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 9ceb5391b3c..4de0611ebb4 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -55,6 +55,7 @@ typedef const struct simple_bitmap_def *const_sbitmap; struct rtx_def; typedef struct rtx_def *rtx; typedef const struct rtx_def *const_rtx; +template class opt_mode; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. diff --git a/gcc/expmed.c b/gcc/expmed.c index 0219e0dee76..48a006004ff 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -207,11 +207,10 @@ init_expmed_one_mode (struct init_expmed_rtl *all, for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT; mode_from = (machine_mode)(mode_from + 1)) init_expmed_one_conv (all, mode, mode_from, speed); - } - if (GET_MODE_CLASS (mode) == MODE_INT) - { - machine_mode wider_mode = GET_MODE_WIDER_MODE (mode); - if (wider_mode != VOIDmode) + + machine_mode wider_mode; + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)) { PUT_MODE (all->zext, wider_mode); PUT_MODE (all->wide_mult, wider_mode); @@ -3641,7 +3640,7 @@ extract_high_half (machine_mode mode, rtx op) gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); - wider_mode = GET_MODE_WIDER_MODE (mode); + wider_mode = GET_MODE_WIDER_MODE (mode).require (); op = expand_shift (RSHIFT_EXPR, wider_mode, op, GET_MODE_BITSIZE (mode), 0, 1); return convert_modes (mode, wider_mode, op, 0); @@ -3663,7 +3662,7 @@ expmed_mult_highpart_optab (machine_mode mode, rtx op0, rtx op1, gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); - wider_mode = GET_MODE_WIDER_MODE (mode); + wider_mode = GET_MODE_WIDER_MODE (mode).require (); size = GET_MODE_BITSIZE (mode); /* Firstly, try using a multiplication insn that only generates the needed @@ -3769,7 +3768,7 @@ static rtx expmed_mult_highpart (machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp, int max_cost) { - machine_mode wider_mode = GET_MODE_WIDER_MODE (mode); + machine_mode wider_mode = GET_MODE_WIDER_MODE (mode).require (); unsigned HOST_WIDE_INT cnst1; int extra_cost; bool sign_adjust = false; diff --git a/gcc/expr.c b/gcc/expr.c index cbec00c64ae..0219045f9ff 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -9159,7 +9159,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, if (code == LSHIFT_EXPR && target && REG_P (target) - && mode == GET_MODE_WIDER_MODE (word_mode) + && mode == GET_MODE_WIDER_MODE (word_mode).else_void () && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode) && TREE_CONSTANT (treeop1) && TREE_CODE (treeop0) == SSA_NAME) diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py index 962df473f57..847cd08302f 100644 --- a/gcc/gdbhooks.py +++ b/gcc/gdbhooks.py @@ -422,6 +422,18 @@ class VecPrinter: ###################################################################### +class OptMachineModePrinter: + def __init__(self, gdbval): + self.gdbval = gdbval + + def to_string (self): + name = str(self.gdbval['m_mode']) + if name == 'E_VOIDmode': + return '' + return name[2:] if name.startswith('E_') else name + +###################################################################### + # TODO: # * hashtab # * location_t @@ -518,6 +530,9 @@ def build_pretty_printer(): 'vec', VecPrinter) + pp.add_printer_for_regex(r'opt_mode<(\S+)>', + 'opt_mode', OptMachineModePrinter) + return pp gdb.printing.register_pretty_printer( diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 2b72367a1d3..8ac4f6a9826 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1460,14 +1460,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, struct separate_ops ops; int prec = GET_MODE_PRECISION (mode); machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1); + machine_mode wmode; ops.op0 = make_tree (type, op0); ops.op1 = make_tree (type, op1); ops.op2 = NULL_TREE; ops.location = loc; - if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode - && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode))) + if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode) + && targetm.scalar_mode_supported_p (wmode)) { - machine_mode wmode = GET_MODE_2XWIDER_MODE (mode); ops.code = WIDEN_MULT_EXPR; ops.type = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns); diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 422b4913b4a..ac19e8f52ad 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -266,7 +266,7 @@ init_lower_subreg (void) memset (this_target_lower_subreg, 0, sizeof (*this_target_lower_subreg)); - twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode); + twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode).require (); rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index ee85efc9754..51d9a7b222b 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1636,7 +1636,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data) : GET_CLASS_NARROWEST_MODE (mclass); pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode; pass ? mr = (machine_mode) (mr + 1) - : mr = GET_MODE_WIDER_MODE (mr)) + : mr = GET_MODE_WIDER_MODE (mr).else_void ()) if (GET_MODE_CLASS (mr) != mclass || GET_MODE_SIZE (mr) != size || GET_MODE_PRECISION (mr) != prec diff --git a/gcc/machmode.h b/gcc/machmode.h index c272888ebf1..3b06f6d2c3c 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 +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 bool exists (U *) const; + +private: + machine_mode m_mode; +}; + +/* If the object contains a T, return its enum value, otherwise return + E_VOIDmode. */ + +template +ALWAYS_INLINE machine_mode +opt_mode::else_void () const +{ + return m_mode; +} + +/* Assert that the object contains a T and return it. */ + +template +inline T +opt_mode::require () const +{ + gcc_checking_assert (m_mode != E_VOIDmode); + return typename mode_traits::from_int (m_mode); +} + +/* Return true if the object contains a T rather than nothing. */ + +template +ALWAYS_INLINE bool +opt_mode::exists () const +{ + return m_mode != E_VOIDmode; +} + +/* Return true if the object contains a T, storing it in *MODE if so. */ + +template +template +inline bool +opt_mode::exists (U *mode) const +{ + if (m_mode != E_VOIDmode) + { + *mode = T (typename mode_traits::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 +ALWAYS_INLINE opt_mode +GET_MODE_WIDER_MODE (const T &m) +{ + return typename opt_mode::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 +ALWAYS_INLINE opt_mode +GET_MODE_2XWIDER_MODE (const T &m) +{ + return typename opt_mode::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 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 (); } } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a36e5f9cbc0..5deb5398c75 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3456,8 +3456,8 @@ omp_clause_aligned_alignment (tree clause) continue; while (vs && GET_MODE_SIZE (vmode) < vs - && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode) - vmode = GET_MODE_2XWIDER_MODE (vmode); + && GET_MODE_2XWIDER_MODE (vmode).exists ()) + vmode = GET_MODE_2XWIDER_MODE (vmode).require (); tree type = lang_hooks.types.type_for_mode (mode, 1); if (type == NULL_TREE || TYPE_MODE (type) != mode) diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c index a3a32b7652c..7b53a465a09 100644 --- a/gcc/optabs-libfuncs.c +++ b/gcc/optabs-libfuncs.c @@ -918,9 +918,10 @@ init_sync_libfuncs_1 (optab tab, const char *base, int max) mode = QImode; for (i = 1; i <= max; i *= 2) { + if (i > 1) + mode = GET_MODE_2XWIDER_MODE (mode).require (); buf[len + 1] = '0' + i; set_optab_libfunc (tab, mode, buf); - mode = GET_MODE_2XWIDER_MODE (mode); } } diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c index ad22f07a395..021d8160cf4 100644 --- a/gcc/optabs-query.c +++ b/gcc/optabs-query.c @@ -425,7 +425,7 @@ find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, for (; (permit_non_widening || from_mode != to_mode) && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode) && from_mode != VOIDmode; - from_mode = GET_MODE_WIDER_MODE (from_mode)) + from_mode = GET_MODE_WIDER_MODE (from_mode).else_void ()) { enum insn_code handler = widening_optab_handler (op, to_mode, from_mode); diff --git a/gcc/optabs.c b/gcc/optabs.c index ce419d361de..c6ad64b5f8d 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1186,13 +1186,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, takes operands of this mode and makes a wider mode. */ if (binoptab == smul_optab - && GET_MODE_2XWIDER_MODE (mode) != VOIDmode - && (widening_optab_handler ((unsignedp ? umul_widen_optab - : smul_widen_optab), - GET_MODE_2XWIDER_MODE (mode), mode) - != CODE_FOR_nothing)) + && GET_MODE_2XWIDER_MODE (mode).exists (&wider_mode) + && (convert_optab_handler ((unsignedp + ? umul_widen_optab + : smul_widen_optab), + wider_mode, mode) != CODE_FOR_nothing)) { - temp = expand_binop (GET_MODE_2XWIDER_MODE (mode), + temp = expand_binop (wider_mode, unsignedp ? umul_widen_optab : smul_widen_optab, op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT); @@ -1253,14 +1253,14 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, && methods != OPTAB_DIRECT && methods != OPTAB_LIB) FOR_EACH_WIDER_MODE (wider_mode, mode) { + machine_mode next_mode; if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing || (binoptab == smul_optab - && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode + && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode) && (find_widening_optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab), - GET_MODE_WIDER_MODE (wider_mode), - mode, 0) + next_mode, mode, 0) != CODE_FOR_nothing))) { rtx xop0 = op0, xop1 = op1; @@ -3702,7 +3702,7 @@ can_compare_p (enum rtx_code code, machine_mode mode, && optab_handler (cmov_optab, mode) != CODE_FOR_nothing) return 1; - mode = GET_MODE_WIDER_MODE (mode); + mode = GET_MODE_WIDER_MODE (mode).else_void (); PUT_MODE (test, mode); } while (mode != VOIDmode); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 735d86eda0b..157f592ee97 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -5671,13 +5671,15 @@ init_num_sign_bit_copies_in_rep (void) /* Currently, it is assumed that TARGET_MODE_REP_EXTENDED extends to the next widest mode. */ gcc_assert (targetm.mode_rep_extended (mode, in_mode) == UNKNOWN - || GET_MODE_WIDER_MODE (mode) == in_mode); + || GET_MODE_WIDER_MODE (mode).require () == in_mode); /* We are in in_mode. Count how many bits outside of mode have to be copies of the sign-bit. */ FOR_EACH_MODE (i, mode, in_mode) { - machine_mode wider = GET_MODE_WIDER_MODE (i); + /* This must always exist (for the last iteration it will be + IN_MODE). */ + machine_mode wider = GET_MODE_WIDER_MODE (i).require (); if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND /* We can only check sign-bit copies starting from the diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index b85c97de5c3..f69fad8fd75 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2745,7 +2745,8 @@ bit_field_mode_iterator bool bit_field_mode_iterator::next_mode (machine_mode *out_mode) { - for (; m_mode != VOIDmode; m_mode = GET_MODE_WIDER_MODE (m_mode)) + for (; m_mode != VOIDmode; + m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ()) { unsigned int unit = GET_MODE_BITSIZE (m_mode); @@ -2782,7 +2783,7 @@ bit_field_mode_iterator::next_mode (machine_mode *out_mode) break; *out_mode = m_mode; - m_mode = GET_MODE_WIDER_MODE (m_mode); + m_mode = GET_MODE_WIDER_MODE (m_mode).else_void (); m_count++; return true; } diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 0b1c880ecef..e6b7dbdf100 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3283,8 +3283,8 @@ convert_mult_to_widen (gimple *stmt, gimple_stmt_iterator *gsi) || (TYPE_UNSIGNED (type2) && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) { - from_mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) + if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode) + || GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) return false; } @@ -3465,8 +3465,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple *stmt, || (from_unsigned2 && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) { - from_mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode)) + if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode) + || GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode)) return false; } diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 85d6816d119..9f88869fbf9 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -1088,8 +1088,7 @@ array_value_type (gswitch *swtch, tree type, int num, if (sign == 1) sign = 0; - mode = GET_MODE_WIDER_MODE (mode); - if (mode == VOIDmode + if (!GET_MODE_WIDER_MODE (mode).exists (&mode) || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (type_mode)) return type; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index e1038a10b7a..268969700b6 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -10120,7 +10120,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, else { mode = GET_CLASS_NARROWEST_MODE (MODE_INT); - do + for (;;) { /* If we cannot do a signed conversion to float from mode or if the value-range does not fit in the signed type @@ -10129,15 +10129,12 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED)) break; - mode = GET_MODE_WIDER_MODE (mode); /* But do not widen the input. Instead leave that to the optabs expansion code. */ - if (GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1))) + if (!GET_MODE_WIDER_MODE (mode).exists (&mode) + || GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1))) return false; } - while (mode != VOIDmode); - if (mode == VOIDmode) - return false; } /* It works, insert a truncation or sign-change before the diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index b107ab491aa..0721771a69d 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -8706,12 +8706,11 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data) last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); /* Attempt to merge adjacent registers or memory. */ - wider_mode = GET_MODE_WIDER_MODE (mode); for (j = i + 1; j < var->n_var_parts; j++) if (last_limit <= VAR_PART_OFFSET (var, j)) break; if (j < var->n_var_parts - && wider_mode != VOIDmode + && GET_MODE_WIDER_MODE (mode).exists (&wider_mode) && var->var_part[j].cur_loc && mode == GET_MODE (var->var_part[j].cur_loc) && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts])) -- 2.11.4.GIT