[04/77] Add FOR_EACH iterators for modes

Message ID 87o9son32j.fsf@linaro.org
State New
Headers show
Series
  • Add wrapper classes for machine_modes
Related show

Commit Message

Richard Sandiford July 13, 2017, 8:39 a.m.
The new iterators are:

- FOR_EACH_MODE_IN_CLASS: iterate over all the modes in a mode class.

- FOR_EACH_MODE_FROM: iterate over all the modes in a class,
  starting at a given mode.

- FOR_EACH_WIDER_MODE: iterate over all the modes in a class,
  starting at the next widest mode after a given mode.

- FOR_EACH_2XWIDER_MODE: same, but considering only modes that
  are two times wider than the previous mode.

- FOR_EACH_MODE_UNTIL: iterate over all the modes in a class until
  a given mode is reached.

- FOR_EACH_MODE: iterate over all the modes in a class between
  two given modes, inclusive of the first but not the second.

These help with the stronger type checking added by later patches,
since every new mode will be in the same class as the previous one.

2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

gcc/
	* machmode.h (mode_traits): New structure.
	(get_narrowest_mode): New function.
	(mode_iterator::start): Likewise.
	(mode_iterator::iterate_p): Likewise.
	(mode_iterator::get_wider): Likewise.
	(mode_iterator::get_known_wider): Likewise.
	(mode_iterator::get_2xwider): Likewise.
	(FOR_EACH_MODE_IN_CLASS): New mode iterator.
	(FOR_EACH_MODE): Likewise.
	(FOR_EACH_MODE_FROM): Likewise.
	(FOR_EACH_MODE_UNTIL): Likewise.
	(FOR_EACH_WIDER_MODE): Likewise.
	(FOR_EACH_2XWIDER_MODE): Likewise.
	* builtins.c (expand_builtin_strlen): Use new mode iterators.
	* combine.c (simplify_comparison): Likewise
	* config/i386/i386.c (type_natural_mode): Likewise.
	* cse.c (cse_insn): Likewise.
	* dse.c (find_shift_sequence): Likewise.
	* emit-rtl.c (init_derived_machine_modes): Likewise.
	(init_emit_once): Likewise.
	* explow.c (hard_function_value): Likewise.
	* expmed.c (init_expmed_one_mode): Likewise.
	(extract_fixed_bit_field_1): Likewise.
	(extract_bit_field_1): Likewise.
	(expand_divmod): Likewise.
	(emit_store_flag_1): Likewise.
	* expr.c (init_expr_target): Likewise.
	(convert_move): Likewise.
	(alignment_for_piecewise_move): Likewise.
	(widest_int_mode_for_size): Likewise.
	(emit_block_move_via_movmem): Likewise.
	(copy_blkmode_to_reg): Likewise.
	(set_storage_via_setmem): Likewise.
	(compress_float_constant): Likewise.
	* omp-low.c (omp_clause_aligned_alignment): Likewise.
	* optabs-query.c (get_best_extraction_insn): Likewise.
	* optabs.c (expand_binop): Likewise.
	(expand_twoval_unop): Likewise.
	(expand_twoval_binop): Likewise.
	(widen_leading): Likewise.
	(widen_bswap): Likewise.
	(expand_parity): Likewise.
	(expand_unop): Likewise.
	(prepare_cmp_insn): Likewise.
	(prepare_float_lib_cmp): Likewise.
	(expand_float): Likewise.
	(expand_fix): Likewise.
	(expand_sfix_optab): Likewise.
	* postreload.c (move2add_use_add2_insn): Likewise.
	* reg-stack.c (reg_to_stack): Likewise.
	* reginfo.c (choose_hard_reg_mode): Likewise.
	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.
	* stmt.c (emit_case_decision_tree): Likewise.
	* stor-layout.c (mode_for_size): Likewise.
	(smallest_mode_for_size): Likewise.
	(mode_for_vector): Likewise.
	(finish_bitfield_representative): Likewise.
	* tree-ssa-math-opts.c (target_supports_divmod_p): Likewise.
	* tree-vect-generic.c (type_for_widest_vector_mode): Likewise.
	* tree-vect-stmts.c (vectorizable_conversion): Likewise.
	* var-tracking.c (prepare_call_arguments): Likewise.

gcc/ada/
	* gcc-interface/misc.c (fp_prec_to_size): Use new mode iterators.
	(fp_size_to_prec): Likewise.

gcc/c-family/
	* c-common.c (c_common_fixed_point_type_for_size): Use new mode
	iterators.
	* c-cppbuiltin.c (c_cpp_builtins): Likewise.

Comments

Jeff Law Aug. 11, 2017, 5 p.m. | #1
On 07/13/2017 02:39 AM, Richard Sandiford wrote:
> The new iterators are:

> 

> - FOR_EACH_MODE_IN_CLASS: iterate over all the modes in a mode class.

> 

> - FOR_EACH_MODE_FROM: iterate over all the modes in a class,

>   starting at a given mode.

> 

> - FOR_EACH_WIDER_MODE: iterate over all the modes in a class,

>   starting at the next widest mode after a given mode.

> 

> - FOR_EACH_2XWIDER_MODE: same, but considering only modes that

>   are two times wider than the previous mode.

> 

> - FOR_EACH_MODE_UNTIL: iterate over all the modes in a class until

>   a given mode is reached.

> 

> - FOR_EACH_MODE: iterate over all the modes in a class between

>   two given modes, inclusive of the first but not the second.

> 

> These help with the stronger type checking added by later patches,

> since every new mode will be in the same class as the previous one.

> 

> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

>             Alan Hayward  <alan.hayward@arm.com>

>             David Sherwood  <david.sherwood@arm.com>

> 

> gcc/

> 	* machmode.h (mode_traits): New structure.

> 	(get_narrowest_mode): New function.

> 	(mode_iterator::start): Likewise.

> 	(mode_iterator::iterate_p): Likewise.

> 	(mode_iterator::get_wider): Likewise.

> 	(mode_iterator::get_known_wider): Likewise.

> 	(mode_iterator::get_2xwider): Likewise.

> 	(FOR_EACH_MODE_IN_CLASS): New mode iterator.

> 	(FOR_EACH_MODE): Likewise.

> 	(FOR_EACH_MODE_FROM): Likewise.

> 	(FOR_EACH_MODE_UNTIL): Likewise.

> 	(FOR_EACH_WIDER_MODE): Likewise.

> 	(FOR_EACH_2XWIDER_MODE): Likewise.

> 	* builtins.c (expand_builtin_strlen): Use new mode iterators.

> 	* combine.c (simplify_comparison): Likewise

> 	* config/i386/i386.c (type_natural_mode): Likewise.

> 	* cse.c (cse_insn): Likewise.

> 	* dse.c (find_shift_sequence): Likewise.

> 	* emit-rtl.c (init_derived_machine_modes): Likewise.

> 	(init_emit_once): Likewise.

> 	* explow.c (hard_function_value): Likewise.

> 	* expmed.c (init_expmed_one_mode): Likewise.

> 	(extract_fixed_bit_field_1): Likewise.

> 	(extract_bit_field_1): Likewise.

> 	(expand_divmod): Likewise.

> 	(emit_store_flag_1): Likewise.

> 	* expr.c (init_expr_target): Likewise.

> 	(convert_move): Likewise.

> 	(alignment_for_piecewise_move): Likewise.

> 	(widest_int_mode_for_size): Likewise.

> 	(emit_block_move_via_movmem): Likewise.

> 	(copy_blkmode_to_reg): Likewise.

> 	(set_storage_via_setmem): Likewise.

> 	(compress_float_constant): Likewise.

> 	* omp-low.c (omp_clause_aligned_alignment): Likewise.

> 	* optabs-query.c (get_best_extraction_insn): Likewise.

> 	* optabs.c (expand_binop): Likewise.

> 	(expand_twoval_unop): Likewise.

> 	(expand_twoval_binop): Likewise.

> 	(widen_leading): Likewise.

> 	(widen_bswap): Likewise.

> 	(expand_parity): Likewise.

> 	(expand_unop): Likewise.

> 	(prepare_cmp_insn): Likewise.

> 	(prepare_float_lib_cmp): Likewise.

> 	(expand_float): Likewise.

> 	(expand_fix): Likewise.

> 	(expand_sfix_optab): Likewise.

> 	* postreload.c (move2add_use_add2_insn): Likewise.

> 	* reg-stack.c (reg_to_stack): Likewise.

> 	* reginfo.c (choose_hard_reg_mode): Likewise.

> 	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.

> 	* stmt.c (emit_case_decision_tree): Likewise.

> 	* stor-layout.c (mode_for_size): Likewise.

> 	(smallest_mode_for_size): Likewise.

> 	(mode_for_vector): Likewise.

> 	(finish_bitfield_representative): Likewise.

> 	* tree-ssa-math-opts.c (target_supports_divmod_p): Likewise.

> 	* tree-vect-generic.c (type_for_widest_vector_mode): Likewise.

> 	* tree-vect-stmts.c (vectorizable_conversion): Likewise.

> 	* var-tracking.c (prepare_call_arguments): Likewise.

> 

> gcc/ada/

> 	* gcc-interface/misc.c (fp_prec_to_size): Use new mode iterators.

> 	(fp_size_to_prec): Likewise.

> 

> gcc/c-family/

> 	* c-common.c (c_common_fixed_point_type_for_size): Use new mode

> 	iterators.

> 	* c-cppbuiltin.c (c_cpp_builtins): Likewise.

So in some cases I see that we have loops like this:

for (; mode != VOIDmode; mode = GET_WIDER_MODE (mode))

