Message ID | 87fue0n317.fsf@linaro.org |
---|---|
State | New |
Headers | show |
Series | Add wrapper classes for machine_modes | expand |
On 07/13/2017 02:40 AM, Richard Sandiford wrote: > 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-07-13 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::operator *): 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. I'm not a big fan of the API here, particularly using operator* to handle asserting the mode exists. I'd prefer to just use a member function rather than overloading operator*. What's the rationale behind using operator* to imply the assertion? THe changes themsleves look fine, it's really just a question of the API we present. jeff
Jeff Law <law@redhat.com> writes: > On 07/13/2017 02:40 AM, Richard Sandiford wrote: >> 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-07-13 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::operator *): 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. > I'm not a big fan of the API here, particularly using operator* to > handle asserting the mode exists. I'd prefer to just use a member > function rather than overloading operator*. > > What's the rationale behind using operator* to imply the assertion? > > THe changes themsleves look fine, it's really just a question of the API > we present. The original idea was to make opt_mode look pointer-ish, so that the dyn_cast <...> result could be used in the same way as for dyn_cast <gassign *> etc. The first cut therefore had operator bool () to test whether there was a mode and operator * to dereference it. However, operator bool () created various subtle problems (as it always seems to) so we dropped it in favour of exists (). I was neutral on whether we should keep '*' or switch to a function, so in the end the status quo won out. I'm happy to change it to a named accessor though. Any better ideas than "get ()" for the name? Maybe something to emphasis that it is asserting for non-nullness/non-emptiness (which '*' does implicitly)? Thanks, Richard
On 08/11/2017 12:24 PM, Richard Sandiford wrote: > Jeff Law <law@redhat.com> writes: >> On 07/13/2017 02:40 AM, Richard Sandiford wrote: >>> 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-07-13 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::operator *): 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. >> I'm not a big fan of the API here, particularly using operator* to >> handle asserting the mode exists. I'd prefer to just use a member >> function rather than overloading operator*. >> >> What's the rationale behind using operator* to imply the assertion? >> >> THe changes themsleves look fine, it's really just a question of the API >> we present. > > The original idea was to make opt_mode look pointer-ish, so that > the dyn_cast <...> result could be used in the same way as for > dyn_cast <gassign *> etc. The first cut therefore had operator bool () > to test whether there was a mode and operator * to dereference it. > > However, operator bool () created various subtle problems (as it always > seems to) so we dropped it in favour of exists (). I was neutral > on whether we should keep '*' or switch to a function, so in the > end the status quo won out. I'm happy to change it to a named > accessor though. > > Any better ideas than "get ()" for the name? Maybe something > to emphasis that it is asserting for non-nullness/non-emptiness > (which '*' does implicitly)?Yea, when I was reading the first few patches it felt like you trying to do a pointer-ish API. I think we should avoid the operator overload. It's not real obvious what's going on and I think our guidelines generally discourage operator overloading. Sadly I think it's going to require a lot of mechanical changes, but better to do it now than go back later and do it. As for the name, get_nonvoid? Ugh. Not sure. Open to suggestions. jeff
Jeff Law <law@redhat.com> writes: > On 08/11/2017 12:24 PM, Richard Sandiford wrote: >> Jeff Law <law@redhat.com> writes: >>> On 07/13/2017 02:40 AM, Richard Sandiford wrote: >>>> 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-07-13 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::operator *): 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. >>> I'm not a big fan of the API here, particularly using operator* to >>> handle asserting the mode exists. I'd prefer to just use a member >>> function rather than overloading operator*. >>> >>> What's the rationale behind using operator* to imply the assertion? >>> >>> THe changes themsleves look fine, it's really just a question of the API >>> we present. >> >> The original idea was to make opt_mode look pointer-ish, so that >> the dyn_cast <...> result could be used in the same way as for >> dyn_cast <gassign *> etc. The first cut therefore had operator bool () >> to test whether there was a mode and operator * to dereference it. >> >> However, operator bool () created various subtle problems (as it always >> seems to) so we dropped it in favour of exists (). I was neutral >> on whether we should keep '*' or switch to a function, so in the >> end the status quo won out. I'm happy to change it to a named >> accessor though. >> >> Any better ideas than "get ()" for the name? Maybe something >> to emphasis that it is asserting for non-nullness/non-emptiness >> (which '*' does implicitly)? > > Yea, when I was reading the first few patches it felt like you trying >to do a pointer-ish API. > > I think we should avoid the operator overload. It's not real obvious > what's going on and I think our guidelines generally discourage operator > overloading. Sadly I think it's going to require a lot of mechanical > changes, but better to do it now than go back later and do it. That's OK, it should be a trivial update. > As for the name, get_nonvoid? Ugh. Not sure. Open to suggestions. I'd rather avoid "nonvoid", since the use of VOIDmode for "no mode" is really an implementation detail in things like opt_mode <scalar_int_mode>. Other possiblities might be: - require - demand - mode - get_mode - require_mode - demand_mode - else_fail (to go with else_void and else_blk) - noelse Thanks, Richard
On 08/28/2017 01:05 PM, Richard Sandiford wrote: > >> As for the name, get_nonvoid? Ugh. Not sure. Open to suggestions. > > I'd rather avoid "nonvoid", since the use of VOIDmode for "no mode" is > really an implementation detail in things like opt_mode <scalar_int_mode>. > Other possiblities might be: Yea, good point on encoding the implementation detail not being a good idea. > > - require > - demand > - mode > - get_mode > - require_mode > - demand_mode > - else_fail (to go with else_void and else_blk) > - noelse require, demand with or without the _mode suffix seem good to me. jeff
Jeff Law <law@redhat.com> writes: > On 08/28/2017 01:05 PM, Richard Sandiford wrote: >> >>> As for the name, get_nonvoid? Ugh. Not sure. Open to suggestions. >> >> I'd rather avoid "nonvoid", since the use of VOIDmode for "no mode" is >> really an implementation detail in things like opt_mode <scalar_int_mode>. >> Other possiblities might be: > Yea, good point on encoding the implementation detail not being a good idea. > >> >> - require >> - demand >> - mode >> - get_mode >> - require_mode >> - demand_mode >> - else_fail (to go with else_void and else_blk) >> - noelse > require, demand with or without the _mode suffix seem good to me. OK, here's a patch that uses require (). I've updated the following patches in the obvious way. This does make me want to reconsider another decision though. Using opt_mode for iterators leads to things like: opt_scalar_int_mode wider_mode_iter; FOR_EACH_WIDER_MODE (wider_mode_iter, mode) { scalar_int_mode wider_mode = wider_mode_iter.require (); if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) ... which isn't pretty. It would be easy to support: scalar_int_mode wider_mode; FOR_EACH_WIDER_MODE (wider_mode, mode) if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) ... *but* this would mean that "wider_mode" is accessible but undefined after the loop (unlike the first loop, where wider_mode_iter is guaranteed to be empty if the loop runs to completion). Is that OK? Or is it too suprising? Another alternative would be: opt_scalar_int_mode wider_mode_iter; scalar_int_mode wider_mode; FOR_EACH_WIDER_MODE (wider_mode_iter, wider_mode, mode) if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) ... which gives both. But perhaps this would be odd for plain machine_mode iterators, where there's no obvious distinction between the first and second arguments. Thanks, Richard 2017-08-29 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. Index: gcc/coretypes.h =================================================================== --- gcc/coretypes.h 2017-08-29 15:51:59.126986401 +0100 +++ gcc/coretypes.h 2017-08-29 15:52:16.793375425 +0100 @@ -55,6 +55,7 @@ typedef const struct simple_bitmap_def * struct rtx_def; typedef struct rtx_def *rtx; typedef const struct rtx_def *const_rtx; +template<typename> class opt_mode; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. Index: gcc/machmode.h =================================================================== --- gcc/machmode.h 2017-08-29 15:51:59.315986390 +0100 +++ gcc/machmode.h 2017-08-29 15:52:16.797005080 +0100 @@ -221,6 +221,71 @@ #define CLASS_HAS_WIDER_MODES_P(CLASS) #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 @@ #define GET_MODE_NUNITS(MODE) (mode_to_n /* 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 @@ struct int_n_data_t { 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 @@ struct int_n_data_t { inline void get_2xwider (machine_mode *iter) { - *iter = GET_MODE_2XWIDER_MODE (*iter); + *iter = GET_MODE_2XWIDER_MODE (*iter).else_void (); } } Index: gcc/combine.c =================================================================== --- gcc/combine.c 2017-08-29 15:51:59.308986390 +0100 +++ gcc/combine.c 2017-08-29 15:52:16.787023529 +0100 @@ -7596,10 +7596,7 @@ make_extraction (machine_mode mode, rtx 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; Index: gcc/config/cr16/cr16.h =================================================================== --- gcc/config/cr16/cr16.h 2017-08-29 15:51:59.055986405 +0100 +++ gcc/config/cr16/cr16.h 2017-08-29 15:52:16.787023529 +0100 @@ -197,9 +197,7 @@ #define CALL_USED_REGISTERS /* 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) \ Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c 2017-08-29 15:51:59.318986390 +0100 +++ gcc/rtlanal.c 2017-08-29 15:52:16.798819908 +0100 @@ -5680,13 +5680,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 Index: gcc/config/c6x/c6x.c =================================================================== --- gcc/config/c6x/c6x.c 2017-08-29 15:51:59.252986394 +0100 +++ gcc/config/c6x/c6x.c 2017-08-29 15:52:16.787023529 +0100 @@ -6066,7 +6066,7 @@ c6x_rtx_costs (rtx x, machine_mode mode, /* 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)) Index: gcc/lower-subreg.c =================================================================== --- gcc/lower-subreg.c 2017-08-29 15:51:59.094986403 +0100 +++ gcc/lower-subreg.c 2017-08-29 15:52:16.796097666 +0100 @@ -267,7 +267,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); Index: gcc/optabs-libfuncs.c =================================================================== --- gcc/optabs-libfuncs.c 2017-07-13 09:25:13.387236070 +0100 +++ gcc/optabs-libfuncs.c 2017-08-29 15:52:16.797912494 +0100 @@ -918,9 +918,10 @@ init_sync_libfuncs_1 (optab tab, const c 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); } } Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2017-08-29 15:51:59.312986390 +0100 +++ gcc/config/i386/i386.c 2017-08-29 15:52:16.790653184 +0100 @@ -28543,6 +28543,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx 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; @@ -28636,9 +28637,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx 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.). */ @@ -43523,7 +43524,7 @@ static bool expand_vec_perm_palignr (str 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; @@ -46886,7 +46887,8 @@ expand_vselect_vconcat (rtx target, rtx 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; Index: gcc/config/ia64/ia64.c =================================================================== --- gcc/config/ia64/ia64.c 2017-08-29 15:51:59.261986393 +0100 +++ gcc/config/ia64/ia64.c 2017-08-29 15:52:16.791560598 +0100 @@ -11353,7 +11353,8 @@ expand_vselect_vconcat (rtx target, rtx 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); } Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2017-08-29 15:51:59.265986393 +0100 +++ gcc/config/mips/mips.c 2017-08-29 15:52:16.793375425 +0100 @@ -21134,7 +21134,8 @@ mips_expand_vselect_vconcat (rtx target, 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); } Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-08-29 15:52:16.456724920 +0100 +++ gcc/expmed.c 2017-08-29 15:52:16.793375425 +0100 @@ -207,11 +207,10 @@ init_expmed_one_mode (struct init_expmed 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); @@ -3618,7 +3617,7 @@ extract_high_half (machine_mode mode, rt 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); @@ -3640,7 +3639,7 @@ expmed_mult_highpart_optab (machine_mode 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 @@ -3746,7 +3745,7 @@ expmed_mult_highpart_optab (machine_mode 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; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-08-29 15:51:59.315986390 +0100 +++ gcc/expr.c 2017-08-29 15:52:16.794282839 +0100 @@ -9142,7 +9142,7 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b 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) Index: gcc/lto-streamer-in.c =================================================================== --- gcc/lto-streamer-in.c 2017-08-21 12:14:39.684583630 +0100 +++ gcc/lto-streamer-in.c 2017-08-29 15:52:16.796097666 +0100 @@ -1636,7 +1636,7 @@ lto_input_mode_table (struct lto_file_de : 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 Index: gcc/optabs-query.c =================================================================== --- gcc/optabs-query.c 2017-08-29 15:51:59.316986390 +0100 +++ gcc/optabs-query.c 2017-08-29 15:52:16.797912494 +0100 @@ -425,7 +425,7 @@ find_widening_optab_handler_and_mode (op 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); Index: gcc/stor-layout.c =================================================================== --- gcc/stor-layout.c 2017-08-29 15:51:59.319986390 +0100 +++ gcc/stor-layout.c 2017-08-29 15:52:16.799727321 +0100 @@ -2745,7 +2745,8 @@ fixup_unsigned_type (tree type) 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 (mach 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; } Index: gcc/internal-fn.c =================================================================== --- gcc/internal-fn.c 2017-08-17 09:05:42.895968489 +0100 +++ gcc/internal-fn.c 2017-08-29 15:52:16.796097666 +0100 @@ -1460,14 +1460,14 @@ expand_mul_overflow (location_t loc, tre 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); Index: gcc/omp-low.c =================================================================== --- gcc/omp-low.c 2017-08-29 15:51:59.316986390 +0100 +++ gcc/omp-low.c 2017-08-29 15:52:16.797005080 +0100 @@ -3456,8 +3456,8 @@ omp_clause_aligned_alignment (tree claus 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) Index: gcc/tree-ssa-math-opts.c =================================================================== --- gcc/tree-ssa-math-opts.c 2017-08-29 15:51:59.319986390 +0100 +++ gcc/tree-ssa-math-opts.c 2017-08-29 15:52:16.799727321 +0100 @@ -3283,8 +3283,8 @@ convert_mult_to_widen (gimple *stmt, gim || (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_ || (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; } Index: gcc/tree-switch-conversion.c =================================================================== --- gcc/tree-switch-conversion.c 2017-08-29 15:51:59.329986389 +0100 +++ gcc/tree-switch-conversion.c 2017-08-29 15:52:16.799727321 +0100 @@ -1085,8 +1085,7 @@ array_value_type (gswitch *swtch, tree t 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; } Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c 2017-08-29 15:51:59.321986390 +0100 +++ gcc/var-tracking.c 2017-08-29 15:52:16.801542149 +0100 @@ -8706,12 +8706,11 @@ emit_note_insn_var_location (variable ** 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])) Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c 2017-08-21 15:50:48.665709938 +0100 +++ gcc/tree-vrp.c 2017-08-29 15:52:16.800634735 +0100 @@ -10120,7 +10120,7 @@ simplify_float_conversion_using_ranges ( 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 ( && 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 Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-08-29 15:51:59.317986390 +0100 +++ gcc/optabs.c 2017-08-29 15:52:16.798819908 +0100 @@ -1186,13 +1186,13 @@ expand_binop (machine_mode mode, optab b 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 b && 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, machi && 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); Index: gcc/gdbhooks.py =================================================================== --- gcc/gdbhooks.py 2017-07-13 09:25:13.387236070 +0100 +++ gcc/gdbhooks.py 2017-08-29 15:52:16.796097666 +0100 @@ -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 '<None>' + 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( Index: gcc/ada/gcc-interface/decl.c =================================================================== --- gcc/ada/gcc-interface/decl.c 2017-07-13 09:25:13.387236070 +0100 +++ gcc/ada/gcc-interface/decl.c 2017-08-29 15:52:16.784301288 +0100 @@ -8576,7 +8576,7 @@ validate_size (Uint uint_size, tree gnu_ { 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)); }
On 08/29/2017 09:01 AM, Richard Sandiford wrote: > Jeff Law <law@redhat.com> writes: > > OK, here's a patch that uses require (). I've updated the following > patches in the obvious way. Thanks. > > This does make me want to reconsider another decision though. > Using opt_mode for iterators leads to things like: > > opt_scalar_int_mode wider_mode_iter; > FOR_EACH_WIDER_MODE (wider_mode_iter, mode) > { > scalar_int_mode wider_mode = wider_mode_iter.require (); > if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) > ... > > which isn't pretty. It would be easy to support: No ideal, but it's reasonably explicit in what it does, so I wouldn't expect anyone to be surprised. > > scalar_int_mode wider_mode; > FOR_EACH_WIDER_MODE (wider_mode, mode) > if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) > ... > > *but* this would mean that "wider_mode" is accessible but undefined > after the loop (unlike the first loop, where wider_mode_iter is > guaranteed to be empty if the loop runs to completion). Is that OK? > Or is it too suprising? I think most folks would be surprised that they can't look at wider_mode in a meaningful way after the loop. > > Another alternative would be: > > opt_scalar_int_mode wider_mode_iter; > scalar_int_mode wider_mode; > FOR_EACH_WIDER_MODE (wider_mode_iter, wider_mode, mode) > if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) > ... > > which gives both. But perhaps this would be odd for plain machine_mode > iterators, where there's no obvious distinction between the first and > second arguments. Well, this is like the first to me, except we've separated the iterator from the mode. I slightly prefer the first and think the second is probably too different from the traditional way we think about the state of loop variables after the loop has terminated. Jeff
Jeff Law <law@redhat.com> writes: > On 08/29/2017 09:01 AM, Richard Sandiford wrote: >> Jeff Law <law@redhat.com> writes: >> >> OK, here's a patch that uses require (). I've updated the following >> patches in the obvious way. > Thanks. > >> >> This does make me want to reconsider another decision though. >> Using opt_mode for iterators leads to things like: >> >> opt_scalar_int_mode wider_mode_iter; >> FOR_EACH_WIDER_MODE (wider_mode_iter, mode) >> { >> scalar_int_mode wider_mode = wider_mode_iter.require (); >> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >> ... >> >> which isn't pretty. It would be easy to support: > No ideal, but it's reasonably explicit in what it does, so I wouldn't > expect anyone to be surprised. > > >> >> scalar_int_mode wider_mode; >> FOR_EACH_WIDER_MODE (wider_mode, mode) >> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >> ... >> >> *but* this would mean that "wider_mode" is accessible but undefined >> after the loop (unlike the first loop, where wider_mode_iter is >> guaranteed to be empty if the loop runs to completion). Is that OK? >> Or is it too suprising? > I think most folks would be surprised that they can't look at wider_mode > in a meaningful way after the loop. > >> >> Another alternative would be: >> >> opt_scalar_int_mode wider_mode_iter; >> scalar_int_mode wider_mode; >> FOR_EACH_WIDER_MODE (wider_mode_iter, wider_mode, mode) >> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >> ... >> >> which gives both. But perhaps this would be odd for plain machine_mode >> iterators, where there's no obvious distinction between the first and >> second arguments. > Well, this is like the first to me, except we've separated the iterator > from the mode. > > I slightly prefer the first and think the second is probably too > different from the traditional way we think about the state of loop > variables after the loop has terminated. OK, that's easy then :-) Is OK to apply the approved parts of the series with the "require" change then? If the consensus ends up being that we should handle the iterators a different way, I'll volunteer to do a bulk update. Thanks again for all the reviews. Richard
On 08/29/2017 09:36 AM, Richard Sandiford wrote: > Jeff Law <law@redhat.com> writes: >> On 08/29/2017 09:01 AM, Richard Sandiford wrote: >>> Jeff Law <law@redhat.com> writes: >>> >>> OK, here's a patch that uses require (). I've updated the following >>> patches in the obvious way. >> Thanks. >> >>> >>> This does make me want to reconsider another decision though. >>> Using opt_mode for iterators leads to things like: >>> >>> opt_scalar_int_mode wider_mode_iter; >>> FOR_EACH_WIDER_MODE (wider_mode_iter, mode) >>> { >>> scalar_int_mode wider_mode = wider_mode_iter.require (); >>> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >>> ... >>> >>> which isn't pretty. It would be easy to support: >> No ideal, but it's reasonably explicit in what it does, so I wouldn't >> expect anyone to be surprised. >> >> >>> >>> scalar_int_mode wider_mode; >>> FOR_EACH_WIDER_MODE (wider_mode, mode) >>> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >>> ... >>> >>> *but* this would mean that "wider_mode" is accessible but undefined >>> after the loop (unlike the first loop, where wider_mode_iter is >>> guaranteed to be empty if the loop runs to completion). Is that OK? >>> Or is it too suprising? >> I think most folks would be surprised that they can't look at wider_mode >> in a meaningful way after the loop. >> >>> >>> Another alternative would be: >>> >>> opt_scalar_int_mode wider_mode_iter; >>> scalar_int_mode wider_mode; >>> FOR_EACH_WIDER_MODE (wider_mode_iter, wider_mode, mode) >>> if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) >>> ... >>> >>> which gives both. But perhaps this would be odd for plain machine_mode >>> iterators, where there's no obvious distinction between the first and >>> second arguments. >> Well, this is like the first to me, except we've separated the iterator >> from the mode. >> >> I slightly prefer the first and think the second is probably too >> different from the traditional way we think about the state of loop >> variables after the loop has terminated. > > OK, that's easy then :-) Is OK to apply the approved parts of the > series with the "require" change then? If the consensus ends up > being that we should handle the iterators a different way, I'll > volunteer to do a bulk update. Yea, I think the approved parts are good to go for the trunk. I think that covers the whole series, except the aarch64 backend bits which I left to the ARM folks. > > Thanks again for all the reviews. No problem. Sorry it took so long. jeff
Index: gcc/coretypes.h =================================================================== --- gcc/coretypes.h 2017-07-02 10:05:20.995639436 +0100 +++ gcc/coretypes.h 2017-07-13 09:18:22.924279021 +0100 @@ -55,6 +55,7 @@ typedef const struct simple_bitmap_def * struct rtx_def; typedef struct rtx_def *rtx; typedef const struct rtx_def *const_rtx; +template<typename> class opt_mode; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. Index: gcc/machmode.h =================================================================== --- gcc/machmode.h 2017-07-13 09:18:21.533429040 +0100 +++ gcc/machmode.h 2017-07-13 09:18:22.930278376 +0100 @@ -221,6 +221,72 @@ #define CLASS_HAS_WIDER_MODES_P(CLASS) #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. + operator * gives the T value. */ +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 operator * () 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>::operator * () 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 +418,22 @@ #define GET_MODE_NUNITS(MODE) (mode_to_n /* 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 +572,17 @@ struct int_n_data_t { 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); } /* Set mode iterator *ITER to the mode that is two times wider than the @@ -516,7 +591,7 @@ struct int_n_data_t { inline void get_2xwider (machine_mode *iter) { - *iter = GET_MODE_2XWIDER_MODE (*iter); + *iter = GET_MODE_2XWIDER_MODE (*iter).else_void (); } } Index: gcc/combine.c =================================================================== --- gcc/combine.c 2017-07-13 09:18:21.524430018 +0100 +++ gcc/combine.c 2017-07-13 09:18:22.914280096 +0100 @@ -7617,10 +7617,7 @@ make_extraction (machine_mode mode, rtx 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); } orig_pos = pos; Index: gcc/config/cr16/cr16.h =================================================================== --- gcc/config/cr16/cr16.h 2017-04-18 19:52:36.663792154 +0100 +++ gcc/config/cr16/cr16.h 2017-07-13 09:18:22.915279989 +0100 @@ -197,9 +197,7 @@ #define CALL_USED_REGISTERS /* 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)) == 1) #define HARD_REGNO_NREGS(REGNO, MODE) \ ((REGNO >= CR16_FIRST_DWORD_REGISTER) \ Index: gcc/rtlanal.c =================================================================== --- gcc/rtlanal.c 2017-07-13 09:18:21.536428715 +0100 +++ gcc/rtlanal.c 2017-07-13 09:18:22.937277624 +0100 @@ -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) == 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); if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND /* We can only check sign-bit copies starting from the Index: gcc/config/c6x/c6x.c =================================================================== --- gcc/config/c6x/c6x.c 2017-07-13 09:18:19.037703403 +0100 +++ gcc/config/c6x/c6x.c 2017-07-13 09:18:22.915279989 +0100 @@ -6065,7 +6065,7 @@ c6x_rtx_costs (rtx x, machine_mode mode, /* 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) && 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)) Index: gcc/lower-subreg.c =================================================================== --- gcc/lower-subreg.c 2017-05-18 07:51:11.882801135 +0100 +++ gcc/lower-subreg.c 2017-07-13 09:18:22.929278484 +0100 @@ -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); rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2); Index: gcc/optabs-libfuncs.c =================================================================== --- gcc/optabs-libfuncs.c 2017-02-23 19:54:04.000000000 +0000 +++ gcc/optabs-libfuncs.c 2017-07-13 09:18:22.933278054 +0100 @@ -918,9 +918,10 @@ init_sync_libfuncs_1 (optab tab, const c mode = QImode; for (i = 1; i <= max; i *= 2) { + if (i > 1) + mode = *GET_MODE_2XWIDER_MODE (mode); buf[len + 1] = '0' + i; set_optab_libfunc (tab, mode, buf); - mode = GET_MODE_2XWIDER_MODE (mode); } } Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2017-07-13 09:18:21.528429583 +0100 +++ gcc/config/i386/i386.c 2017-07-13 09:18:22.921279344 +0100 @@ -28388,6 +28388,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx 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; @@ -28481,9 +28482,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx 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.). */ @@ -43337,7 +43338,7 @@ static bool expand_vec_perm_palignr (str 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); gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2); gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n)); return n; @@ -46605,7 +46606,8 @@ expand_vselect_vconcat (rtx target, rtx 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; Index: gcc/config/ia64/ia64.c =================================================================== --- gcc/config/ia64/ia64.c 2017-07-13 09:18:19.067700078 +0100 +++ gcc/config/ia64/ia64.c 2017-07-13 09:18:22.922279236 +0100 @@ -11297,7 +11297,8 @@ expand_vselect_vconcat (rtx target, rtx 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); } Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2017-07-13 09:18:19.076699080 +0100 +++ gcc/config/mips/mips.c 2017-07-13 09:18:22.924279021 +0100 @@ -21105,7 +21105,8 @@ mips_expand_vselect_vconcat (rtx target, 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); } Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-07-13 09:18:21.531429258 +0100 +++ gcc/expmed.c 2017-07-13 09:18:22.925278914 +0100 @@ -206,11 +206,10 @@ init_expmed_one_mode (struct init_expmed { FOR_EACH_MODE_IN_CLASS (mode_from, MODE_INT) 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); @@ -3588,7 +3587,7 @@ extract_high_half (machine_mode mode, rt gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); - wider_mode = GET_MODE_WIDER_MODE (mode); + wider_mode = *GET_MODE_WIDER_MODE (mode); op = expand_shift (RSHIFT_EXPR, wider_mode, op, GET_MODE_BITSIZE (mode), 0, 1); return convert_modes (mode, wider_mode, op, 0); @@ -3610,7 +3609,7 @@ expmed_mult_highpart_optab (machine_mode gcc_assert (!SCALAR_FLOAT_MODE_P (mode)); - wider_mode = GET_MODE_WIDER_MODE (mode); + wider_mode = *GET_MODE_WIDER_MODE (mode); size = GET_MODE_BITSIZE (mode); /* Firstly, try using a multiplication insn that only generates the needed @@ -3716,7 +3715,7 @@ expmed_mult_highpart_optab (machine_mode 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); unsigned HOST_WIDE_INT cnst1; int extra_cost; bool sign_adjust = false; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-07-13 09:18:21.532429149 +0100 +++ gcc/expr.c 2017-07-13 09:18:22.928278591 +0100 @@ -9153,7 +9153,7 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b 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) Index: gcc/lto-streamer-in.c =================================================================== --- gcc/lto-streamer-in.c 2017-06-30 12:50:38.331658620 +0100 +++ gcc/lto-streamer-in.c 2017-07-13 09:18:22.930278376 +0100 @@ -1593,7 +1593,7 @@ lto_input_mode_table (struct lto_file_de : 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 Index: gcc/optabs-query.c =================================================================== --- gcc/optabs-query.c 2017-07-13 09:18:21.534428932 +0100 +++ gcc/optabs-query.c 2017-07-13 09:18:22.934277946 +0100 @@ -425,7 +425,7 @@ find_widening_optab_handler_and_mode (op 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); Index: gcc/stor-layout.c =================================================================== --- gcc/stor-layout.c 2017-07-13 09:18:21.536428715 +0100 +++ gcc/stor-layout.c 2017-07-13 09:18:22.938277517 +0100 @@ -2719,7 +2719,8 @@ fixup_unsigned_type (tree type) 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); @@ -2756,7 +2757,7 @@ bit_field_mode_iterator::next_mode (mach 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; } Index: gcc/internal-fn.c =================================================================== --- gcc/internal-fn.c 2017-07-08 11:37:46.037390715 +0100 +++ gcc/internal-fn.c 2017-07-13 09:18:22.929278484 +0100 @@ -1446,14 +1446,14 @@ expand_mul_overflow (location_t loc, tre 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); Index: gcc/omp-low.c =================================================================== --- gcc/omp-low.c 2017-07-13 09:18:21.533429040 +0100 +++ gcc/omp-low.c 2017-07-13 09:18:22.933278054 +0100 @@ -3452,8 +3452,8 @@ omp_clause_aligned_alignment (tree claus 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); tree type = lang_hooks.types.type_for_mode (mode, 1); if (type == NULL_TREE || TYPE_MODE (type) != mode) Index: gcc/tree-ssa-math-opts.c =================================================================== --- gcc/tree-ssa-math-opts.c 2017-07-13 09:18:21.537428606 +0100 +++ gcc/tree-ssa-math-opts.c 2017-07-13 09:18:22.939277409 +0100 @@ -3160,8 +3160,8 @@ convert_mult_to_widen (gimple *stmt, gim || (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; } @@ -3342,8 +3342,8 @@ convert_plusminus_to_widen (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; } Index: gcc/tree-switch-conversion.c =================================================================== --- gcc/tree-switch-conversion.c 2017-07-13 09:18:22.307345334 +0100 +++ gcc/tree-switch-conversion.c 2017-07-13 09:18:22.939277409 +0100 @@ -1085,8 +1085,7 @@ array_value_type (gswitch *swtch, tree t 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; } Index: gcc/var-tracking.c =================================================================== --- gcc/var-tracking.c 2017-07-13 09:18:21.539428389 +0100 +++ gcc/var-tracking.c 2017-07-13 09:18:22.945276764 +0100 @@ -8706,12 +8706,11 @@ emit_note_insn_var_location (variable ** 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])) Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c 2017-07-05 16:25:08.469709143 +0100 +++ gcc/tree-vrp.c 2017-07-13 09:18:22.943276979 +0100 @@ -10115,7 +10115,7 @@ simplify_float_conversion_using_ranges ( 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 @@ -10124,15 +10124,12 @@ simplify_float_conversion_using_ranges ( && 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 Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-07-13 09:18:21.534428932 +0100 +++ gcc/optabs.c 2017-07-13 09:18:22.935277839 +0100 @@ -1185,13 +1185,13 @@ expand_binop (machine_mode mode, optab b 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); @@ -1252,14 +1252,14 @@ expand_binop (machine_mode mode, optab b && 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; @@ -3701,7 +3701,7 @@ can_compare_p (enum rtx_code code, machi && 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); Index: gcc/gdbhooks.py =================================================================== --- gcc/gdbhooks.py 2017-02-23 19:54:12.000000000 +0000 +++ gcc/gdbhooks.py 2017-07-13 09:18:22.928278591 +0100 @@ -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 '<None>' + 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( Index: gcc/ada/gcc-interface/decl.c =================================================================== --- gcc/ada/gcc-interface/decl.c 2017-06-22 12:22:56.063377521 +0100 +++ gcc/ada/gcc-interface/decl.c 2017-07-13 09:18:22.913280204 +0100 @@ -8576,7 +8576,7 @@ validate_size (Uint uint_size, tree gnu_ { 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); type_size = bitsize_int (GET_MODE_BITSIZE (p_mode)); }