Which iterates from the current mode through all the remaining modes,
with each iteration using a wider mode than the previous iteration.
GET_WIDER_MODE is always going to give us something in the same class or
VOIDmode.

This is getting translated into:

FOR_EACH_MODE_FROM (mode, mode)

The two loops have different steps.  The original steps to a wider mode
each iteration.  The new one may step to a different mode of the same
width IIUC.

Am I missing something here?

I realize you won't want to use FOR_EACH_WIDER_MODE since that's got a
different starting point.  But we might want to have an iterator that
starts at the current mode, but steps to the net wider mode within the
class.  That would match the existing loops in several places and would
avoid having to review each one of those use cases to ensure that the
difference in steps isn't important.

Thoughts?  Am I missing something?

jeff
Richard Sandiford Aug. 11, 2017, 5:16 p.m. | #2
Hi Jeff,

First, many thanks for the reviews!

Jeff Law <law@redhat.com> writes:
> On 07/13/2017 02:39 AM, Richard Sandiford wrote:

>> The new iterators are:

>> 

>> - FOR_EACH_MODE_IN_CLASS: iterate over all the modes in a mode class.

>> 

>> - FOR_EACH_MODE_FROM: iterate over all the modes in a class,

>>   starting at a given mode.

>> 

>> - FOR_EACH_WIDER_MODE: iterate over all the modes in a class,

>>   starting at the next widest mode after a given mode.

>> 

>> - FOR_EACH_2XWIDER_MODE: same, but considering only modes that

>>   are two times wider than the previous mode.

>> 

>> - FOR_EACH_MODE_UNTIL: iterate over all the modes in a class until

>>   a given mode is reached.

>> 

>> - FOR_EACH_MODE: iterate over all the modes in a class between

>>   two given modes, inclusive of the first but not the second.

>> 

>> These help with the stronger type checking added by later patches,

>> since every new mode will be in the same class as the previous one.

>> 

>> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

>>             Alan Hayward  <alan.hayward@arm.com>

>>             David Sherwood  <david.sherwood@arm.com>

>> 

>> gcc/

>> 	* machmode.h (mode_traits): New structure.

>> 	(get_narrowest_mode): New function.

>> 	(mode_iterator::start): Likewise.

>> 	(mode_iterator::iterate_p): Likewise.

>> 	(mode_iterator::get_wider): Likewise.

>> 	(mode_iterator::get_known_wider): Likewise.

>> 	(mode_iterator::get_2xwider): Likewise.

>> 	(FOR_EACH_MODE_IN_CLASS): New mode iterator.

>> 	(FOR_EACH_MODE): Likewise.

>> 	(FOR_EACH_MODE_FROM): Likewise.

>> 	(FOR_EACH_MODE_UNTIL): Likewise.

>> 	(FOR_EACH_WIDER_MODE): Likewise.

>> 	(FOR_EACH_2XWIDER_MODE): Likewise.

>> 	* builtins.c (expand_builtin_strlen): Use new mode iterators.

>> 	* combine.c (simplify_comparison): Likewise

>> 	* config/i386/i386.c (type_natural_mode): Likewise.

>> 	* cse.c (cse_insn): Likewise.

>> 	* dse.c (find_shift_sequence): Likewise.

>> 	* emit-rtl.c (init_derived_machine_modes): Likewise.

>> 	(init_emit_once): Likewise.

>> 	* explow.c (hard_function_value): Likewise.

>> 	* expmed.c (init_expmed_one_mode): Likewise.

>> 	(extract_fixed_bit_field_1): Likewise.

>> 	(extract_bit_field_1): Likewise.

>> 	(expand_divmod): Likewise.

>> 	(emit_store_flag_1): Likewise.

>> 	* expr.c (init_expr_target): Likewise.

>> 	(convert_move): Likewise.

>> 	(alignment_for_piecewise_move): Likewise.

>> 	(widest_int_mode_for_size): Likewise.

>> 	(emit_block_move_via_movmem): Likewise.

>> 	(copy_blkmode_to_reg): Likewise.

>> 	(set_storage_via_setmem): Likewise.

>> 	(compress_float_constant): Likewise.

>> 	* omp-low.c (omp_clause_aligned_alignment): Likewise.

>> 	* optabs-query.c (get_best_extraction_insn): Likewise.

>> 	* optabs.c (expand_binop): Likewise.

>> 	(expand_twoval_unop): Likewise.

>> 	(expand_twoval_binop): Likewise.

>> 	(widen_leading): Likewise.

>> 	(widen_bswap): Likewise.

>> 	(expand_parity): Likewise.

>> 	(expand_unop): Likewise.

>> 	(prepare_cmp_insn): Likewise.

>> 	(prepare_float_lib_cmp): Likewise.

>> 	(expand_float): Likewise.

>> 	(expand_fix): Likewise.

>> 	(expand_sfix_optab): Likewise.

>> 	* postreload.c (move2add_use_add2_insn): Likewise.

>> 	* reg-stack.c (reg_to_stack): Likewise.

>> 	* reginfo.c (choose_hard_reg_mode): Likewise.

>> 	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.

>> 	* stmt.c (emit_case_decision_tree): Likewise.

>> 	* stor-layout.c (mode_for_size): Likewise.

>> 	(smallest_mode_for_size): Likewise.

>> 	(mode_for_vector): Likewise.

>> 	(finish_bitfield_representative): Likewise.

>> 	* tree-ssa-math-opts.c (target_supports_divmod_p): Likewise.

>> 	* tree-vect-generic.c (type_for_widest_vector_mode): Likewise.

>> 	* tree-vect-stmts.c (vectorizable_conversion): Likewise.

>> 	* var-tracking.c (prepare_call_arguments): Likewise.

>> 

>> gcc/ada/

>> 	* gcc-interface/misc.c (fp_prec_to_size): Use new mode iterators.

>> 	(fp_size_to_prec): Likewise.

>> 

>> gcc/c-family/

>> 	* c-common.c (c_common_fixed_point_type_for_size): Use new mode

>> 	iterators.

>> 	* c-cppbuiltin.c (c_cpp_builtins): Likewise.

> So in some cases I see that we have loops like this:

>

> for (; mode != VOIDmode; mode = GET_WIDER_MODE (mode))

>

> Which iterates from the current mode through all the remaining modes,

> with each iteration using a wider mode than the previous iteration.

> GET_WIDER_MODE is always going to give us something in the same class or

> VOIDmode.

>

> This is getting translated into:

>

> FOR_EACH_MODE_FROM (mode, mode)

>

> The two loops have different steps.  The original steps to a wider mode

> each iteration.  The new one may step to a different mode of the same

> width IIUC.

>

> Am I missing something here?


The new iterators use GET_MODE_WIDER or GET_MODE_2XWIDER to step,
and the patch is only supposed to convert loops that have matching steps.
It wasn't supposed to convert loops that step through modes as numerical
values, but I see now that I fluffed it with:


Sorry about that!  Will fix.

[Maybe in this case the change is safe, since I'm not sure we support
multiple full-integer modes with the same width.  It's still too subtle
for a mechanical change like this though.]

Is that patch OK with that hunk removed?

Thanks,
Richard

> I realize you won't want to use FOR_EACH_WIDER_MODE since that's got a

> different starting point.  But we might want to have an iterator that

> starts at the current mode, but steps to the net wider mode within the

> class.  That would match the existing loops in several places and would

> avoid having to review each one of those use cases to ensure that the

> difference in steps isn't important.

>

> Thoughts?  Am I missing something?

>

> jeffIndex: gcc/expmed.c

===================================================================
--- gcc/expmed.c	2017-07-13 09:17:39.972572368 +0100
+++ gcc/expmed.c	2017-07-13 09:18:21.531429258 +0100
@@ -204,8 +204,7 @@ init_expmed_one_mode (struct init_expmed
 
   if (SCALAR_INT_MODE_P (mode))
     {
-      for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;
-	   mode_from = (machine_mode)(mode_from + 1))
+      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)

Jeff Law Aug. 11, 2017, 5:29 p.m. | #3
On 08/11/2017 11:16 AM, Richard Sandiford wrote:
> Hi Jeff,

> 

> First, many thanks for the reviews!

> 

> Jeff Law <law@redhat.com> writes:

>> On 07/13/2017 02:39 AM, Richard Sandiford wrote:

>>> The new iterators are:

>>>

>>> - FOR_EACH_MODE_IN_CLASS: iterate over all the modes in a mode class.

>>>

>>> - FOR_EACH_MODE_FROM: iterate over all the modes in a class,

>>>   starting at a given mode.

>>>

>>> - FOR_EACH_WIDER_MODE: iterate over all the modes in a class,

>>>   starting at the next widest mode after a given mode.

>>>

>>> - FOR_EACH_2XWIDER_MODE: same, but considering only modes that

>>>   are two times wider than the previous mode.

>>>

>>> - FOR_EACH_MODE_UNTIL: iterate over all the modes in a class until

>>>   a given mode is reached.

>>>

>>> - FOR_EACH_MODE: iterate over all the modes in a class between

>>>   two given modes, inclusive of the first but not the second.

>>>

>>> These help with the stronger type checking added by later patches,

>>> since every new mode will be in the same class as the previous one.

>>>

>>> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

>>>             Alan Hayward  <alan.hayward@arm.com>

>>>             David Sherwood  <david.sherwood@arm.com>

>>>

>>> gcc/

>>> 	* machmode.h (mode_traits): New structure.

>>> 	(get_narrowest_mode): New function.

>>> 	(mode_iterator::start): Likewise.

>>> 	(mode_iterator::iterate_p): Likewise.

>>> 	(mode_iterator::get_wider): Likewise.

>>> 	(mode_iterator::get_known_wider): Likewise.

>>> 	(mode_iterator::get_2xwider): Likewise.

>>> 	(FOR_EACH_MODE_IN_CLASS): New mode iterator.

>>> 	(FOR_EACH_MODE): Likewise.

>>> 	(FOR_EACH_MODE_FROM): Likewise.

>>> 	(FOR_EACH_MODE_UNTIL): Likewise.

>>> 	(FOR_EACH_WIDER_MODE): Likewise.

>>> 	(FOR_EACH_2XWIDER_MODE): Likewise.

>>> 	* builtins.c (expand_builtin_strlen): Use new mode iterators.

>>> 	* combine.c (simplify_comparison): Likewise

>>> 	* config/i386/i386.c (type_natural_mode): Likewise.

>>> 	* cse.c (cse_insn): Likewise.

>>> 	* dse.c (find_shift_sequence): Likewise.

>>> 	* emit-rtl.c (init_derived_machine_modes): Likewise.

>>> 	(init_emit_once): Likewise.

>>> 	* explow.c (hard_function_value): Likewise.

>>> 	* expmed.c (init_expmed_one_mode): Likewise.

>>> 	(extract_fixed_bit_field_1): Likewise.

>>> 	(extract_bit_field_1): Likewise.

>>> 	(expand_divmod): Likewise.

>>> 	(emit_store_flag_1): Likewise.

>>> 	* expr.c (init_expr_target): Likewise.

>>> 	(convert_move): Likewise.

>>> 	(alignment_for_piecewise_move): Likewise.

>>> 	(widest_int_mode_for_size): Likewise.

>>> 	(emit_block_move_via_movmem): Likewise.

>>> 	(copy_blkmode_to_reg): Likewise.

>>> 	(set_storage_via_setmem): Likewise.

>>> 	(compress_float_constant): Likewise.

>>> 	* omp-low.c (omp_clause_aligned_alignment): Likewise.

>>> 	* optabs-query.c (get_best_extraction_insn): Likewise.

>>> 	* optabs.c (expand_binop): Likewise.

>>> 	(expand_twoval_unop): Likewise.

>>> 	(expand_twoval_binop): Likewise.

>>> 	(widen_leading): Likewise.

>>> 	(widen_bswap): Likewise.

>>> 	(expand_parity): Likewise.

>>> 	(expand_unop): Likewise.

>>> 	(prepare_cmp_insn): Likewise.

>>> 	(prepare_float_lib_cmp): Likewise.

>>> 	(expand_float): Likewise.

>>> 	(expand_fix): Likewise.

>>> 	(expand_sfix_optab): Likewise.

>>> 	* postreload.c (move2add_use_add2_insn): Likewise.

>>> 	* reg-stack.c (reg_to_stack): Likewise.

>>> 	* reginfo.c (choose_hard_reg_mode): Likewise.

>>> 	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.

>>> 	* stmt.c (emit_case_decision_tree): Likewise.

>>> 	* stor-layout.c (mode_for_size): Likewise.

>>> 	(smallest_mode_for_size): Likewise.

>>> 	(mode_for_vector): Likewise.

>>> 	(finish_bitfield_representative): Likewise.

>>> 	* tree-ssa-math-opts.c (target_supports_divmod_p): Likewise.

>>> 	* tree-vect-generic.c (type_for_widest_vector_mode): Likewise.

>>> 	* tree-vect-stmts.c (vectorizable_conversion): Likewise.

>>> 	* var-tracking.c (prepare_call_arguments): Likewise.

>>>

>>> gcc/ada/

>>> 	* gcc-interface/misc.c (fp_prec_to_size): Use new mode iterators.

>>> 	(fp_size_to_prec): Likewise.

>>>

>>> gcc/c-family/

>>> 	* c-common.c (c_common_fixed_point_type_for_size): Use new mode

>>> 	iterators.

>>> 	* c-cppbuiltin.c (c_cpp_builtins): Likewise.

>> So in some cases I see that we have loops like this:

>>

>> for (; mode != VOIDmode; mode = GET_WIDER_MODE (mode))

>>

>> Which iterates from the current mode through all the remaining modes,

>> with each iteration using a wider mode than the previous iteration.

>> GET_WIDER_MODE is always going to give us something in the same class or

>> VOIDmode.

>>

>> This is getting translated into:

>>

>> FOR_EACH_MODE_FROM (mode, mode)

>>

>> The two loops have different steps.  The original steps to a wider mode

>> each iteration.  The new one may step to a different mode of the same

>> width IIUC.

>>

>> Am I missing something here?

> 

> The new iterators use GET_MODE_WIDER or GET_MODE_2XWIDER to step,

> and the patch is only supposed to convert loops that have matching steps.

> It wasn't supposed to convert loops that step through modes as numerical

> values, but I see now that I fluffed it with:

Ah, I was just doing a high level looksie at the conversions first using
the descriptions you gave when I saw what appeared to be the
inconsistency.  Let me repeat that knowing that we're stepping with
GET_MODE_WIDER and friends.


> 

> Index: gcc/expmed.c

> ===================================================================

> --- gcc/expmed.c	2017-07-13 09:17:39.972572368 +0100

> +++ gcc/expmed.c	2017-07-13 09:18:21.531429258 +0100

> @@ -204,8 +204,7 @@ init_expmed_one_mode (struct init_expmed

>  

>    if (SCALAR_INT_MODE_P (mode))

>      {

> -      for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;

> -	   mode_from = (machine_mode)(mode_from + 1))

> +      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)

> 

> Sorry about that!  Will fix.

> 

> [Maybe in this case the change is safe, since I'm not sure we support

> multiple full-integer modes with the same width.  It's still too subtle

> for a mechanical change like this though.]

> 

> Is that patch OK with that hunk removed?

Let me walk through a few uses again, then the implementation of the
iterators.  Odds are it's fine, but I should look at it deeper than I
have so far.

jeff
Jeff Law Aug. 11, 2017, 5:51 p.m. | #4
On 07/13/2017 02:39 AM, Richard Sandiford wrote:
> The new iterators are:

> 

> - FOR_EACH_MODE_IN_CLASS: iterate over all the modes in a mode class.

> 

> - FOR_EACH_MODE_FROM: iterate over all the modes in a class,

>   starting at a given mode.

> 

> - FOR_EACH_WIDER_MODE: iterate over all the modes in a class,

>   starting at the next widest mode after a given mode.

> 

> - FOR_EACH_2XWIDER_MODE: same, but considering only modes that

>   are two times wider than the previous mode.

> 

> - FOR_EACH_MODE_UNTIL: iterate over all the modes in a class until

>   a given mode is reached.

> 

> - FOR_EACH_MODE: iterate over all the modes in a class between

>   two given modes, inclusive of the first but not the second.

> 

> These help with the stronger type checking added by later patches,

> since every new mode will be in the same class as the previous one.

> 

> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

>             Alan Hayward  <alan.hayward@arm.com>

>             David Sherwood  <david.sherwood@arm.com>

> 

> gcc/

> 	* machmode.h (mode_traits): New structure.

> 	(get_narrowest_mode): New function.

> 	(mode_iterator::start): Likewise.

> 	(mode_iterator::iterate_p): Likewise.

> 	(mode_iterator::get_wider): Likewise.

> 	(mode_iterator::get_known_wider): Likewise.

> 	(mode_iterator::get_2xwider): Likewise.

> 	(FOR_EACH_MODE_IN_CLASS): New mode iterator.

> 	(FOR_EACH_MODE): Likewise.

> 	(FOR_EACH_MODE_FROM): Likewise.

> 	(FOR_EACH_MODE_UNTIL): Likewise.

> 	(FOR_EACH_WIDER_MODE): Likewise.

> 	(FOR_EACH_2XWIDER_MODE): Likewise.

> 	* builtins.c (expand_builtin_strlen): Use new mode iterators.

> 	* combine.c (simplify_comparison): Likewise

> 	* config/i386/i386.c (type_natural_mode): Likewise.

> 	* cse.c (cse_insn): Likewise.

> 	* dse.c (find_shift_sequence): Likewise.

> 	* emit-rtl.c (init_derived_machine_modes): Likewise.

> 	(init_emit_once): Likewise.

> 	* explow.c (hard_function_value): Likewise.

> 	* expmed.c (init_expmed_one_mode): Likewise.

> 	(extract_fixed_bit_field_1): Likewise.

> 	(extract_bit_field_1): Likewise.

> 	(expand_divmod): Likewise.

> 	(emit_store_flag_1): Likewise.

> 	* expr.c (init_expr_target): Likewise.

> 	(convert_move): Likewise.

> 	(alignment_for_piecewise_move): Likewise.

> 	(widest_int_mode_for_size): Likewise.

> 	(emit_block_move_via_movmem): Likewise.

> 	(copy_blkmode_to_reg): Likewise.

> 	(set_storage_via_setmem): Likewise.

> 	(compress_float_constant): Likewise.

> 	* omp-low.c (omp_clause_aligned_alignment): Likewise.

> 	* optabs-query.c (get_best_extraction_insn): Likewise.

> 	* optabs.c (expand_binop): Likewise.

> 	(expand_twoval_unop): Likewise.

> 	(expand_twoval_binop): Likewise.

> 	(widen_leading): Likewise.

> 	(widen_bswap): Likewise.

> 	(expand_parity): Likewise.

> 	(expand_unop): Likewise.

> 	(prepare_cmp_insn): Likewise.

> 	(prepare_float_lib_cmp): Likewise.

> 	(expand_float): Likewise.

> 	(expand_fix): Likewise.

> 	(expand_sfix_optab): Likewise.

> 	* postreload.c (move2add_use_add2_insn): Likewise.

> 	* reg-stack.c (reg_to_stack): Likewise.

> 	* reginfo.c (choose_hard_reg_mode): Likewise.

> 	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.

> 	* stmt.c (emit_case_decision_tree): Likewise.

> 	* stor-layout.c (mode_for_size): Likewise.

> 	(smallest_mode_for_size): Likewise.

> 	(mode_for_vector): Likewise.

> 	(finish_bitfield_representative): Likewise.

> 	* tree-ssa-math-opts.c (target_supports_divmod_p): Likewise.

> 	* tree-vect-generic.c (type_for_widest_vector_mode): Likewise.

> 	* tree-vect-stmts.c (vectorizable_conversion): Likewise.

> 	* var-tracking.c (prepare_call_arguments): Likewise.

> 

> gcc/ada/

> 	* gcc-interface/misc.c (fp_prec_to_size): Use new mode iterators.

> 	(fp_size_to_prec): Likewise.

> 

> gcc/c-family/

> 	* c-common.c (c_common_fixed_point_type_for_size): Use new mode

> 	iterators.

> 	* c-cppbuiltin.c (c_cpp_builtins): Likewise.

I would have missed the expmed.c goof.  THanks for looking at things
again after my first message.

With your fix to expmed.c this is OK.

Jeff

Patch

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-07-13 09:18:20.866501621 +0100
+++ gcc/machmode.h	2017-07-13 09:18:21.533429040 +0100
@@ -29,6 +29,44 @@  #define HAVE_MACHINE_MODES
 extern const unsigned char mode_wider[NUM_MACHINE_MODES];
 extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
 
+template<typename T>
+struct mode_traits
+{
+  /* For use by the machmode support code only.
+
+     There are cases in which the machmode support code needs to forcibly
+     convert a machine_mode to a specific mode class T, and in which the
+     context guarantees that this is valid without the need for an assert.
+     This can be done using:
+
+       return typename mode_traits<T>::from_int (mode);
+
+     when returning a T and:
+
+       res = T (typename mode_traits<T>::from_int (mode));
+
+     when assigning to a value RES that must be assignment-compatible
+     with (but possibly not the same as) T.
+
+     Here we use an enum type distinct from machine_mode but with the
+     same range as machine_mode.  T should have a constructor that
+     accepts this enum type; it should not have a constructor that
+     accepts machine_mode.
+
+     We use this somewhat indirect approach to avoid too many constructor
+     calls when the compiler is built with -O0.  For example, even in
+     unoptimized code, the return statement above would construct the
+     returned T directly from the numerical value of MODE.  */
+  enum from_int { dummy = MAX_MACHINE_MODE };
+};
+
+template<>
+struct mode_traits<machine_mode>
+{
+  /* machine_mode itself needs no conversion.  */
+  typedef machine_mode from_int;
+};
+
 /* Get the name of mode MODE as a string.  */
 
 extern const char * const mode_name[NUM_MACHINE_MODES];
@@ -395,6 +433,16 @@  #define GET_MODE_ALIGNMENT(MODE) get_mod
 #define GET_CLASS_NARROWEST_MODE(CLASS) \
   ((machine_mode) class_narrowest_mode[CLASS])
 
+/* Return the narrowest mode in T's class.  */
+
+template<typename T>
+inline T
+get_narrowest_mode (T mode)
+{
+  return typename mode_traits<T>::from_int
+    (class_narrowest_mode[GET_MODE_CLASS (mode)]);
+}
+
 /* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD
    and the mode whose class is Pmode and whose size is POINTER_SIZE.  */
 
@@ -425,4 +473,95 @@  struct int_n_data_t {
 extern bool int_n_enabled_p[NUM_INT_N_ENTS];
 extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
 
+namespace mode_iterator
+{
+  /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */
+
+  inline void
+  start (machine_mode *iter, enum mode_class mclass)
+  {
+    *iter = GET_CLASS_NARROWEST_MODE (mclass);
+  }
+
+  /* Return true if mode iterator *ITER has not reached the end.  */
+
+  inline bool
+  iterate_p (machine_mode *iter)
+  {
+    return *iter != E_VOIDmode;
+  }
+
+  /* Set mode iterator *ITER to the next widest mode in the same class,
+     if any.  */
+
+  inline void
+  get_wider (machine_mode *iter)
+  {
+    *iter = GET_MODE_WIDER_MODE (*iter);
+  }
+
+  /* Set mode iterator *ITER to the next widest mode in the same class.
+     Such a mode is known to exist.  */
+
+  inline void
+  get_known_wider (machine_mode *iter)
+  {
+    *iter = GET_MODE_WIDER_MODE (*iter);
+    gcc_checking_assert (*iter != VOIDmode);
+  }
+
+  /* Set mode iterator *ITER to the mode that is two times wider than the
+     current one, if such a mode exists.  */
+
+  inline void
+  get_2xwider (machine_mode *iter)
+  {
+    *iter = GET_MODE_2XWIDER_MODE (*iter);
+  }
+}
+
+/* Make ITERATOR iterate over all the modes in mode class CLASS,
+   from narrowest to widest.  */
+#define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS)  \
+  for (mode_iterator::start (&(ITERATOR), CLASS); \
+       mode_iterator::iterate_p (&(ITERATOR)); \
+       mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over all the modes in the range [START, END),
+   in order of increasing width.  */
+#define FOR_EACH_MODE(ITERATOR, START, END) \
+  for ((ITERATOR) = (START); \
+       (ITERATOR) != (END); \
+       mode_iterator::get_known_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over START and all wider modes in the same
+   class, in order of increasing width.  */
+#define FOR_EACH_MODE_FROM(ITERATOR, START) \
+  for ((ITERATOR) = (START); \
+       mode_iterator::iterate_p (&(ITERATOR)); \
+       mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over modes in the range [NARROWEST, END)
+   in order of increasing width, where NARROWEST is the narrowest mode
+   in END's class.  */
+#define FOR_EACH_MODE_UNTIL(ITERATOR, END) \
+  FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)
+
+/* Make ITERATOR iterate over modes in the same class as MODE, in order
+   of increasing width.  Start at the first mode wider than START,
+   or don't iterate at all if there is no wider mode.  */
+#define FOR_EACH_WIDER_MODE(ITERATOR, START) \
+  for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR)); \
+       mode_iterator::iterate_p (&(ITERATOR)); \
+       mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over modes in the same class as MODE, in order
+   of increasing width, and with each mode being twice the width of the
+   previous mode.  Start at the mode that is two times wider than START,
+   or don't iterate at all if there is no such mode.  */
+#define FOR_EACH_2XWIDER_MODE(ITERATOR, START) \
+  for ((ITERATOR) = (START), mode_iterator::get_2xwider (&(ITERATOR)); \
+       mode_iterator::iterate_p (&(ITERATOR)); \
+       mode_iterator::get_2xwider (&(ITERATOR)))
+
 #endif /* not HAVE_MACHINE_MODES */
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2017-07-13 09:17:38.381630186 +0100
+++ gcc/builtins.c	2017-07-13 09:18:21.522430235 +0100
@@ -2790,7 +2790,7 @@  expand_builtin_strlen (tree exp, rtx tar
       tree src = CALL_EXPR_ARG (exp, 0);
       rtx src_reg;
       rtx_insn *before_strlen;
-      machine_mode insn_mode = target_mode;
+      machine_mode insn_mode;
       enum insn_code icode = CODE_FOR_nothing;
       unsigned int align;
 
@@ -2818,13 +2818,11 @@  expand_builtin_strlen (tree exp, rtx tar
 	return NULL_RTX;
 
       /* Bail out if we can't compute strlen in the right mode.  */
-      while (insn_mode != VOIDmode)
+      FOR_EACH_MODE_FROM (insn_mode, target_mode)
 	{
 	  icode = optab_handler (strlen_optab, insn_mode);
 	  if (icode != CODE_FOR_nothing)
 	    break;
-
-	  insn_mode = GET_MODE_WIDER_MODE (insn_mode);
 	}
       if (insn_mode == VOIDmode)
 	return NULL_RTX;
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2017-07-05 16:29:19.580961907 +0100
+++ gcc/combine.c	2017-07-13 09:18:21.524430018 +0100
@@ -11852,9 +11852,7 @@  simplify_comparison (enum rtx_code code,
 	    }
 
 	  else if (c0 == c1)
-	    for (tmode = GET_CLASS_NARROWEST_MODE
-		 (GET_MODE_CLASS (GET_MODE (op0)));
-		 tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
+	    FOR_EACH_MODE_UNTIL (tmode, GET_MODE (op0))
 	      if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
 		{
 		  op0 = gen_lowpart_or_truncate (tmode, inner_op0);
@@ -12727,75 +12725,81 @@  simplify_comparison (enum rtx_code code,
   if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
       && GET_MODE_SIZE (mode) < UNITS_PER_WORD
       && ! have_insn_for (COMPARE, mode))
-    for (tmode = GET_MODE_WIDER_MODE (mode);
-	 (tmode != VOIDmode && HWI_COMPUTABLE_MODE_P (tmode));
-	 tmode = GET_MODE_WIDER_MODE (tmode))
-      if (have_insn_for (COMPARE, tmode))
-	{
-	  int zero_extended;
-
-	  /* If this is a test for negative, we can make an explicit
-	     test of the sign bit.  Test this first so we can use
-	     a paradoxical subreg to extend OP0.  */
-
-	  if (op1 == const0_rtx && (code == LT || code == GE)
-	      && HWI_COMPUTABLE_MODE_P (mode))
-	    {
-	      unsigned HOST_WIDE_INT sign
-		= HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (mode) - 1);
-	      op0 = simplify_gen_binary (AND, tmode,
-					 gen_lowpart (tmode, op0),
-					 gen_int_mode (sign, tmode));
-	      code = (code == LT) ? NE : EQ;
-	      break;
-	    }
-
-	  /* If the only nonzero bits in OP0 and OP1 are those in the
-	     narrower mode and this is an equality or unsigned comparison,
-	     we can use the wider mode.  Similarly for sign-extended
-	     values, in which case it is true for all comparisons.  */
-	  zero_extended = ((code == EQ || code == NE
-			    || code == GEU || code == GTU
-			    || code == LEU || code == LTU)
-			   && (nonzero_bits (op0, tmode)
-			       & ~GET_MODE_MASK (mode)) == 0
-			   && ((CONST_INT_P (op1)
-				|| (nonzero_bits (op1, tmode)
-				    & ~GET_MODE_MASK (mode)) == 0)));
-
-	  if (zero_extended
-	      || ((num_sign_bit_copies (op0, tmode)
-		   > (unsigned int) (GET_MODE_PRECISION (tmode)
-				     - GET_MODE_PRECISION (mode)))
-		  && (num_sign_bit_copies (op1, tmode)
-		      > (unsigned int) (GET_MODE_PRECISION (tmode)
-					- GET_MODE_PRECISION (mode)))))
-	    {
-	      /* If OP0 is an AND and we don't have an AND in MODE either,
-		 make a new AND in the proper mode.  */
-	      if (GET_CODE (op0) == AND
-		  && !have_insn_for (AND, mode))
+    FOR_EACH_WIDER_MODE (tmode, mode)
+      {
+	if (!HWI_COMPUTABLE_MODE_P (tmode))
+	  break;
+	if (have_insn_for (COMPARE, tmode))
+	  {
+	    int zero_extended;
+
+	    /* If this is a test for negative, we can make an explicit
+	       test of the sign bit.  Test this first so we can use
+	       a paradoxical subreg to extend OP0.  */
+
+	    if (op1 == const0_rtx && (code == LT || code == GE)
+		&& HWI_COMPUTABLE_MODE_P (mode))
+	      {
+		unsigned HOST_WIDE_INT sign
+		  = HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (mode) - 1);
 		op0 = simplify_gen_binary (AND, tmode,
-					   gen_lowpart (tmode,
-							XEXP (op0, 0)),
-					   gen_lowpart (tmode,
-							XEXP (op0, 1)));
-	      else
-		{
-		  if (zero_extended)
-		    {
-		      op0 = simplify_gen_unary (ZERO_EXTEND, tmode, op0, mode);
-		      op1 = simplify_gen_unary (ZERO_EXTEND, tmode, op1, mode);
-		    }
-		  else
-		    {
-		      op0 = simplify_gen_unary (SIGN_EXTEND, tmode, op0, mode);
-		      op1 = simplify_gen_unary (SIGN_EXTEND, tmode, op1, mode);
-		    }
-		  break;
-		}
-	    }
-	}
+					   gen_lowpart (tmode, op0),
+					   gen_int_mode (sign, tmode));
+		code = (code == LT) ? NE : EQ;
+		break;
+	      }
+
+	    /* If the only nonzero bits in OP0 and OP1 are those in the
+	       narrower mode and this is an equality or unsigned comparison,
+	       we can use the wider mode.  Similarly for sign-extended
+	       values, in which case it is true for all comparisons.  */
+	    zero_extended = ((code == EQ || code == NE
+			      || code == GEU || code == GTU
+			      || code == LEU || code == LTU)
+			     && (nonzero_bits (op0, tmode)
+				 & ~GET_MODE_MASK (mode)) == 0
+			     && ((CONST_INT_P (op1)
+				  || (nonzero_bits (op1, tmode)
+				      & ~GET_MODE_MASK (mode)) == 0)));
+
+	    if (zero_extended
+		|| ((num_sign_bit_copies (op0, tmode)
+		     > (unsigned int) (GET_MODE_PRECISION (tmode)
+				       - GET_MODE_PRECISION (mode)))
+		    && (num_sign_bit_copies (op1, tmode)
+			> (unsigned int) (GET_MODE_PRECISION (tmode)
+					  - GET_MODE_PRECISION (mode)))))
+	      {
+		/* If OP0 is an AND and we don't have an AND in MODE either,
+		   make a new AND in the proper mode.  */
+		if (GET_CODE (op0) == AND
+		    && !have_insn_for (AND, mode))
+		  op0 = simplify_gen_binary (AND, tmode,
+					     gen_lowpart (tmode,
+							  XEXP (op0, 0)),
+					     gen_lowpart (tmode,
+							  XEXP (op0, 1)));
+		else
+		  {
+		    if (zero_extended)
+		      {
+			op0 = simplify_gen_unary (ZERO_EXTEND, tmode,
+						  op0, mode);
+			op1 = simplify_gen_unary (ZERO_EXTEND, tmode,
+						  op1, mode);
+		      }
+		    else
+		      {
+			op0 = simplify_gen_unary (SIGN_EXTEND, tmode,
+						  op0, mode);
+			op1 = simplify_gen_unary (SIGN_EXTEND, tmode,
+						  op1, mode);
+		      }
+		    break;
+		  }
+	      }
+	  }
+      }
 
   /* We may have changed the comparison operands.  Re-canonicalize.  */
   if (swap_commutative_operands_p (op0, op1))
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-07-13 09:18:19.062700632 +0100
+++ gcc/config/i386/i386.c	2017-07-13 09:18:21.528429583 +0100
@@ -9034,7 +9034,7 @@  type_natural_mode (const_tree type, cons
 	    mode = MIN_MODE_VECTOR_INT;
 
 	  /* Get the mode which has this inner mode and number of units.  */
-	  for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
+	  FOR_EACH_MODE_FROM (mode, mode)
 	    if (GET_MODE_NUNITS (mode) == TYPE_VECTOR_SUBPARTS (type)
 		&& GET_MODE_INNER (mode) == innermode)
 	      {
Index: gcc/cse.c
===================================================================
--- gcc/cse.c	2017-03-28 16:19:22.000000000 +0100
+++ gcc/cse.c	2017-07-13 09:18:21.529429475 +0100
@@ -4845,12 +4845,11 @@  cse_insn (rtx_insn *insn)
 	{
 	  machine_mode wider_mode;
 
-	  for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	       wider_mode != VOIDmode
-	       && GET_MODE_PRECISION (wider_mode) <= BITS_PER_WORD
-	       && src_related == 0;
-	       wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+	  FOR_EACH_WIDER_MODE (wider_mode, mode)
 	    {
+	      if (GET_MODE_PRECISION (wider_mode) > BITS_PER_WORD)
+		break;
+
 	      struct table_elt *const_elt
 		= lookup (src_const, HASH (src_const, wider_mode), wider_mode);
 
@@ -4864,6 +4863,9 @@  cse_insn (rtx_insn *insn)
 		    src_related = gen_lowpart (mode, const_elt->exp);
 		    break;
 		  }
+
+	      if (src_related != 0)
+		break;
 	    }
 	}
 
@@ -4880,10 +4882,11 @@  cse_insn (rtx_insn *insn)
 	  machine_mode tmode;
 	  rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
 
-	  for (tmode = GET_MODE_WIDER_MODE (mode);
-	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
-	       tmode = GET_MODE_WIDER_MODE (tmode))
+	  FOR_EACH_WIDER_MODE (tmode, mode)
 	    {
+	      if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
+		break;
+
 	      rtx inner = gen_lowpart (tmode, XEXP (src, 0));
 	      struct table_elt *larger_elt;
 
@@ -4930,12 +4933,13 @@  cse_insn (rtx_insn *insn)
 	  PUT_CODE (memory_extend_rtx, extend_op);
 	  XEXP (memory_extend_rtx, 0) = src;
 
-	  for (tmode = GET_MODE_WIDER_MODE (mode);
-	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
-	       tmode = GET_MODE_WIDER_MODE (tmode))
+	  FOR_EACH_WIDER_MODE (tmode, mode)
 	    {
 	      struct table_elt *larger_elt;
 
+	      if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
+		break;
+
 	      PUT_MODE (memory_extend_rtx, tmode);
 	      larger_elt = lookup (memory_extend_rtx,
 				   HASH (memory_extend_rtx, tmode), tmode);
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	2017-02-23 19:54:15.000000000 +0000
+++ gcc/dse.c	2017-07-13 09:18:21.530429366 +0100
@@ -1583,15 +1583,17 @@  find_shift_sequence (int access_size,
      justify the value we want to read but is available in one insn on
      the machine.  */
 
-  for (new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
-					  MODE_INT);
-       GET_MODE_BITSIZE (new_mode) <= BITS_PER_WORD;
-       new_mode = GET_MODE_WIDER_MODE (new_mode))
+  FOR_EACH_MODE_FROM (new_mode,
+		      smallest_mode_for_size (access_size * BITS_PER_UNIT,
+					      MODE_INT))
     {
       rtx target, new_reg, new_lhs;
       rtx_insn *shift_seq, *insn;
       int cost;
 
+      if (GET_MODE_BITSIZE (new_mode) > BITS_PER_WORD)
+	break;
+
       /* If a constant was stored into memory, try to simplify it here,
 	 otherwise the cost of the shift might preclude this optimization
 	 e.g. at -Os, even when no actual shift will be needed.  */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-05-04 11:58:11.115865939 +0100
+++ gcc/emit-rtl.c	2017-07-13 09:18:21.530429366 +0100
@@ -5873,9 +5873,8 @@  init_derived_machine_modes (void)
   byte_mode = VOIDmode;
   word_mode = VOIDmode;
 
-  for (machine_mode mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  machine_mode mode;
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     {
       if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
 	  && byte_mode == VOIDmode)
@@ -5957,23 +5956,17 @@  init_emit_once (void)
       const REAL_VALUE_TYPE *const r =
 	(i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
 
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
 	const_tiny_rtx[i][(int) mode] =
 	  const_double_from_real_value (*r, mode);
 
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_DECIMAL_FLOAT)
 	const_tiny_rtx[i][(int) mode] =
 	  const_double_from_real_value (*r, mode);
 
       const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
 
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
 	const_tiny_rtx[i][(int) mode] = GEN_INT (i);
 
       for (mode = MIN_MODE_PARTIAL_INT;
@@ -5984,52 +5977,40 @@  init_emit_once (void)
 
   const_tiny_rtx[3][(int) VOIDmode] = constm1_rtx;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     const_tiny_rtx[3][(int) mode] = constm1_rtx;
 
   for (mode = MIN_MODE_PARTIAL_INT;
        mode <= MAX_MODE_PARTIAL_INT;
        mode = (machine_mode)((int)(mode) + 1))
     const_tiny_rtx[3][(int) mode] = constm1_rtx;
-      
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_COMPLEX_INT)
     {
       rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
       const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_COMPLEX_FLOAT)
     {
       rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
       const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
       const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FRACT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FRACT)
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -6038,9 +6019,7 @@  init_emit_once (void)
 				      FCONST0 (mode), mode);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_UFRACT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_UFRACT)
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -6049,9 +6028,7 @@  init_emit_once (void)
 				      FCONST0 (mode), mode);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_ACCUM);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_ACCUM)
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -6071,9 +6048,7 @@  init_emit_once (void)
 				      FCONST1 (mode), mode);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_UACCUM);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_UACCUM)
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -6093,31 +6068,23 @@  init_emit_once (void)
 				      FCONST1 (mode), mode);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FRACT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FRACT)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_UFRACT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_UFRACT)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_ACCUM);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_ACCUM)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_UACCUM);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_UACCUM)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
@@ -6131,9 +6098,7 @@  init_emit_once (void)
   if (STORE_FLAG_VALUE == 1)
     const_tiny_rtx[1][(int) BImode] = const1_rtx;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_POINTER_BOUNDS);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_POINTER_BOUNDS)
     {
       wide_int wi_zero = wi::zero (GET_MODE_PRECISION (mode));
       const_tiny_rtx[0][mode] = immed_wide_int_const (wi_zero, mode);
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	2017-06-30 12:50:38.436653781 +0100
+++ gcc/explow.c	2017-07-13 09:18:21.531429258 +0100
@@ -1912,9 +1912,7 @@  hard_function_value (const_tree valtype,
 	 since the value of bytes will then be large enough that no
 	 mode will match anyway.  */
 
-      for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-	   tmpmode != VOIDmode;
-	   tmpmode = GET_MODE_WIDER_MODE (tmpmode))
+      FOR_EACH_MODE_IN_CLASS (tmpmode, MODE_INT)
 	{
 	  /* Have we found a large enough mode?  */
 	  if (GET_MODE_SIZE (tmpmode) >= bytes)
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-07-13 09:17:39.972572368 +0100
+++ gcc/expmed.c	2017-07-13 09:18:21.531429258 +0100
@@ -204,8 +204,7 @@  init_expmed_one_mode (struct init_expmed
 
   if (SCALAR_INT_MODE_P (mode))
     {
-      for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;
-	   mode_from = (machine_mode)(mode_from + 1))
+      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)
@@ -1586,7 +1585,7 @@  extract_bit_field_1 (rtx str_rtx, unsign
       else
 	new_mode = MIN_MODE_VECTOR_INT;
 
-      for (; new_mode != VOIDmode ; new_mode = GET_MODE_WIDER_MODE (new_mode))
+      FOR_EACH_MODE_FROM (new_mode, new_mode)
 	if (GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0))
 	    && GET_MODE_UNIT_SIZE (new_mode) == GET_MODE_SIZE (tmode)
 	    && targetm.vector_mode_supported_p (new_mode))
@@ -2029,8 +2028,7 @@  extract_fixed_bit_field_1 (machine_mode
 
   /* Find the narrowest integer mode that contains the field.  */
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     if (GET_MODE_BITSIZE (mode) >= bitsize + bitnum)
       {
 	op0 = convert_to_mode (mode, op0, 0);
@@ -4094,15 +4092,13 @@  expand_divmod (int rem_flag, enum tree_c
   optab2 = (op1_is_pow2 ? optab1
 	    : (unsignedp ? udivmod_optab : sdivmod_optab));
 
-  for (compute_mode = mode; compute_mode != VOIDmode;
-       compute_mode = GET_MODE_WIDER_MODE (compute_mode))
+  FOR_EACH_MODE_FROM (compute_mode, mode)
     if (optab_handler (optab1, compute_mode) != CODE_FOR_nothing
 	|| optab_handler (optab2, compute_mode) != CODE_FOR_nothing)
       break;
 
   if (compute_mode == VOIDmode)
-    for (compute_mode = mode; compute_mode != VOIDmode;
-	 compute_mode = GET_MODE_WIDER_MODE (compute_mode))
+    FOR_EACH_MODE_FROM (compute_mode, mode)
       if (optab_libfunc (optab1, compute_mode)
 	  || optab_libfunc (optab2, compute_mode))
 	break;
@@ -5504,8 +5500,7 @@  emit_store_flag_1 (rtx target, enum rtx_
     }
 
   mclass = GET_MODE_CLASS (mode);
-  for (compare_mode = mode; compare_mode != VOIDmode;
-       compare_mode = GET_MODE_WIDER_MODE (compare_mode))
+  FOR_EACH_MODE_FROM (compare_mode, mode)
     {
      machine_mode optab_mode = mclass == MODE_CC ? CCmode : compare_mode;
      icode = optab_handler (cstore_optab, optab_mode);
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-06-30 12:50:38.246662537 +0100
+++ gcc/expr.c	2017-07-13 09:18:21.532429149 +0100
@@ -177,12 +177,10 @@  init_expr_target (void)
 
   mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1));
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
     {
       machine_mode srcmode;
-      for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
-	   srcmode = GET_MODE_WIDER_MODE (srcmode))
+      FOR_EACH_MODE_UNTIL (srcmode, mode)
 	{
 	  enum insn_code ic;
 
@@ -549,8 +547,7 @@  convert_move (rtx to, rtx from, int unsi
 	  int shift_amount;
 
 	  /* Search for a mode to convert via.  */
-	  for (intermediate = from_mode; intermediate != VOIDmode;
-	       intermediate = GET_MODE_WIDER_MODE (intermediate))
+	  FOR_EACH_MODE_FROM (intermediate, from_mode)
 	    if (((can_extend_p (to_mode, intermediate, unsignedp)
 		  != CODE_FOR_nothing)
 		 || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
@@ -702,12 +699,14 @@  alignment_for_piecewise_move (unsigned i
     {
       machine_mode tmode, xmode;
 
-      for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT), xmode = tmode;
-	   tmode != VOIDmode;
-	   xmode = tmode, tmode = GET_MODE_WIDER_MODE (tmode))
-	if (GET_MODE_SIZE (tmode) > max_pieces
-	    || SLOW_UNALIGNED_ACCESS (tmode, align))
-	  break;
+      xmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+      FOR_EACH_MODE_IN_CLASS (tmode, MODE_INT)
+	{
+	  if (GET_MODE_SIZE (tmode) > max_pieces
+	      || SLOW_UNALIGNED_ACCESS (tmode, align))
+	    break;
+	  xmode = tmode;
+	}
 
       align = MAX (align, GET_MODE_ALIGNMENT (xmode));
     }
@@ -723,8 +722,7 @@  widest_int_mode_for_size (unsigned int s
 {
   machine_mode tmode, mode = VOIDmode;
 
-  for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-       tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
+  FOR_EACH_MODE_IN_CLASS (tmode, MODE_INT)
     if (GET_MODE_SIZE (tmode) < size)
       mode = tmode;
 
@@ -1728,8 +1726,7 @@  emit_block_move_via_movmem (rtx x, rtx y
      including more than one in the machine description unless
      the more limited one has some advantage.  */
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     {
       enum insn_code code = direct_optab_handler (movmem_optab, mode);
 
@@ -2790,9 +2787,7 @@  copy_blkmode_to_reg (machine_mode mode,
     {
       /* Find the smallest integer mode large enough to hold the
 	 entire structure.  */
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
 	/* Have we found a large enough mode?  */
 	if (GET_MODE_SIZE (mode) >= bytes)
 	  break;
@@ -3048,8 +3043,7 @@  set_storage_via_setmem (rtx object, rtx
 	expected_size = min_size;
     }
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     {
       enum insn_code code = direct_optab_handler (setmem_optab, mode);
 
@@ -3788,9 +3782,7 @@  compress_float_constant (rtx x, rtx y)
   else
     oldcost = set_src_cost (force_const_mem (dstmode, y), dstmode, speed);
 
-  for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
-       srcmode != orig_srcmode;
-       srcmode = GET_MODE_WIDER_MODE (srcmode))
+  FOR_EACH_MODE_UNTIL (srcmode, orig_srcmode)
     {
       enum insn_code ic;
       rtx trunc_y;
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	2017-07-05 16:29:19.600761904 +0100
+++ gcc/omp-low.c	2017-07-13 09:18:21.533429040 +0100
@@ -3445,9 +3445,7 @@  omp_clause_aligned_alignment (tree claus
   static enum mode_class classes[]
     = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
   for (int i = 0; i < 4; i += 2)
-    for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
-	 mode != VOIDmode;
-	 mode = GET_MODE_WIDER_MODE (mode))
+    FOR_EACH_MODE_IN_CLASS (mode, classes[i])
       {
 	vmode = targetm.vectorize.preferred_simd_mode (mode);
 	if (GET_MODE_CLASS (vmode) != classes[i + 1])
Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c	2017-02-23 19:54:15.000000000 +0000
+++ gcc/optabs-query.c	2017-07-13 09:18:21.534428932 +0100
@@ -194,21 +194,20 @@  get_best_extraction_insn (extraction_ins
 			  machine_mode field_mode)
 {
   machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
-  while (mode != VOIDmode)
+  FOR_EACH_MODE_FROM (mode, mode)
     {
       if (get_extraction_insn (insn, pattern, type, mode))
 	{
-	  while (mode != VOIDmode
-		 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
-		 && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
-						    field_mode))
+	  FOR_EACH_MODE_FROM (mode, mode)
 	    {
+	      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (field_mode)
+		  || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
+						    field_mode))
+		break;
 	      get_extraction_insn (insn, pattern, type, mode);
-	      mode = GET_MODE_WIDER_MODE (mode);
 	    }
 	  return true;
 	}
-      mode = GET_MODE_WIDER_MODE (mode);
     }
   return false;
 }
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2017-07-02 09:32:32.142745257 +0100
+++ gcc/optabs.c	2017-07-13 09:18:21.534428932 +0100
@@ -1250,9 +1250,7 @@  expand_binop (machine_mode mode, optab b
 
   if (CLASS_HAS_WIDER_MODES_P (mclass)
       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
-    for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	 wider_mode != VOIDmode;
-	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+    FOR_EACH_WIDER_MODE (wider_mode, mode)
       {
 	if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
 	    || (binoptab == smul_optab
@@ -1793,9 +1791,7 @@  expand_binop (machine_mode mode, optab b
 
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	   wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_WIDER_MODE (wider_mode, mode)
 	{
 	  if (find_widening_optab_handler (binoptab, wider_mode, mode, 1)
 		  != CODE_FOR_nothing
@@ -1951,9 +1947,7 @@  expand_twoval_unop (optab unoptab, rtx o
 
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	   wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_WIDER_MODE (wider_mode, mode)
 	{
 	  if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
 	    {
@@ -2034,9 +2028,7 @@  expand_twoval_binop (optab binoptab, rtx
 
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	   wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_WIDER_MODE (wider_mode, mode)
 	{
 	  if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing)
 	    {
@@ -2138,9 +2130,7 @@  widen_leading (machine_mode mode, rtx op
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
       machine_mode wider_mode;
-      for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	   wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_WIDER_MODE (wider_mode, mode)
 	{
 	  if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
 	    {
@@ -2310,9 +2300,7 @@  widen_bswap (machine_mode mode, rtx op0,
   if (!CLASS_HAS_WIDER_MODES_P (mclass))
     return NULL_RTX;
 
-  for (wider_mode = GET_MODE_WIDER_MODE (mode);
-       wider_mode != VOIDmode;
-       wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+  FOR_EACH_WIDER_MODE (wider_mode, mode)
     if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing)
       goto found;
   return NULL_RTX;
@@ -2374,8 +2362,7 @@  expand_parity (machine_mode mode, rtx op
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
       machine_mode wider_mode;
-      for (wider_mode = mode; wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_MODE_FROM (wider_mode, mode)
 	{
 	  if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
 	    {
@@ -2827,9 +2814,7 @@  expand_unop (machine_mode mode, optab un
     }
 
   if (CLASS_HAS_WIDER_MODES_P (mclass))
-    for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	 wider_mode != VOIDmode;
-	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+    FOR_EACH_WIDER_MODE (wider_mode, mode)
       {
 	if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
 	  {
@@ -2996,9 +2981,7 @@  expand_unop (machine_mode mode, optab un
 
   if (CLASS_HAS_WIDER_MODES_P (mclass))
     {
-      for (wider_mode = GET_MODE_WIDER_MODE (mode);
-	   wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_WIDER_MODE (wider_mode, mode)
 	{
 	  if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing
 	      || optab_libfunc (unoptab, wider_mode))
@@ -3799,9 +3782,7 @@  prepare_cmp_insn (rtx x, rtx y, enum rtx
 
       /* Try to use a memory block compare insn - either cmpstr
 	 or cmpmem will do.  */
-      for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-	   cmp_mode != VOIDmode;
-	   cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
+      FOR_EACH_MODE_IN_CLASS (cmp_mode, MODE_INT)
 	{
 	  cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
 	  if (cmp_code == CODE_FOR_nothing)
@@ -3863,9 +3844,8 @@  prepare_cmp_insn (rtx x, rtx y, enum rtx
 
   mclass = GET_MODE_CLASS (mode);
   test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y);
-  cmp_mode = mode;
-  do
-   {
+  FOR_EACH_MODE_FROM (cmp_mode, mode)
+    {
       enum insn_code icode;
       icode = optab_handler (cbranch_optab, cmp_mode);
       if (icode != CODE_FOR_nothing
@@ -3889,9 +3869,7 @@  prepare_cmp_insn (rtx x, rtx y, enum rtx
 
       if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass))
 	break;
-      cmp_mode = GET_MODE_WIDER_MODE (cmp_mode);
     }
-  while (cmp_mode != VOIDmode);
 
   if (methods != OPTAB_LIB_WIDEN)
     goto fail;
@@ -4074,9 +4052,7 @@  prepare_float_lib_cmp (rtx x, rtx y, enu
   bool reversed_p = false;
   cmp_mode = targetm.libgcc_cmp_return_mode ();
 
-  for (mode = orig_mode;
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_FROM (mode, orig_mode)
     {
       if (code_to_optab (comparison)
 	  && (libfunc = optab_libfunc (code_to_optab (comparison), mode)))
@@ -4649,10 +4625,8 @@  expand_float (rtx to, rtx from, int unsi
      wider mode.  If the integer mode is wider than the mode of FROM,
      we can do the conversion signed even if the input is unsigned.  */
 
-  for (fmode = GET_MODE (to); fmode != VOIDmode;
-       fmode = GET_MODE_WIDER_MODE (fmode))
-    for (imode = GET_MODE (from); imode != VOIDmode;
-	 imode = GET_MODE_WIDER_MODE (imode))
+  FOR_EACH_MODE_FROM (fmode, GET_MODE (to))
+    FOR_EACH_MODE_FROM (imode, GET_MODE (from))
       {
 	int doing_unsigned = unsignedp;
 
@@ -4699,8 +4673,7 @@  expand_float (rtx to, rtx from, int unsi
 	 least as wide as the target.  Using FMODE will avoid rounding woes
 	 with unsigned values greater than the signed maximum value.  */
 
-      for (fmode = GET_MODE (to);  fmode != VOIDmode;
-	   fmode = GET_MODE_WIDER_MODE (fmode))
+      FOR_EACH_MODE_FROM (fmode, GET_MODE (to))
 	if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
 	    && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
 	  break;
@@ -4847,10 +4820,8 @@  expand_fix (rtx to, rtx from, int unsign
      this conversion.  If the integer mode is wider than the mode of TO,
      we can do the conversion either signed or unsigned.  */
 
-  for (fmode = GET_MODE (from); fmode != VOIDmode;
-       fmode = GET_MODE_WIDER_MODE (fmode))
-    for (imode = GET_MODE (to); imode != VOIDmode;
-	 imode = GET_MODE_WIDER_MODE (imode))
+  FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
+    FOR_EACH_MODE_FROM (imode, GET_MODE (to))
       {
 	int doing_unsigned = unsignedp;
 
@@ -4910,8 +4881,7 @@  expand_fix (rtx to, rtx from, int unsign
      simply clears out that bit.  The rest is trivial.  */
 
   if (unsignedp && GET_MODE_PRECISION (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
-    for (fmode = GET_MODE (from); fmode != VOIDmode;
-	 fmode = GET_MODE_WIDER_MODE (fmode))
+    FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
       if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc)
 	  && (!DECIMAL_FLOAT_MODE_P (fmode)
 	      || GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (GET_MODE (to))))
@@ -5112,10 +5082,8 @@  expand_sfix_optab (rtx to, rtx from, con
      this conversion.  If the integer mode is wider than the mode of TO,
      we can do the conversion either signed or unsigned.  */
 
-  for (fmode = GET_MODE (from); fmode != VOIDmode;
-       fmode = GET_MODE_WIDER_MODE (fmode))
-    for (imode = GET_MODE (to); imode != VOIDmode;
-	 imode = GET_MODE_WIDER_MODE (imode))
+  FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
+    FOR_EACH_MODE_FROM (imode, GET_MODE (to))
       {
 	icode = convert_optab_handler (tab, imode, fmode);
 	if (icode != CODE_FOR_nothing)
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2017-02-23 19:54:03.000000000 +0000
+++ gcc/postreload.c	2017-07-13 09:18:21.535428823 +0100
@@ -1770,10 +1770,7 @@  move2add_use_add2_insn (rtx reg, rtx sym
       else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
 	{
 	  machine_mode narrow_mode;
-	  for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-	       narrow_mode != VOIDmode
-		 && narrow_mode != GET_MODE (reg);
-	       narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
+	  FOR_EACH_MODE_UNTIL (narrow_mode, GET_MODE (reg))
 	    {
 	      if (have_insn_for (STRICT_LOW_PART, narrow_mode)
 		  && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c	2017-02-23 19:54:20.000000000 +0000
+++ gcc/reg-stack.c	2017-07-13 09:18:21.535428823 +0100
@@ -3315,13 +3315,9 @@  reg_to_stack (void)
   for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
     {
       machine_mode mode;
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
 	FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
-      for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_COMPLEX_FLOAT)
 	FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
     }
 
Index: gcc/reginfo.c
===================================================================
--- gcc/reginfo.c	2017-03-28 16:19:28.000000000 +0100
+++ gcc/reginfo.c	2017-07-13 09:18:21.535428823 +0100
@@ -632,36 +632,28 @@  choose_hard_reg_mode (unsigned int regno
      held in REGNO.  If none, we look for the largest floating-point mode.
      If we still didn't find a valid mode, try CCmode.  */
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
 	&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
       found_mode = mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
-       mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
     if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	&& HARD_REGNO_MODE_OK (regno, mode)
 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2017-07-02 09:32:32.142745257 +0100
+++ gcc/rtlanal.c	2017-07-13 09:18:21.536428715 +0100
@@ -5663,10 +5663,8 @@  init_num_sign_bit_copies_in_rep (void)
 {
   machine_mode mode, in_mode;
 
-  for (in_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); in_mode != VOIDmode;
-       in_mode = GET_MODE_WIDER_MODE (mode))
-    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != in_mode;
-	 mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (in_mode, MODE_INT)
+    FOR_EACH_MODE_UNTIL (mode, in_mode)
       {
 	machine_mode i;
 
@@ -5677,7 +5675,7 @@  init_num_sign_bit_copies_in_rep (void)
 
 	/* We are in in_mode.  Count how many bits outside of mode
 	   have to be copies of the sign-bit.  */
-	for (i = mode; i != in_mode; i = GET_MODE_WIDER_MODE (i))
+	FOR_EACH_MODE (i, mode, in_mode)
 	  {
 	    machine_mode wider = GET_MODE_WIDER_MODE (i);
 
Index: gcc/stmt.c
===================================================================
--- gcc/stmt.c	2017-06-30 12:50:38.965629405 +0100
+++ gcc/stmt.c	2017-07-13 09:18:21.536428715 +0100
@@ -868,8 +868,7 @@  emit_case_decision_tree (tree index_expr
     {
       int unsignedp = TYPE_UNSIGNED (index_type);
       machine_mode wider_mode;
-      for (wider_mode = GET_MODE (index); wider_mode != VOIDmode;
-	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
+      FOR_EACH_MODE_FROM (wider_mode, GET_MODE (index))
 	if (have_insn_for (COMPARE, wider_mode))
 	  {
 	    index = convert_to_mode (wider_mode, index, unsignedp);
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-05-18 07:51:11.855803833 +0100
+++ gcc/stor-layout.c	2017-07-13 09:18:21.536428715 +0100
@@ -306,8 +306,7 @@  mode_for_size (unsigned int size, enum m
     return BLKmode;
 
   /* Get the first mode which has this size, in the specified class.  */
-  for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, mclass)
     if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
@@ -348,8 +347,7 @@  smallest_mode_for_size (unsigned int siz
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
-  for (mode = GET_CLASS_NARROWEST_MODE (mclass); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, mclass)
     if (GET_MODE_PRECISION (mode) >= size)
       break;
 
@@ -501,7 +499,7 @@  mode_for_vector (machine_mode innermode,
 
   /* Do not check vector_mode_supported_p here.  We'll do that
      later in vector_type_mode.  */
-  for (; mode != VOIDmode ; mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_NUNITS (mode) == nunits
 	&& GET_MODE_INNER (mode) == innermode)
       break;
@@ -1895,8 +1893,7 @@  finish_bitfield_representative (tree rep
   gcc_assert (maxbitsize % BITS_PER_UNIT == 0);
 
   /* Find the smallest nice mode to use.  */
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     if (GET_MODE_BITSIZE (mode) >= bitsize)
       break;
   if (mode != VOIDmode
Index: gcc/tree-ssa-math-opts.c
===================================================================
--- gcc/tree-ssa-math-opts.c	2017-07-05 16:29:19.601661904 +0100
+++ gcc/tree-ssa-math-opts.c	2017-07-13 09:18:21.537428606 +0100
@@ -3824,9 +3824,8 @@  target_supports_divmod_p (optab divmod_o
     {
       /* If optab_handler exists for div_optab, perhaps in a wider mode,
 	 we don't want to use the libfunc even if it exists for given mode.  */ 
-      for (machine_mode div_mode = mode;
-	   div_mode != VOIDmode;
-	   div_mode = GET_MODE_WIDER_MODE (div_mode))
+      machine_mode div_mode;
+      FOR_EACH_MODE_FROM (div_mode, mode)
 	if (optab_handler (div_optab, div_mode) != CODE_FOR_nothing)
 	  return false;
 
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	2017-03-28 16:19:28.000000000 +0100
+++ gcc/tree-vect-generic.c	2017-07-13 09:18:21.537428606 +0100
@@ -1154,7 +1154,7 @@  type_for_widest_vector_mode (tree type,
   else
     mode = MIN_MODE_VECTOR_INT;
 
-  for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_INNER (mode) == inner_mode
         && GET_MODE_NUNITS (mode) > best_nunits
 	&& optab_handler (op, mode) != CODE_FOR_nothing)
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c	2017-07-05 16:29:19.602561904 +0100
+++ gcc/tree-vect-stmts.c	2017-07-13 09:18:21.538428497 +0100
@@ -4228,12 +4228,12 @@  vectorizable_conversion (gimple *stmt, g
 	      <= GET_MODE_SIZE (TYPE_MODE (rhs_type))))
 	goto unsupported;
 
-      rhs_mode = TYPE_MODE (rhs_type);
       fltsz = GET_MODE_SIZE (TYPE_MODE (lhs_type));
-      for (rhs_mode = GET_MODE_2XWIDER_MODE (TYPE_MODE (rhs_type));
-	   rhs_mode != VOIDmode && GET_MODE_SIZE (rhs_mode) <= fltsz;
-	   rhs_mode = GET_MODE_2XWIDER_MODE (rhs_mode))
+      FOR_EACH_2XWIDER_MODE (rhs_mode, TYPE_MODE (rhs_type))
 	{
+	  if (GET_MODE_SIZE (rhs_mode) > fltsz)
+	    break;
+
 	  cvt_type
 	    = build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), 0);
 	  cvt_type = get_same_sized_vectype (cvt_type, vectype_in);
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c	2017-05-24 09:25:11.592569829 +0100
+++ gcc/var-tracking.c	2017-07-13 09:18:21.539428389 +0100
@@ -6306,13 +6306,14 @@  prepare_call_arguments (basic_block bb,
 	    else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
 		     || GET_MODE_CLASS (GET_MODE (x)) == MODE_PARTIAL_INT)
 	      {
-		machine_mode mode = GET_MODE (x);
+		machine_mode mode;
 
-		while ((mode = GET_MODE_WIDER_MODE (mode)) != VOIDmode
-		       && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD)
+		FOR_EACH_WIDER_MODE (mode, GET_MODE (x))
 		  {
-		    rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
+		    if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
+		      break;
 
+		    rtx reg = simplify_subreg (mode, x, GET_MODE (x), 0);
 		    if (reg == NULL_RTX || !REG_P (reg))
 		      continue;
 		    val = cselib_lookup (reg, mode, 0, VOIDmode);
Index: gcc/ada/gcc-interface/misc.c
===================================================================
--- gcc/ada/gcc-interface/misc.c	2017-05-03 08:46:30.761861657 +0100
+++ gcc/ada/gcc-interface/misc.c	2017-07-13 09:18:21.521430343 +0100
@@ -1313,8 +1313,7 @@  fp_prec_to_size (int prec)
 {
   machine_mode mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
     if (GET_MODE_PRECISION (mode) == prec)
       return GET_MODE_BITSIZE (mode);
 
@@ -1328,8 +1327,7 @@  fp_size_to_prec (int size)
 {
   machine_mode mode;
 
-  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
     if (GET_MODE_BITSIZE (mode) == size)
       return GET_MODE_PRECISION (mode);
 
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	2017-07-08 11:37:46.129575607 +0100
+++ gcc/c-family/c-common.c	2017-07-13 09:18:21.523430126 +0100
@@ -2149,13 +2149,14 @@  c_common_type_for_size (unsigned int bit
 c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
 				    int unsignedp, int satp)
 {
-  machine_mode mode;
+  enum mode_class mclass;
   if (ibit == 0)
-    mode = unsignedp ? UQQmode : QQmode;
+    mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
   else
-    mode = unsignedp ? UHAmode : HAmode;
+    mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
 
-  for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
+  machine_mode mode;
+  FOR_EACH_MODE_IN_CLASS (mode, mclass)
     if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
       break;
 
Index: gcc/c-family/c-cppbuiltin.c
===================================================================
--- gcc/c-family/c-cppbuiltin.c	2017-07-13 09:18:19.010706397 +0100
+++ gcc/c-family/c-cppbuiltin.c	2017-07-13 09:18:21.523430126 +0100
@@ -1186,9 +1186,8 @@  c_cpp_builtins (cpp_reader *pfile)
   if (flag_building_libgcc)
     {
       /* Properties of floating-point modes for libgcc2.c.  */
-      for (machine_mode mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
-	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+      machine_mode mode;
+      FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
 	{
 	  const char *name = GET_MODE_NAME (mode);
 	  char *macro_name