public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [0/67] Add wrapper classes for machine_modes
@ 2016-12-09 12:48 Richard Sandiford
  2016-12-09 12:50 ` [1/67] Add an E_ prefix to mode names and update case statements Richard Sandiford
                   ` (69 more replies)
  0 siblings, 70 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:48 UTC (permalink / raw)
  To: gcc-patches

This series includes most of the changes in group C from:

    https://gcc.gnu.org/ml/gcc/2016-11/msg00033.html

The idea is to add wrapper classes around machine_mode_enum
for specific groups of modes, such as scalar integers, scalar floats,
complex values, etc.  This has two main benefits: one specific to SVE
and one not.

The SVE-specific benefit is that it helps to introduce the concept
of variable-length vectors.  To do that we need to change the size
of a vector mode from being a known compile-time constant to being
(possibly) a run-time invariant.  We then need to do the same for
unconstrained machine_modes, which might or might not be vectors.
Introducing these new constrained types means that we can continue
to treat them as having a constant size.

The other benefit is that it uses static type checking to enforce
conditions that are easily forgotten otherwise.  The most common
sources of problems seem to be:

(a) using VOIDmode or BLKmode where a scalar integer was expected
    (e.g. when getting the number of bits in the value).

(b) simplifying vector operations in ways that only make sense for
    scalars.

The series helps with both of these, although we don't get the full
benefit of (b) until variable-sized modes are introduced.

I know of three specific cases in which the static type checking
forced fixes for things that turned out to be real bugs (although
we didn't know that at the time, otherwise we'd have posted patches).
They were later fixed for trunk by:

  https://gcc.gnu.org/ml/gcc-patches/2016-07/msg01783.html
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02983.html
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02896.html

The group C patches in ARM/sve-branch did slow compile time down a little.
I've since taken steps to avoid that:

- Make the tailcall pass handle aggregate parameters and return values
  (already in trunk).

- Turn some of the new wrapper functions into inline functions.

- Make all the machmode.h macros that used:

    __builtin_constant_p (M) ? foo_inline (M) : foo_array[M[

  forward to an ALWAYS_INLINE function, so that (a) M is only evaluated
  once and (b) __builtin_constant_p is applied to a variable, and so is
  deferred until later passes.  This helped the optimisation to fire in
  more cases and to continue firing when M is a class rather than a
  raw enum.

- In a similar vein, make sure that conditions like:

     SImode == DImode

  are treated as builtin_constant_p by gencondmd, so that .md patterns
  with those conditions are dropped.

With these changes the series is actually a very slight compile-time win.
That might seem unlikely, but there are several possible reasons:

1. The machmode.h macro change above might allow more constant folding.

2. The series has a tendency to evaluate modes once, rather than
   continually fetching them from (sometimes quite deep) rtx nests.
   Refetching a mode is a particular problem if call comes between
   two uses, since the compiler then has to re-evaluate the whole thing.

3. The series introduces many uses of new SCALAR_*TYPE_MODE macros,
   as alternatives to TYPE_MODE.  The new macros avoid the usual:

     (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
      ? vector_type_mode (NODE) : (NODE)->type_common.mode)

   and become direct field accesses in release builds.

   VECTOR_TYPE_P would be consistently false for these uses,
   but call-clobbered registers would usually be treated as clobbered
   by the condition as a whole.

Maybe (3) is the most likely reason.

I tested this by compiling the testsuite for:

    aarch64-linux-gnu alpha-linux-gnu arc-elf arm-linux-gnueabi
    arm-linux-gnueabihf avr-elf bfin-elf c6x-elf cr16-elf cris-elf
    epiphany-elf fr30-elf frv-linux-gnu ft32-elf h8300-elf
    hppa64-hp-hpux11.23 ia64-linux-gnu i686-pc-linux-gnu
    i686-apple-darwin iq2000-elf lm32-elf m32c-elf m32r-elf
    m68k-linux-gnu mcore-elf microblaze-elf mips-linux-gnu
    mipsisa64-linux-gnu mmix mn10300-elf moxie-rtems msp430-elf
    nds32le-elf nios2-linux-gnu nvptx-none pdp11 powerpc-linux-gnuspe
    powerpc-eabispe powerpc64-linux-gnu powerpc-ibm-aix7.0 rl78-elf
    rx-elf s390-linux-gnu s390x-linux-gnu sh-linux-gnu sparc-linux-gnu
    sparc64-linux-gnu sparc-wrs-vxworks spu-elf tilegx-elf tilepro-elf
    xstormy16-elf v850-elf vax-netbsdelf visium-elf x86_64-darwin
    x86_64-linux-gnu xtensa-elf

and checking that there were no changes in assembly.  Also tested
in the normal way on aarch64-linux-gnu and x86_64-linux-gnu.

The series depends on the already-posted:

  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg01657.html

Sorry that this is so late, been distracted by other things.  Even if
we're too far into stage 3 for SVE itself to go in, I was hoping this
part (which was kind-of posted during stage 1) could go in independently.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [1/67] Add an E_ prefix to mode names and update case statements
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
@ 2016-12-09 12:50 ` Richard Sandiford
  2016-12-09 12:52 ` [2/67] Make machine_mode a class Richard Sandiford
                   ` (68 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:50 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 14251 bytes --]

Later patches will add wrapper types for specific classes
of mode.  E.g. SImode will be a scalar_int_mode, SFmode will
be a scalar_float_mode, etc.  This patch prepares for that
change by adding an E_ prefix to the mode enum values.
It also adds #defines that map the unprefixed names
to the prefixed names; e.g:

  #define QImode (machine_mode (E_QImode))

Later patches will change this to use things like scalar_int_mode
where appropriate.

All case statements need to be updated to use the prefixed
names, since the unprefixed names will eventually not be
integer constant expressions.  This patch does a mechanical
substitution over the whole codebase.

gcc/
2016-11-23  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* genmodes.c (mode_size_inline): Add an E_ prefix to mode names.
	(mode_nunits_inline): Likewise.
	(mode_inner_inline): Likewise.
	(mode_unit_size_inline): Likewise.
	(mode_unit_precision_inline): Likewise.
	(emit_insn_modes_h): Likewise.  Also emit a #define of the
	unprefixed name.
	(emit_mode_wider): Add an E_ prefix to mode names.
	(emit_mode_complex): Likewise.
	(emit_mode_inner): Likewise.
	(emit_mode_adjustments): Likewise.
	(emit_mode_int_n): Likewise.
	* config/aarch64/aarch64-builtins.c (aarch64_simd_builtin_std_type):
	Likewise.
	* config/aarch64/aarch64-elf.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/aarch64/aarch64.c (aarch64_split_simd_combine): Likewise.
	(aarch64_split_simd_move): Likewise.
	(aarch64_gen_storewb_pair): Likewise.
	(aarch64_gen_loadwb_pair): Likewise.
	(aarch64_gen_store_pair): Likewise.
	(aarch64_gen_load_pair): Likewise.
	(aarch64_get_condition_code_1): Likewise.
	(aarch64_constant_pool_reload_icode): Likewise.
	(get_rsqrte_type): Likewise.
	(get_rsqrts_type): Likewise.
	(get_recpe_type): Likewise.
	(get_recps_type): Likewise.
	(aarch64_gimplify_va_arg_expr): Likewise.
	(aarch64_simd_container_mode): Likewise.
	(aarch64_emit_load_exclusive): Likewise.
	(aarch64_emit_store_exclusive): Likewise.
	(aarch64_expand_compare_and_swap): Likewise.
	(aarch64_gen_atomic_cas): Likewise.
	(aarch64_emit_bic): Likewise.
	(aarch64_emit_atomic_swap): Likewise.
	(aarch64_emit_atomic_load_op): Likewise.
	(aarch64_evpc_trn): Likewise.
	(aarch64_evpc_uzp): Likewise.
	(aarch64_evpc_zip): Likewise.
	(aarch64_evpc_ext): Likewise.
	(aarch64_evpc_rev): Likewise.
	(aarch64_evpc_dup): Likewise.
	(aarch64_gen_ccmp_first): Likewise.
	(aarch64_gen_ccmp_next): Likewise.
	* config/alpha/alpha.c (alpha_scalar_mode_supported_p): Likewise.
	(alpha_emit_xfloating_libcall): Likewise.
	(emit_insxl): Likewise.
	(alpha_arg_type): Likewise.
	* config/arc/arc.c (arc_vector_mode_supported_p): Likewise.
	(arc_preferred_simd_mode): Likewise.
	(arc_secondary_reload): Likewise.
	(get_arc_condition_code): Likewise.
	(arc_print_operand): Likewise.
	* config/arc/arc.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/arc/arc.md (casesi_load): Likewise.
	(casesi_compact_jump): Likewise.
	* config/arc/predicates.md (proper_comparison_operator): Likewise.
	(cc_use_register): Likewise.
	* config/arm/aout.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/arm/arm-builtins.c (arm_simd_builtin_std_type): Likewise.
	(arm_init_iwmmxt_builtins): Likewise.
	* config/arm/arm.c (thumb1_size_rtx_costs): Likewise.
	(neon_expand_vector_init): Likewise.
	(arm_attr_length_move_neon): Likewise.
	(maybe_get_arm_condition_code): Likewise.
	(arm_emit_vector_const): Likewise.
	(arm_preferred_simd_mode): Likewise.
	(arm_output_iwmmxt_tinsr): Likewise.
	(thumb1_output_casesi): Likewise.
	(thumb2_output_casesi): Likewise.
	(arm_emit_load_exclusive): Likewise.
	(arm_emit_store_exclusive): Likewise.
	(arm_expand_compare_and_swap): Likewise.
	(arm_evpc_neon_vuzp): Likewise.
	(arm_evpc_neon_vzip): Likewise.
	(arm_evpc_neon_vrev): Likewise.
	(arm_evpc_neon_vtrn): Likewise.
	(arm_evpc_neon_vext): Likewise.
	(arm_validize_comparison): Likewise.
	* config/arm/neon.md (neon_vc<cmp_op><mode>): Likewise.
	* config/avr/avr-c.c (avr_resolve_overloaded_builtin): Likewise.
	* config/avr/avr.c (avr_rtx_costs_1): Likewise.
	* config/c6x/c6x.c (c6x_vector_mode_supported_p): Likewise.
	(c6x_preferred_simd_mode): Likewise.
	* config/epiphany/epiphany.c (get_epiphany_condition_code):
	Likewise.
	(epiphany_rtx_costs): Likewise.
	* config/epiphany/predicates.md (proper_comparison_operator):
	Likewise.
	* config/frv/frv.c (condexec_memory_operand): Likewise.
	(frv_emit_move): Likewise.
	(output_move_single): Likewise.
	(output_condmove_single): Likewise.
	(frv_hard_regno_mode_ok): Likewise.
	(frv_matching_accg_mode): Likewise.
	* config/h8300/h8300.c (split_adds_subs): Likewise.
	(h8300_rtx_costs): Likewise.
	(h8300_print_operand): Likewise.
	(compute_mov_length): Likewise.
	(output_logical_op): Likewise.
	(compute_logical_op_length): Likewise.
	(compute_logical_op_cc): Likewise.
	(h8300_shift_needs_scratch_p): Likewise.
	(output_a_shift): Likewise.
	(compute_a_shift_length): Likewise.
	(compute_a_shift_cc): Likewise.
	(expand_a_rotate): Likewise.
	(output_a_rotate): Likewise.
	* config/i386/i386.c (classify_argument): Likewise.
	(function_arg_advance_32): Likewise.
	(function_arg_32): Likewise.
	(function_arg_64): Likewise.
	(function_value_64): Likewise.
	(ix86_gimplify_va_arg): Likewise.
	(ix86_legitimate_constant_p): Likewise.
	(put_condition_code): Likewise.
	(split_double_mode): Likewise.
	(ix86_avx256_split_vector_move_misalign): Likewise.
	(ix86_expand_vector_logical_operator): Likewise.
	(ix86_split_idivmod): Likewise.
	(ix86_expand_adjust_ufix_to_sfix_si): Likewise.
	(ix86_build_const_vector): Likewise.
	(ix86_build_signbit_mask): Likewise.
	(ix86_match_ccmode): Likewise.
	(ix86_cc_modes_compatible): Likewise.
	(ix86_expand_branch): Likewise.
	(ix86_expand_sse_cmp): Likewise.
	(ix86_expand_sse_movcc): Likewise.
	(ix86_expand_int_sse_cmp): Likewise.
	(ix86_expand_vec_perm_vpermi2): Likewise.
	(ix86_expand_vec_perm): Likewise.
	(ix86_expand_sse_unpack): Likewise.
	(ix86_expand_int_addcc): Likewise.
	(ix86_split_to_parts): Likewise.
	(ix86_vectorize_builtin_gather): Likewise.
	(ix86_vectorize_builtin_scatter): Likewise.
	(avx_vpermilp_parallel): Likewise.
	(inline_memory_move_cost): Likewise.
	(ix86_tieable_integer_mode_p): Likewise.
	(x86_maybe_negate_const_int): Likewise.
	(ix86_expand_vector_init_duplicate): Likewise.
	(ix86_expand_vector_init_one_nonzero): Likewise.
	(ix86_expand_vector_init_one_var): Likewise.
	(ix86_expand_vector_init_concat): Likewise.
	(ix86_expand_vector_init_interleave): Likewise.
	(ix86_expand_vector_init_general): Likewise.
	(ix86_expand_vector_set): Likewise.
	(ix86_expand_vector_extract): Likewise.
	(emit_reduc_half): Likewise.
	(ix86_emit_i387_round): Likewise.
	(ix86_mangle_type): Likewise.
	(ix86_expand_round_sse4): Likewise.
	(expand_vec_perm_blend): Likewise.
	(canonicalize_vector_int_perm): Likewise.
	(ix86_expand_vec_one_operand_perm_avx512): Likewise.
	(expand_vec_perm_1): Likewise.
	(expand_vec_perm_interleave3): Likewise.
	(expand_vec_perm_even_odd_pack): Likewise.
	(expand_vec_perm_even_odd_1): Likewise.
	(expand_vec_perm_broadcast_1): Likewise.
	(ix86_vectorize_vec_perm_const_ok): Likewise.
	(ix86_expand_vecop_qihi): Likewise.
	(ix86_expand_mul_widen_hilo): Likewise.
	(ix86_expand_sse2_abs): Likewise.
	(ix86_expand_pextr): Likewise.
	(ix86_expand_pinsr): Likewise.
	(ix86_preferred_simd_mode): Likewise.
	(ix86_simd_clone_compute_vecsize_and_simdlen): Likewise.
	* config/i386/sse.md (*andnot<mode>3): Likewise.
	(<mask_codefor><code><mode>3<mask_name>): Likewise.
	(*<code><mode>3): Likewise.
	* config/ia64/ia64.c (ia64_expand_vecint_compare): Likewise.
	(ia64_expand_atomic_op): Likewise.
	(ia64_arg_type): Likewise.
	(ia64_mode_to_int): Likewise.
	(ia64_scalar_mode_supported_p): Likewise.
	(ia64_vector_mode_supported_p): Likewise.
	(expand_vec_perm_broadcast): Likewise.
	* config/iq2000/iq2000.c (iq2000_move_1word): Likewise.
	(iq2000_function_arg_advance): Likewise.
	(iq2000_function_arg): Likewise.
	* config/m32c/m32c.c (m32c_preferred_reload_class): Likewise.
	* config/m68k/m68k.c (output_dbcc_and_branch): Likewise.
	(m68k_libcall_value): Likewise.
	(m68k_function_value): Likewise.
	(sched_attr_op_type): Likewise.
	* config/mcore/mcore.c (mcore_output_move): Likewise.
	* config/microblaze/microblaze.c (microblaze_function_arg_advance):
	Likewise.
	(microblaze_function_arg): Likewise.
	* config/mips/mips.c (mips16_build_call_stub): Likewise.
	(mips_print_operand): Likewise.
	(mips_mode_ok_for_mov_fmt_p): Likewise.
	(mips_vector_mode_supported_p): Likewise.
	(mips_preferred_simd_mode): Likewise.
	(mips_expand_vpc_loongson_even_odd): Likewise.
	(mips_expand_vec_unpack): Likewise.
	(mips_expand_vi_broadcast): Likewise.
	(mips_expand_vector_init): Likewise.
	(mips_expand_vec_reduc): Likewise.
	(mips_expand_msa_cmp): Likewise.
	* config/mips/mips.md (casesi_internal_mips16_<mode>): Likewise.
	* config/mn10300/mn10300.c (mn10300_print_operand): Likewise.
	(cc_flags_for_mode): Likewise.
	* config/msp430/msp430.c (msp430_print_operand): Likewise.
	* config/nds32/nds32-md-auxiliary.c (nds32_mem_format): Likewise.
	(nds32_output_casesi_pc_relative): Likewise.
	* config/nds32/nds32.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/nvptx/nvptx.c (nvptx_ptx_type_from_mode): Likewise.
	(nvptx_gen_unpack): Likewise.
	(nvptx_gen_pack): Likewise.
	(nvptx_gen_shuffle): Likewise.
	(nvptx_gen_wcast): Likewise.
	* config/pa/pa.c (pa_secondary_reload): Likewise.
	* config/pa/predicates.md (base14_operand): Likewise.
	* config/rs6000/predicates.md (easy_fp_constant): Likewise.
	(fusion_gpr_mem_load): Likewise.
	(fusion_addis_mem_combo_load): Likewise.
	(fusion_addis_mem_combo_store): Likewise.
	* config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_setup_reg_addr_masks): Likewise.
	(rs6000_preferred_simd_mode): Likewise.
	(output_vec_const_move): Likewise.
	(rs6000_expand_vector_extract): Likewise.
	(rs6000_split_vec_extract_var): Likewise.
	(reg_offset_addressing_ok_p): Likewise.
	(rs6000_legitimate_offset_address_p): Likewise.
	(rs6000_legitimize_address): Likewise.
	(rs6000_emit_set_const): Likewise.
	(rs6000_const_vec): Likewise.
	(rs6000_emit_move): Likewise.
	(spe_build_register_parallel): Likewise.
	(rs6000_darwin64_record_arg_recurse): Likewise.
	(swap_selector_for_mode): Likewise.
	(spe_init_builtins): Likewise.
	(paired_init_builtins): Likewise.
	(altivec_init_builtins): Likewise.
	(do_load_for_compare): Likewise.
	(rs6000_generate_compare): Likewise.
	(rs6000_expand_float128_convert): Likewise.
	(emit_load_locked): Likewise.
	(emit_store_conditional): Likewise.
	(rs6000_output_function_epilogue): Likewise.
	(rs6000_handle_altivec_attribute): Likewise.
	(rs6000_function_value): Likewise.
	(emit_fusion_gpr_load): Likewise.
	(emit_fusion_p9_load): Likewise.
	(emit_fusion_p9_store): Likewise.
	* config/rx/rx.c (rx_gen_move_template): Likewise.
	(flags_from_mode): Likewise.
	* config/s390/predicates.md (s390_alc_comparison): Likewise.
	(s390_slb_comparison): Likewise.
	* config/s390/s390.c (s390_handle_vectorbool_attribute): Likewise.
	(s390_vector_mode_supported_p): Likewise.
	(s390_cc_modes_compatible): Likewise.
	(s390_match_ccmode_set): Likewise.
	(s390_canonicalize_comparison): Likewise.
	(s390_branch_condition_mask): Likewise.
	(s390_rtx_costs): Likewise.
	(s390_secondary_reload): Likewise.
	(s390_expand_vec_compare_cc): Likewise.
	(s390_preferred_simd_mode): Likewise.
	* config/s390/vx-builtins.md (vec_packsu_u<mode>): Likewise.
	* config/sh/sh.c (sh_print_operand): Likewise.
	(dump_table): Likewise.
	(sh_secondary_reload): Likewise.
	* config/sh/sh.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/sh/sh.md (casesi_worker_1): Likewise.
	(casesi_worker_2): Likewise.
	* config/sparc/predicates.md (icc_comparison_operator): Likewise.
	(fcc_comparison_operator): Likewise.
	* config/sparc/sparc.c (sparc_expand_move): Likewise.
	(emit_soft_tfmode_cvt): Likewise.
	(sparc_preferred_simd_mode): Likewise.
	(output_cbranch): Likewise.
	(sparc_print_operand): Likewise.
	(sparc_expand_vec_perm_bmask): Likewise.
	(vector_init_bshuffle): Likewise.
	* config/spu/spu.c (spu_scalar_mode_supported_p): Likewise.
	(spu_vector_mode_supported_p): Likewise.
	(spu_expand_insv): Likewise.
	(spu_emit_branch_or_set): Likewise.
	(spu_handle_vector_attribute): Likewise.
	(spu_builtin_splats): Likewise.
	(spu_builtin_extract): Likewise.
	(spu_builtin_promote): Likewise.
	(spu_expand_sign_extend): Likewise.
	* config/tilegx/tilegx.c (tilegx_scalar_mode_supported_p): Likewise.
	(tilegx_simd_int): Likewise.
	* config/tilepro/tilepro.c (tilepro_scalar_mode_supported_p):
	Likewise.
	(tilepro_simd_int): Likewise.
	* config/v850/v850.c (const_double_split): Likewise.
	(v850_print_operand): Likewise.
	(ep_memory_offset): Likewise.
	* config/vax/vax.c (vax_rtx_costs): Likewise.
	(vax_output_int_move): Likewise.
	(vax_output_int_add): Likewise.
	(vax_output_int_subtract): Likewise.
	* config/visium/predicates.md (visium_branch_operator): Likewise.
	* config/visium/visium.c (rtx_ok_for_offset_p): Likewise.
	(visium_print_operand_address): Likewise.
	* config/visium/visium.h (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise.
	* config/xtensa/xtensa.c (xtensa_mem_offset): Likewise.
	(xtensa_expand_conditional_branch): Likewise.
	(xtensa_copy_incoming_a7): Likewise.
	(xtensa_output_literal): Likewise.
	* dfp.c (decimal_real_maxval): Likewise.
	* targhooks.c (default_libgcc_floating_mode_supported_p): Likewise.

gcc/c-family/
2016-11-23  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* c-cppbuiltin.c (mode_has_fma): Add an E_ prefix to mode names.

gcc/objc/
2016-11-23  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* objc-encoding.c (encode_gnu_bitfield): Add an E_ prefix to
	mode names.

libobjc/
2016-11-23  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* encoding.c (_darwin_rs6000_special_round_type_align): Add an
	E_ prefix to mode names.


[-- Attachment #2: add-e-prefix.diff.gz --]
[-- Type: application/octet-stream, Size: 52018 bytes --]

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [2/67] Make machine_mode a class
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
  2016-12-09 12:50 ` [1/67] Add an E_ prefix to mode names and update case statements Richard Sandiford
@ 2016-12-09 12:52 ` Richard Sandiford
  2016-12-15 22:34   ` Trevor Saunders
  2016-12-09 12:53 ` [3/67] Add GDB pretty printer for machine mode classes Richard Sandiford
                   ` (67 subsequent siblings)
  69 siblings, 1 reply; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:52 UTC (permalink / raw)
  To: gcc-patches

This patch renames enum machine_mode to enum machine_mode_enum
and adds a machine_mode wrapper class.

The previous patch mechanically replaced mode names in case
statements; this one updates other places that should continue
to use the enum directly.

The patch continues to use enums for static variables.  This isn't
necessary, but it cuts down on the amount of load-time initialisation
and shouldn't have any downsides.

The patch also changes things like:

  cmp_mode == DImode ? DFmode : DImode

to:

  cmp_mode == DImode ? E_DFmode : E_DImode

This is because DImode and DFmode will eventually be different
classes, so the original ?: wouldn't be well-formed.

The member functions of the new class are trivial and
heavily used.  There's not much point keeping them out-of-line
at -O0: if anything it would make debugging harder rather than
easier, and it would also slow things down.  The patch therefore
marks them as "always_inline", if that's available.

The patch continues to use enums for gencondmd.c, so that more
mode comparisons are integer constant expressions when checking
for always-true or always-false conditions.  This is the only
intended use of USE_ENUM_MODES.

The patch adds inline functions for all mode size properties,
with the macros being simple wrappers around them.  This is
necessary for the __builtin_constant_p trick to continue working
effectively when the mode arguments are slightly more complex
(but still foldable at compile time).

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* coretypes.h (machine_mode): New class.
	* calls.c (emit_library_call_value_1): Cast to machine_mode_enum
	instead of machine_mode.
	* combine.c (reg_stat_type): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	(undo): Likewise.
	(simplify_if_then_else): Remove "enum" keywoard before "machine_mode".
	* compare-elim.c (can_eliminate_compare): Likewise.
	* config/aarch64/aarch64-builtins.c (v8qi_UP, v4hi_UP, v4hf_UP)
	(v2si_UP, v2sf_UP, v1df_UP, di_UP, df_UP, v16qi_UP, v8hi_UP, v8hf_UP)
	(v4si_UP, v4sf_UP, v2di_UP, v2df_UP, ti_UP, oi_UP, ci_UP, xi_UP)
	(si_UP, sf_UP, hi_UP, hf_UP, qi_UP): Add E_ prefixes.
	(CRC32_BUILTIN, ENTRY): Likewise.
	(aarch64_simd_builtin_datum): Use machine_mode_enum instead of
	machine_mode.
	(aarch64_crc_builtin_datum): Likewise.
	(aarch64_builtins): Likewise.
	(aarch64_simd_builtin_std_type): Remove "enum" keyword
	before "machine_mode".
	(aarch64_lookup_simd_builtin_type): Likewise.
	(aarch64_init_simd_builtin_types): Likewise.
	(aarch64_simd_expand_args): Likewise.
	* config/aarch64/aarch64-protos.h (aarch64_simd_attr_length_rglist):
	Likewise.
	(aarch64_reverse_mask): Likewise.
	(aarch64_simd_emit_reg_reg_move): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.
	(aarch64_ccmp_mode_to_code): Likewise.
	(aarch64_operands_ok_for_ldpstp): Likewise.
	(aarch64_operands_adjust_ok_for_ldpstp): Likewise.
	(simd_check_vect_par_cnst_half): Likewise.  Remove parameter names.
	* config/aarch64/aarch64.c (aarch64_ira_change_pseudo_allocno_class):
	Remove "enum" keyword before "machine_mode".
	(aarch64_min_divisions_for_recip_mul): Likewise.
	(aarch64_reassociation_width): Likewise.
	(aarch64_get_condition_code_1): Likewise.
	(aarch64_simd_emit_reg_reg_move): Likewise.
	(aarch64_simd_attr_length_rglist): Likewise.
	(aarch64_reverse_mask): Likewise.
	(aarch64_operands_ok_for_ldpstp): Likewise.
	(aarch64_operands_adjust_ok_for_ldpstp): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.
	(aarch64_push_regs): Add E_ prefixes to mode names.
	(aarch64_pop_regs): Likewise.
	(aarch64_process_components): Likewise.
	* config/aarch64/aarch64.h (MACHMODE): Delete.
	(CUMULATIVE_ARGS): Replace MACHMODE with machine_mode.
	* config/aarch64/cortex-a57-fma-steering.c (fma_node::rename): Remove
	"enum" keyword before "machine_mode".
	* config/alpha/alpha.c (alpha_emit_conditional_move): Add E_ prefixes.
	* config/arc/arc.c (arc_init_reg_tables): Cast to machine_mode_enum
	rather than machine_mode.
	(arc_legitimize_address_0): Likewise.
	* config/arm/arm-builtins.c (arm_simd_builtin_std_type): Remove
	"enum" keyword before "machine_mode".
	(arm_lookup_simd_builtin_type): Likewise.
	(arm_simd_builtin_type): Likewise.
	(arm_init_simd_builtin_types): Likewise.
	(arm_expand_neon_args): Likewise.
	* config/arm/arm-protos.h (arm_expand_builtin): Likewise.
	* config/avr/avr-log.c (avr_log_vadump): Cast to machine_mode_enum
	rather than machine_mode.
	* config/ft32/ft32.c (ft32_libcall_value): Remove "enum" keyword
	before "machine_mode".
	(ft32_setup_incoming_varargs): Likewise.
	(ft32_function_arg): Likewise.
	(ft32_function_arg_advance): Likewise.
	(ft32_pass_by_reference): Likewise.
	(ft32_arg_partial_bytes): Likewise.
	(ft32_valid_pointer_mode): Likewise.
	(ft32_addr_space_pointer_mode): Likewise.
	(ft32_addr_space_address_mode): Likewise.
	(ft32_addr_space_legitimate_address_p): Likewise.
	* config/i386/i386-builtin-types.awk (ix86_builtin_type_vect_mode):
	Use machine_mode_enum instead of machine_mode.  Add E_ prefix to
	initialisers.
	* config/i386/i386-builtin.def (pcmpestr): Add E_ prefixes to mode
	names.
	(pcmpistr): Likewise.
	* config/i386/i386-protos.h (ix86_operands_ok_for_move_multiple):
	Remove "enum" keyword before "machine_mode".
	* config/i386/i386.c (ix86_setup_incoming_vararg_bounds): Likewise.
	(iamcu_alignment): Likewise.
	(canonicalize_vector_int_perm): Likewise.
	(ix86_mpx_bound_mode): Likewise.
	(ix86_operands_ok_for_move_multiple): Likewise.
	(struct expand_vec_perm_d): Use machine_mode_enum instead of
	machine_mode.
	(ix86_expand_sse_pcmpestr): Cast to machine_mode_enum instead of
	machine_mode.
	(ix86_expand_sse_pcmpistr): Likewise.
	* config/iq2000/iq2000.c (iq2000_function_arg): Cast to
	machine_mode_enum instead of machine_mode.
	* config/m32r/m32r.c (init_reg_tables): Likewise.
	* config/microblaze/microblaze-protos.h
	(microblaze_expand_conditional_branch_reg): Remove "enum" keyword
	before "machine_mode".
	* config/microblaze/microblaze.c (double_memory_operand): Add E_
	prefixes to mode names.
	(microblaze_function_arg): Cast to machine_mode_enum instead of
	machine_mode.
	(microblaze_option_override): Likewise.  Remove register keyword.
	(microblaze_expand_conditional_branch_reg): Remove "enum" keyword
	before "machine_mode".
	* config/mips/mips.c (mips_function_arg): Cast to machine_mode_enum
	instead of machine_mode.
	(mips_option_override): Likewise.
	* config/nvptx/nvptx.c (write_return_type): Likewise.
	(nvptx_output_return): Likewise.
	* config/rl78/rl78-protos.h (rl78_split_movsi): Remove "enum" keyword
	before "machine_mode".
	* config/rl78/rl78.c (struct mduc_reg_type): Likewise.
	(rl78_split_movsi): Likewise.
	(rl78_addr_space_address_mode): Likewise.
	* config/rs6000/rs6000.c (rs6000_pmode): Change type from unsigned
	to machine_mode.
	(rs6000_setup_reg_addr_masks): Cast to machine_mode_enum instead of
	machine_mode.
	(rs6000_init_hard_regno_mode_ok): Likewise.  Change types of
	fuse_insns fields from machine_mode to machine_mode_enum.
	Remove "enum" keyword before "machine_mode".
	(rs6000_option_override_internal): Remove casts from assignment
	to rs6000_pmode.
	(rs6000_reassociation_width): Remove "enum" keyword before
	"machine_mode".
	(rs6000_invalid_binary_op): Likewise.
	(fusion_p9_p): Likewise.
	(emit_fusion_p9_load): Likewise.
	(emit_fusion_p9_store): Likewise.
	(htm_expand_builtin): Add E_ prefixes to mode names.
	* config/rs6000/rs6000.h (rs6000_pmode): Change type from unsigned
	to machine_mode.
	(Pmode): Remove cast.
	* config/s390/s390.c (s390_expand_builtin): Add cast to
	machine_mode_enum.
	* config/s390/s390.h (Pmode): Remove cast.
	* config/sh/sh.h (REGISTER_NATURAL_MODE): Add E_ prefixes to mode
	names.
	* config/sparc/sparc.c (emit_save_or_restore_regs): Likewise.
	(sparc_init_modes): Cast to machine_mode_enum instead of machine_mode.
	* config/stormy16/stormy16.c (xstormy16_expand_builtin): Likewise.
	* config/visium/visium-protos.h (prepare_move_operands): Remove
	"enum" keyword before "machine_mode".
	(ok_for_simple_move_operands): Likewise.
	(ok_for_simple_move_strict_operands): Likewise.
	(ok_for_simple_arith_logic_operands): Likewise.
	(visium_legitimize_reload_address): Likewise.
	(visium_select_cc_mode): Likewise.
	(output_cbranch): Likewise.
	(visium_split_double_move): Likewise.
	(visium_expand_copysign): Likewise.
	(visium_expand_int_cstore): Likewise.
	(visium_expand_fp_cstore): Likewise.
	* config/visium/visium.c (visium_legitimate_constant_p): Likewise.
	(prepare_move_operands): Likewise.
	(ok_for_simple_move_operands): Likewise.
	(ok_for_simple_move_strict_operands): Likewise.
	(ok_for_simple_arith_logic_operands): Likewise.
	(visium_pass_by_reference): Likewise.
	(visium_function_arg): Likewise.
	(visium_function_arg_advance): Likewise.
	(visium_function_value_1): Likewise.
	(visium_libcall_value): Likewise.
	(visium_setup_incoming_varargs): Likewise.
	(rtx_ok_for_offset_p): Likewise.
	(visium_legitimate_address_p): Likewise.
	(visium_legitimize_address): Likewise.
	(visium_legitimize_reload_address): Likewise.
	(visium_register_move_cost): Likewise.
	(visium_memory_move_cost): Likewise.
	(visium_split_double_move): Likewise.
	(visium_expand_copysign): Likewise.
	(visium_expand_int_cstore): Likewise.
	(visium_expand_fp_cstore): Likewise.
	(visium_split_cstore): Likewise.
	(visium_select_cc_mode): Likewise.
	(visium_expand_fp_cstore): Likewise.
	(visium_split_cbranch): Likewise.
	(output_cbranch): Likewise.
	(visium_print_operand_address): Likewise.
	(visium_secondary_reload): Likewise.
	* config/xtensa/xtensa.c (xtensa_option_override): Cast to
	machine_mode_enum instead of machine_mode.
	(print_operand): Add E_ prefixes to mode names.
	* cse.c (qty_table_elem): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	(table_elt): Likewise.
	(set): Likewise.
	* doc/tm.texi (TARGET_SETUP_INCOMING_VARARG_BOUNDS): Remove "enum"
	keyword before "machine_mode".
	(TARGET_CHKP_BOUND_MODE): Likewise.
	* emit-rtl.c (init_emit_regs): Cast to machine_mode_enum instead
	of machine_mode.
	(init_emit_once): Likewise.
	* expmed.c (init_expmed_one_mode): Likewise.
	(init_expmed): Likewise.
	(flip_storage_order): Remove "enum" keyword before "machine_mode".
	* expmed.h (struct alg_hash_entry): Add E_ prefixes to mode names.
	(emit_cstore): Remove "enum" keyword before "machine_mode".
	(flip_storage_order): Likewise.
	* expr.c (init_expr_target): Cast to machine_mode_enum instead
	of machine_mode.
	* fixed-value.h (fixed_value): Likewise.
	* gcse.c (compute_can_copy): Likewise.
	* genconditions.c (write_header): Add a "#define USE_ENUM_MODES".
	* gengtype.c (main): Add machine_mode_enum instead of machine_mode.
	* genmodes.c (emit_mode_nunits_inline): Use machine_mode_enum
	rather than machine_mode for the parameter.
	(emit_mode_nunits_inline): Likewise.
	(emit_mode_inner_inline): Likewise.
	(mode_unit_size_inline): Likewise.
	(mode_unit_precision_inline): Likewise.
	(emit_insn_modes_h): Change enum name to machine_mode_enum.
	Define FOOmode to E_FOOmode if USE_ENUM_MODES is defined.
	* genoutput.c (operand_data): Use machine_mode_enum instead of
	machine_mode.
	(null_operand): Add E_ prefixes to mode names.
	(output_operand_data): Likewise.
	* genrecog.c (match_pattern_2): Cast mode label values to
	machine_mode_enum when passing them to add_decision.
	(print_parameter_value): Add an E_ prefix to mode names.
	* hsa-gen.c (gen_hsa_addr): Remove "enum" keyword before
	"machine_mode".
	* ifcvt.c (cond_exec_process_insns): Cast to machine_mode_enum instead
	of machine_mode.
	* internal-fn.c (expand_arith_overflow): Remove "enum" keyword before
	"machine_mode".
	* ira-color.c (allocno_copy_cost_saving): Likewise.
	* ira-int.h (ira_allocno): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	* ira.c (setup_class_subset_and_memory_move_costs): Cast to
	machine_mode_enum instead of machine_mode.
	(setup_pressure_classes): Likewise.
	(setup_uniform_class_p): Likewise.
	(setup_reg_class_nregs): Likewise.
	(setup_prohibited_class_mode_regs): Likewise.
	(clarify_prohibited_class_mode_regs): Likewise.
	(setup_prohibited_mode_move_regs): Likewise.
	* lists.c (alloc_EXPR_LIST): Cast to machine_mode_enum instead
	of machine_mode.
	* lower-subreg.c (compute_costs): Likewise.
	(dump_choices): Likewise.
	* lra-constraints.c (process_invariant_for_inheritance): Remove
	"enum" keyword before "machine_mode".
	* lra-eliminations.c (move_plus_up): Likewise.
	* lra-int.h (lra_operand_data): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	(lra_insn_reg): Likewise.
	* lra.c (debug_operand_data): Add E_ prefixes to mode names.
	(setup_reg_spill_flag): Cast to machine_mode_enum instead
	of machine_mode.
	* lto-streamer-in.c (lto_input_mode_table): Likewise.
	* lto-streamer-out.c (lto_write_mode_table): Likewise.
	* machmode.h (mode_size): Move earlier in file.
	(mode_precision): Likewise.
	(mode_inner): Likewise.
	(mode_nunits): Likewise.
	(mode_unit_size): Likewise.
	(unit_unit_precision): Likewise.
	(mode_wider): Likewise.
	(mode_2xwider): Likewise.
	(machine_mode): New class.
	(mode_to_bytes): New function.
	(mode_to_bits): Likewise.
	(mode_to_precision): Likewise.
	(mode_to_inner): Likewise.
	(mode_to_unit_size): Likewise.
	(mode_to_unit_precision): Likewise.
	(mode_to_nunits): Likewise.
	(GET_MODE_SIZE): Use mode_to_bytes.
	(GET_MODE_BITSIZE): Use mode_to_bits.
	(GET_MODE_INNER): Use mode_to_inner.
	(GET_MODE_UNIT_SIZE): Use mode_to_unit_size.
	(GET_MODE_UNIT_PRECISION): Use mode_to_unit_precision.
	(GET_MODE_NUNITS): Use mode_to_nunits.
	(GET_MODE_WIDER_MODE): Add a cast to machine_mode_enum.
	(GET_MODE_2XWIDER_MODE): Likewise.
	(GET_CLASS_NARROWEST_MODE): Likewise.
	(int_n_data_t): Use machine_mode_enum instead of machine_mode.
	* omp-low.c (lower_oacc_reductions): Remove "enum" keyword before
	"machine_mode".
	* optabs.c (debug_optab_libfuncs): Cast to machine_mode_enum instead
	of machine_mode.
	* optabs.h (expand_operand): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	* read-rtl.c (apply_mode_iterator): Cast to machine_mode_enum instead
	of machine_mode.
	* recog.h (insn_operand_data): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	* ree.c (ext_modified): Likewise.
	* reginfo.c (init_reg_sets_1): Cast to machine_mode_enum instead
	of machine_mode.
	(init_reg_modes_target): Likewise.
	(init_fake_stack_mems): Likewise.
	(choose_hard_reg_mode): Likewise.
	* reload1.c (init_reload): Likewise.
	* rtl.h (rtunion): Use machine_mode_enum instead of machine_mode.
	(rtx_def): Use machine_mode_enum and remove ENUM_BITFIELD wrapper.
	(GET_MODE): Use a C++-style cast.
	(REG_NOTE_KIND): Access the mode field directly.
	(PUT_REG_NOTE_KIND): Cast to machine_mode_enum instead of machine_mode.
	* rtlanal.c (add_int_reg_note): Likewise.
	(duplicate_reg_note): Likewise.
	* simplify-rtx.c (simplify_const_relational_operation): Avoid
	a ?: condition.
	(simplify_subreg): Remove "enum" keyword before
	"machine_mode".
	* system.h (ALWAYS_INLINE): New macro.
	* target.def (chkp_bound_mode): Remove "enum" keyword before
	"machine_mode".
	(setup_incoming_vararg_bounds): Likewise.
	* targhooks.c (default_chkp_bound_mode): Likewise.
	(default_setup_incoming_vararg_bounds): Likewise.
	* targhooks.h (default_chkp_bound_mode): Likewise.
	(default_setup_incoming_vararg_bounds): Likewise.
	* tree-core.h (tree_type_common): Use machine_mode_enum and remove
	ENUM_BITFIELD wrapper.
	(tree_decl_common): Likewise.
	* tree-ssa-math-opts.c (divmod_candidate_p): Remove "enum" keyword
	before "machine_mode".
	* tree-streamer.h (bp_pack_machine_mode): Take a machine_mode_enum
	rather than a machine_mode.
	(bp_unpack_machine_mode): Return a machine_mode_enum rather than
	a machine_mode.
	* tree-vect-loop.c (calc_vec_perm_mask_for_shift): Remove "enum"
	keyword before "machine_mode".
	(have_whole_vector_shift): Likewise.
	* tree-vect-stmts.c (vectorizable_load): Likewise.
	* tree.c (build_common_builtin_nodes): Cast to machine_mode_enum
	instead of machine_mode.
	* tree.h (TYPE_MODE): Cast the mode to a constant reference.
	(DECL_MODE): Likewise.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/misc.c (enumerate_modes): Cast to machine_mode_enum
	instead of machine_mode.

gcc/c-family/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* c-attribs.c (handle_mode_attribute): Cast to machine_mode_enum
	instead of machine_mode.
	* c-common.h (c_default_pointer_mode): Change type to
	machine_mode_enum.
	* c-common.c (c_default_pointer_mode): Likewise.

gcc/fortran/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* trans-types.c (gfc_init_kinds): Use machine_mode_enum rather
	than unsigned int for the "mode" variable.

gcc/jit/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* dummy-frontend.c (jit_langhook_type_for_mode): Remove "enum"
	keyword before "machine_mode".

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 1fed72a..cef4b3a 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -1177,7 +1177,7 @@ enumerate_modes (void (*f) (const char *, int, int, int, int, int, int, int))
 
   for (iloop = 0; iloop < NUM_MACHINE_MODES; iloop++)
     {
-      machine_mode i = (machine_mode) iloop;
+      machine_mode i = (machine_mode_enum) iloop;
       machine_mode inner_mode = i;
       bool float_p = false;
       bool complex_p = false;
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index f5adade..4c4017a 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1303,7 +1303,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 	for (j = 0; j < NUM_MACHINE_MODES; j++)
 	  if (!strcmp (p, GET_MODE_NAME (j)))
 	    {
-	      mode = (machine_mode) j;
+	      mode = (machine_mode_enum) j;
 	      break;
 	    }
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0749361..51253ce 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -53,7 +53,7 @@ cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
 /* Mode used to build pointers (VOIDmode means ptr_mode).  */
 
-machine_mode c_default_pointer_mode = VOIDmode;
+machine_mode_enum c_default_pointer_mode = E_VOIDmode;
 
 /* The following symbols are subsumed in the c_global_trees array, and
    listed here individually for documentation purposes.
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index a23193e..2956f67 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -375,7 +375,7 @@ struct c_common_resword
 
 /* Mode used to build pointers (VOIDmode means ptr_mode).  */
 
-extern machine_mode c_default_pointer_mode;
+extern machine_mode_enum c_default_pointer_mode;
 
 /* Extra cpp_ttype values for C++.  */
 
diff --git a/gcc/calls.c b/gcc/calls.c
index 530e7bf..fcfee25 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -4202,7 +4202,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   for (; count < nargs; count++)
     {
       rtx val = va_arg (p, rtx);
-      machine_mode mode = (machine_mode) va_arg (p, int);
+      machine_mode mode = (machine_mode_enum) va_arg (p, int);
       int unsigned_p = 0;
 
       /* We cannot convert the arg value to the mode the library wants here;
diff --git a/gcc/combine.c b/gcc/combine.c
index b429453..4d9cd09 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -213,7 +213,7 @@ struct reg_stat_type {
 
   unsigned HOST_WIDE_INT	last_set_nonzero_bits;
   char				last_set_sign_bit_copies;
-  ENUM_BITFIELD(machine_mode)	last_set_mode : 8;
+  machine_mode_enum		last_set_mode : 8;
 
   /* Set nonzero if references to register n in expressions should not be
      used.  last_set_invalid is set nonzero when this register is being
@@ -248,7 +248,7 @@ struct reg_stat_type {
      truncation if we know that value already contains a truncated
      value.  */
 
-  ENUM_BITFIELD(machine_mode)	truncated_to_mode : 8;
+  machine_mode_enum		truncated_to_mode : 8;
 };
 
 
@@ -382,7 +382,12 @@ struct undo
 {
   struct undo *next;
   enum undo_kind kind;
-  union { rtx r; int i; machine_mode m; struct insn_link *l; } old_contents;
+  union {
+    rtx r;
+    int i;
+    machine_mode_enum m;
+    struct insn_link *l;
+  } old_contents;
   union { rtx *r; int *i; struct insn_link **l; } where;
 };
 
@@ -6554,7 +6559,7 @@ simplify_if_then_else (rtx x)
       && (i = exact_log2 (UINTVAL (true_rtx) & GET_MODE_MASK (mode))) >= 0)
     {
       rtx val = XEXP (cond, 0);
-      enum machine_mode val_mode = GET_MODE (val);
+      machine_mode val_mode = GET_MODE (val);
       if (val_mode == mode)
         return val;
       else if (GET_MODE_PRECISION (val_mode) < GET_MODE_PRECISION (mode))
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index c66f131..174783d 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -279,7 +279,7 @@ can_eliminate_compare (rtx compare, rtx eh_note, struct comparison *cmp)
     return false;
 
   /* New mode must be compatible with the previous compare mode.  */
-  enum machine_mode new_mode
+  machine_mode new_mode
     = targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode);
 
   if (new_mode == VOIDmode)
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 5ca7506..2dd4048 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -41,30 +41,30 @@
 #include "gimple-iterator.h"
 #include "case-cfn-macros.h"
 
-#define v8qi_UP  V8QImode
-#define v4hi_UP  V4HImode
-#define v4hf_UP  V4HFmode
-#define v2si_UP  V2SImode
-#define v2sf_UP  V2SFmode
-#define v1df_UP  V1DFmode
-#define di_UP    DImode
-#define df_UP    DFmode
-#define v16qi_UP V16QImode
-#define v8hi_UP  V8HImode
-#define v8hf_UP  V8HFmode
-#define v4si_UP  V4SImode
-#define v4sf_UP  V4SFmode
-#define v2di_UP  V2DImode
-#define v2df_UP  V2DFmode
-#define ti_UP	 TImode
-#define oi_UP	 OImode
-#define ci_UP	 CImode
-#define xi_UP	 XImode
-#define si_UP    SImode
-#define sf_UP    SFmode
-#define hi_UP    HImode
-#define hf_UP    HFmode
-#define qi_UP    QImode
+#define v8qi_UP  E_V8QImode
+#define v4hi_UP  E_V4HImode
+#define v4hf_UP  E_V4HFmode
+#define v2si_UP  E_V2SImode
+#define v2sf_UP  E_V2SFmode
+#define v1df_UP  E_V1DFmode
+#define di_UP    E_DImode
+#define df_UP    E_DFmode
+#define v16qi_UP E_V16QImode
+#define v8hi_UP  E_V8HImode
+#define v8hf_UP  E_V8HFmode
+#define v4si_UP  E_V4SImode
+#define v4sf_UP  E_V4SFmode
+#define v2di_UP  E_V2DImode
+#define v2df_UP  E_V2DFmode
+#define ti_UP	 E_TImode
+#define oi_UP	 E_OImode
+#define ci_UP	 E_CImode
+#define xi_UP	 E_XImode
+#define si_UP    E_SImode
+#define sf_UP    E_SFmode
+#define hi_UP    E_HImode
+#define hf_UP    E_HFmode
+#define qi_UP    E_QImode
 #define UP(X) X##_UP
 
 #define SIMD_MAX_BUILTIN_ARGS 5
@@ -106,7 +106,7 @@ enum aarch64_type_qualifiers
 typedef struct
 {
   const char *name;
-  machine_mode mode;
+  machine_mode_enum mode;
   const enum insn_code code;
   unsigned int fcode;
   enum aarch64_type_qualifiers *qualifiers;
@@ -340,7 +340,7 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
 typedef struct
 {
   const char *name;
-  machine_mode mode;
+  machine_mode_enum mode;
   const enum insn_code icode;
   unsigned int fcode;
 } aarch64_crc_builtin_datum;
@@ -381,7 +381,7 @@ enum aarch64_builtins
 
 #undef CRC32_BUILTIN
 #define CRC32_BUILTIN(N, M) \
-  {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
+  {"__builtin_aarch64_"#N, E_##M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
 
 static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
   AARCH64_CRC32_BUILTINS
@@ -453,14 +453,14 @@ struct aarch64_simd_type_info
   tree eltype;
 
   /* Machine mode the internal type maps to.  */
-  enum machine_mode mode;
+  machine_mode_enum mode;
 
   /* Qualifiers.  */
   enum aarch64_type_qualifiers q;
 };
 
 #define ENTRY(E, M, Q, G)  \
-  {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
+  {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, E_##M##mode, qualifier_##Q},
 static struct aarch64_simd_type_info aarch64_simd_types [] = {
 #include "aarch64-simd-builtin-types.def"
 };
@@ -526,7 +526,7 @@ aarch64_mangle_builtin_type (const_tree type)
 }
 
 static tree
-aarch64_simd_builtin_std_type (enum machine_mode mode,
+aarch64_simd_builtin_std_type (machine_mode mode,
 			       enum aarch64_type_qualifiers q)
 {
 #define QUAL_TYPE(M)  \
@@ -562,7 +562,7 @@ aarch64_simd_builtin_std_type (enum machine_mode mode,
 }
 
 static tree
-aarch64_lookup_simd_builtin_type (enum machine_mode mode,
+aarch64_lookup_simd_builtin_type (machine_mode mode,
 				  enum aarch64_type_qualifiers q)
 {
   int i;
@@ -581,7 +581,7 @@ aarch64_lookup_simd_builtin_type (enum machine_mode mode,
 }
 
 static tree
-aarch64_simd_builtin_type (enum machine_mode mode,
+aarch64_simd_builtin_type (machine_mode mode,
 			   bool unsigned_p, bool poly_p)
 {
   if (poly_p)
@@ -645,7 +645,7 @@ aarch64_init_simd_builtin_types (void)
   for (i = 0; i < nelts; i++)
     {
       tree eltype = aarch64_simd_types[i].eltype;
-      enum machine_mode mode = aarch64_simd_types[i].mode;
+      machine_mode mode = aarch64_simd_types[i].mode;
 
       if (aarch64_simd_types[i].itype == NULL)
 	{
@@ -975,7 +975,7 @@ typedef enum
 static rtx
 aarch64_simd_expand_args (rtx target, int icode, int have_retval,
 			  tree exp, builtin_simd_arg *args,
-			  enum machine_mode builtin_mode)
+			  machine_mode builtin_mode)
 {
   rtx pat;
   rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand.  */
@@ -1000,7 +1000,7 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval,
       else
 	{
 	  tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
-	  enum machine_mode mode = insn_data[icode].operand[opc].mode;
+	  machine_mode mode = insn_data[icode].operand[opc].mode;
 	  op[opc] = expand_normal (arg);
 
 	  switch (thisarg)
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 7f67f14..803d4fc 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -323,8 +323,8 @@ bool aarch64_modes_tieable_p (machine_mode mode1,
 bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
 bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
 bool aarch64_mov_operand_p (rtx, machine_mode);
-int aarch64_simd_attr_length_rglist (enum machine_mode);
-rtx aarch64_reverse_mask (enum machine_mode);
+int aarch64_simd_attr_length_rglist (machine_mode);
+rtx aarch64_reverse_mask (machine_mode);
 bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
 char *aarch64_output_scalar_simd_mov_immediate (rtx, machine_mode);
 char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
@@ -332,8 +332,7 @@ bool aarch64_pad_arg_upward (machine_mode, const_tree);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
 bool aarch64_regno_ok_for_base_p (int, bool);
 bool aarch64_regno_ok_for_index_p (int, bool);
-bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode,
-					    bool high);
+bool aarch64_simd_check_vect_par_cnst_half (rtx, machine_mode, bool);
 bool aarch64_simd_imm_scalar_p (rtx x, machine_mode mode);
 bool aarch64_simd_imm_zero_p (rtx, machine_mode);
 bool aarch64_simd_scalar_immediate_valid_for_move (rtx, machine_mode);
@@ -391,7 +390,7 @@ void aarch64_save_restore_target_globals (tree);
 /* Initialize builtins for SIMD intrinsics.  */
 void init_aarch64_simd_builtins (void);
 
-void aarch64_simd_emit_reg_reg_move (rtx *, enum machine_mode, unsigned int);
+void aarch64_simd_emit_reg_reg_move (rtx *, machine_mode, unsigned int);
 
 /* Expand builtins for SIMD intrinsics.  */
 rtx aarch64_simd_expand_builtin (int, tree, rtx);
@@ -424,7 +423,7 @@ bool aarch64_atomic_ldop_supported_p (enum rtx_code);
 void aarch64_gen_atomic_ldop (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
 void aarch64_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx);
 
-bool aarch64_gen_adjusted_ldpstp (rtx *, bool, enum machine_mode, RTX_CODE);
+bool aarch64_gen_adjusted_ldpstp (rtx *, bool, machine_mode, RTX_CODE);
 #endif /* RTX_CODE */
 
 void aarch64_init_builtins (void);
@@ -448,11 +447,11 @@ extern void aarch64_final_prescan_insn (rtx_insn *);
 extern bool
 aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
 void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *);
-int aarch64_ccmp_mode_to_code (enum machine_mode mode);
+int aarch64_ccmp_mode_to_code (machine_mode mode);
 
 bool extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset);
-bool aarch64_operands_ok_for_ldpstp (rtx *, bool, enum machine_mode);
-bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, enum machine_mode);
+bool aarch64_operands_ok_for_ldpstp (rtx *, bool, machine_mode);
+bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, machine_mode);
 extern bool aarch64_nopcrelative_literal_loads;
 
 extern void aarch64_asm_output_pool_epilogue (FILE *, const char *,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 4ffc458..944577d 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -934,7 +934,7 @@ static reg_class_t
 aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
 					 reg_class_t best_class)
 {
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (allocno_class != ALL_REGS)
     return allocno_class;
@@ -947,7 +947,7 @@ aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class,
 }
 
 static unsigned int
-aarch64_min_divisions_for_recip_mul (enum machine_mode mode)
+aarch64_min_divisions_for_recip_mul (machine_mode mode)
 {
   if (GET_MODE_UNIT_SIZE (mode) == 4)
     return aarch64_tune_params.min_div_recip_mul_sf;
@@ -956,7 +956,7 @@ aarch64_min_divisions_for_recip_mul (enum machine_mode mode)
 
 static int
 aarch64_reassociation_width (unsigned opc ATTRIBUTE_UNUSED,
-			     enum machine_mode mode)
+			     machine_mode mode)
 {
   if (VECTOR_MODE_P (mode))
     return aarch64_tune_params.vec_reassoc_width;
@@ -3014,7 +3014,7 @@ static void
 aarch64_push_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment)
 {
   rtx_insn *insn;
-  machine_mode mode = (regno1 <= R30_REGNUM) ? DImode : DFmode;
+  machine_mode mode = (regno1 <= R30_REGNUM) ? E_DImode : E_DFmode;
 
   if (regno2 == INVALID_REGNUM)
     return aarch64_pushwb_single_reg (mode, regno1, adjustment);
@@ -3057,7 +3057,7 @@ static void
 aarch64_pop_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment,
 		  rtx *cfi_ops)
 {
-  machine_mode mode = (regno1 <= R30_REGNUM) ? DImode : DFmode;
+  machine_mode mode = (regno1 <= R30_REGNUM) ? E_DImode : E_DFmode;
   rtx reg1 = gen_rtx_REG (mode, regno1);
 
   *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops);
@@ -3379,7 +3379,7 @@ aarch64_process_components (sbitmap components, bool prologue_p)
     {
       /* AAPCS64 section 5.1.2 requires only the bottom 64 bits to be saved
 	 so DFmode for the vector registers is enough.  */
-      machine_mode mode = GP_REGNUM_P (regno) ? DImode : DFmode;
+      machine_mode mode = GP_REGNUM_P (regno) ? E_DImode : E_DFmode;
       rtx reg = gen_rtx_REG (mode, regno);
       HOST_WIDE_INT offset = cfun->machine->frame.reg_offset[regno];
       if (!frame_pointer_needed)
@@ -4676,7 +4676,7 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
 }
 
 static int
-aarch64_get_condition_code_1 (enum machine_mode, enum rtx_code);
+aarch64_get_condition_code_1 (machine_mode, enum rtx_code);
 
 int
 aarch64_get_condition_code (rtx x)
@@ -4690,7 +4690,7 @@ aarch64_get_condition_code (rtx x)
 }
 
 static int
-aarch64_get_condition_code_1 (enum machine_mode mode, enum rtx_code comp_code)
+aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code)
 {
   switch (mode)
     {
@@ -11372,7 +11372,7 @@ aarch64_simd_mem_operand_p (rtx op)
    COUNT is the number of components into which the copy needs to be
    decomposed.  */
 void
-aarch64_simd_emit_reg_reg_move (rtx *operands, enum machine_mode mode,
+aarch64_simd_emit_reg_reg_move (rtx *operands, machine_mode mode,
 				unsigned int count)
 {
   unsigned int i;
@@ -11393,7 +11393,7 @@ aarch64_simd_emit_reg_reg_move (rtx *operands, enum machine_mode mode,
 /* Compute and return the length of aarch64_simd_reglist<mode>, where <mode> is
    one of VSTRUCT modes: OI, CI, or XI.  */
 int
-aarch64_simd_attr_length_rglist (enum machine_mode mode)
+aarch64_simd_attr_length_rglist (machine_mode mode)
 {
   return (GET_MODE_SIZE (mode) / UNITS_PER_VREG) * 4;
 }
@@ -13308,7 +13308,7 @@ aarch64_vectorize_vec_perm_const_ok (machine_mode vmode,
 }
 
 rtx
-aarch64_reverse_mask (enum machine_mode mode)
+aarch64_reverse_mask (machine_mode mode)
 {
   /* We have to reverse each vector because we dont have
      a permuted load that can reverse-load according to ABI rules.  */
@@ -14078,7 +14078,7 @@ aarch64_sched_fusion_priority (rtx_insn *insn, int max_pri,
 
 bool
 aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
-				enum machine_mode mode)
+				machine_mode mode)
 {
   HOST_WIDE_INT offval_1, offval_2, msize;
   enum reg_class rclass_1, rclass_2;
@@ -14185,7 +14185,7 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
 
 bool
 aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
-				       enum machine_mode mode)
+				       machine_mode mode)
 {
   enum reg_class rclass_1, rclass_2, rclass_3, rclass_4;
   HOST_WIDE_INT offval_1, offval_2, offval_3, offval_4, msize;
@@ -14319,7 +14319,7 @@ aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
 
 bool
 aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
-			     enum machine_mode mode, RTX_CODE code)
+			     machine_mode mode, RTX_CODE code)
 {
   rtx base, offset, t1, t2;
   rtx mem_1, mem_2, mem_3, mem_4;
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index c417569..c9e68eb 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -615,19 +615,6 @@ enum arm_pcs
   ARM_PCS_UNKNOWN
 };
 
-
-
-
-/* We can't use machine_mode inside a generator file because it
-   hasn't been created yet; we shouldn't be using any code that
-   needs the real definition though, so this ought to be safe.  */
-#ifdef GENERATOR_FILE
-#define MACHMODE int
-#else
-#include "insn-modes.h"
-#define MACHMODE machine_mode
-#endif
-
 #ifndef USED_FOR_TARGET
 /* AAPCS related state tracking.  */
 typedef struct
@@ -641,7 +628,7 @@ typedef struct
   rtx aapcs_reg;		/* Register assigned to this argument.  This
 				   is NULL_RTX if this parameter goes on
 				   the stack.  */
-  MACHMODE aapcs_vfp_rmode;
+  machine_mode aapcs_vfp_rmode;
   int aapcs_stack_words;	/* If the argument is passed on the stack, this
 				   is the number of words needed, after rounding
 				   up.  Only meaningful when
diff --git a/gcc/config/aarch64/cortex-a57-fma-steering.c b/gcc/config/aarch64/cortex-a57-fma-steering.c
index 8b4384c..5aeb7a7 100644
--- a/gcc/config/aarch64/cortex-a57-fma-steering.c
+++ b/gcc/config/aarch64/cortex-a57-fma-steering.c
@@ -603,7 +603,7 @@ fma_node::rename (fma_forest *forest)
     {
       rtx_insn *insn = this->m_insn;
       HARD_REG_SET unavailable;
-      enum machine_mode mode;
+      machine_mode mode;
       int reg;
 
       if (dump_file)
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 37d6540..59774bf 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -2780,7 +2780,7 @@ alpha_emit_conditional_move (rtx cmp, machine_mode mode)
       emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (cmp_code, cmp_mode,
 						   op0, op1)));
 
-      cmp_mode = cmp_mode == DImode ? DFmode : DImode;
+      cmp_mode = cmp_mode == DImode ? E_DFmode : E_DImode;
       op0 = gen_lowpart (cmp_mode, tem);
       op1 = CONST0_RTX (cmp_mode);
       cmp = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index a5eaba0..2b25a37 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -1253,7 +1253,7 @@ arc_init_reg_tables (void)
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
-      machine_mode m = (machine_mode) i;
+      machine_mode m = (machine_mode_enum) i;
 
       switch (GET_MODE_CLASS (m))
 	{
@@ -8674,7 +8674,7 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
     }
   else if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P (addr))
     x = force_reg (Pmode, x);
-  if (memory_address_p ((machine_mode) mode, x))
+  if (memory_address_p ((machine_mode_enum) mode, x))
      return x;
   return NULL_RTX;
 }
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index dcc4a10..fed6a70 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -716,7 +716,7 @@ arm_mangle_builtin_type (const_tree type)
 }
 
 static tree
-arm_simd_builtin_std_type (enum machine_mode mode,
+arm_simd_builtin_std_type (machine_mode mode,
 			   enum arm_type_qualifiers q)
 {
 #define QUAL_TYPE(M)  \
@@ -754,7 +754,7 @@ arm_simd_builtin_std_type (enum machine_mode mode,
 }
 
 static tree
-arm_lookup_simd_builtin_type (enum machine_mode mode,
+arm_lookup_simd_builtin_type (machine_mode mode,
 			      enum arm_type_qualifiers q)
 {
   int i;
@@ -776,8 +776,7 @@ arm_lookup_simd_builtin_type (enum machine_mode mode,
 }
 
 static tree
-arm_simd_builtin_type (enum machine_mode mode,
-			   bool unsigned_p, bool poly_p)
+arm_simd_builtin_type (machine_mode mode, bool unsigned_p, bool poly_p)
 {
   if (poly_p)
     return arm_lookup_simd_builtin_type (mode, qualifier_poly);
@@ -851,7 +850,7 @@ arm_init_simd_builtin_types (void)
   for (i = 0; i < nelts; i++)
     {
       tree eltype = arm_simd_types[i].eltype;
-      enum machine_mode mode = arm_simd_types[i].mode;
+      machine_mode mode = arm_simd_types[i].mode;
 
       if (arm_simd_types[i].itype == NULL)
 	arm_simd_types[i].itype =
@@ -2165,7 +2164,7 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode,
 	      gcc_assert (argc > 0);
 	      if (CONST_INT_P (op[argc]))
 		{
-		  enum machine_mode vmode = mode[argc - 1];
+		  machine_mode vmode = mode[argc - 1];
 		  neon_lane_bounds (op[argc], 0, GET_MODE_NUNITS (vmode), exp);
 		}
 	      /* If the lane index isn't a constant then the next
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 05d73ab..3406d51 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -47,7 +47,7 @@ extern unsigned int arm_dbx_register_number (unsigned int);
 extern void arm_output_fn_unwind (FILE *, bool);
 
 extern rtx arm_expand_builtin (tree exp, rtx target, rtx subtarget
-			       ATTRIBUTE_UNUSED, enum machine_mode mode
+			       ATTRIBUTE_UNUSED, machine_mode mode
 			       ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED);
 extern tree arm_builtin_decl (unsigned code, bool initialize_p
 			      ATTRIBUTE_UNUSED);
diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c
index 46578d6..b006416 100644
--- a/gcc/config/avr/avr-log.c
+++ b/gcc/config/avr/avr-log.c
@@ -195,7 +195,7 @@ avr_log_vadump (FILE *file, const char *caller, va_list ap)
               break;
 
             case 'm':
-              fputs (GET_MODE_NAME ((machine_mode) va_arg (ap, int)),
+              fputs (GET_MODE_NAME ((machine_mode_enum) va_arg (ap, int)),
                      file);
               break;
 
diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c
index 6ac8701..5679dad 100644
--- a/gcc/config/ft32/ft32.c
+++ b/gcc/config/ft32/ft32.c
@@ -79,7 +79,7 @@ ft32_function_value (const_tree valtype,
    We always return values in register $r0 for ft32.  */
 
 static rtx
-ft32_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+ft32_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
 {
   return gen_rtx_REG (mode, FT32_R0);
 }
@@ -625,7 +625,7 @@ ft32_initial_elimination_offset (int from, int to)
 
 static void
 ft32_setup_incoming_varargs (cumulative_args_t cum_v,
-			     enum machine_mode mode,
+			     machine_mode mode,
 			     tree type ATTRIBUTE_UNUSED,
 			     int *pretend_size, int no_rtl ATTRIBUTE_UNUSED)
 {
@@ -653,7 +653,7 @@ ft32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
    NULL_RTX if there's no more space.  */
 
 static rtx
-ft32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
+ft32_function_arg (cumulative_args_t cum_v, machine_mode mode,
                    const_tree type ATTRIBUTE_UNUSED,
                    bool named ATTRIBUTE_UNUSED)
 {
@@ -670,7 +670,7 @@ ft32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
    : (unsigned) int_size_in_bytes (TYPE))
 
 static void
-ft32_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
+ft32_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
                            const_tree type, bool named ATTRIBUTE_UNUSED)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
@@ -684,7 +684,7 @@ ft32_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
 
 static bool
 ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
-                        enum machine_mode mode, const_tree type,
+                        machine_mode mode, const_tree type,
                         bool named ATTRIBUTE_UNUSED)
 {
   unsigned HOST_WIDE_INT size;
@@ -707,7 +707,7 @@ ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
 
 static int
 ft32_arg_partial_bytes (cumulative_args_t cum_v,
-                        enum machine_mode mode, tree type, bool named)
+                        machine_mode mode, tree type, bool named)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   int bytes_left, size;
@@ -790,7 +790,7 @@ ft32_is_mem_pm (rtx o)
 #undef TARGET_VALID_POINTER_MODE
 #define TARGET_VALID_POINTER_MODE ft32_valid_pointer_mode
 static bool
-ft32_valid_pointer_mode (enum machine_mode mode)
+ft32_valid_pointer_mode (machine_mode mode)
 {
   if (mode == SImode)
     return 1;
@@ -799,7 +799,7 @@ ft32_valid_pointer_mode (enum machine_mode mode)
 
 #undef TARGET_ADDR_SPACE_POINTER_MODE
 #define TARGET_ADDR_SPACE_POINTER_MODE ft32_addr_space_pointer_mode
-static enum machine_mode
+static machine_mode
 ft32_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 {
   return Pmode;
@@ -807,7 +807,7 @@ ft32_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 
 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
 #define TARGET_ADDR_SPACE_ADDRESS_MODE ft32_addr_space_address_mode
-static enum machine_mode
+static machine_mode
 ft32_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 {
   return Pmode;
@@ -861,8 +861,7 @@ reg_ok_for_base_p (rtx r, bool strict)
 }
 
 static bool
-ft32_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
-                                      bool strict,
+ft32_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
                                       addr_space_t as ATTRIBUTE_UNUSED)
 {
   if (mode != BLKmode)
diff --git a/gcc/config/i386/i386-builtin-types.awk b/gcc/config/i386/i386-builtin-types.awk
index 1825e9f..b4c8c1d 100644
--- a/gcc/config/i386/i386-builtin-types.awk
+++ b/gcc/config/i386/i386-builtin-types.awk
@@ -179,7 +179,7 @@ END {
     # The vector types are defined via two tables defining the real
     # machine mode and the builtin primitive type.  We use two tables
     # rather than a structure to avoid structure padding and save space.
-    print "static const machine_mode ix86_builtin_type_vect_mode[] = {"
+    print "static const machine_mode_enum ix86_builtin_type_vect_mode[] = {"
     for (i = 0; i < vect_defs; ++i) {
 	if (i == 0)
 	    printf "  "
@@ -187,7 +187,7 @@ END {
 	    printf ",\n  "
 	else
 	    printf ", "
-	printf vect_mode[i] "mode"
+	printf "E_" vect_mode[i] "mode"
     }
     print "\n};\n\n"
 
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 83a5089..d87f9e9 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -66,11 +66,11 @@ BDESC_END (COMI, PCMPESTR)
 BDESC_FIRST (pcmpestr, PCMPESTR,
        OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestri128", IX86_BUILTIN_PCMPESTRI128, UNKNOWN, 0)
 BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestrm128", IX86_BUILTIN_PCMPESTRM128, UNKNOWN, 0)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestria128", IX86_BUILTIN_PCMPESTRA128, UNKNOWN, (int) CCAmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestric128", IX86_BUILTIN_PCMPESTRC128, UNKNOWN, (int) CCCmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestrio128", IX86_BUILTIN_PCMPESTRO128, UNKNOWN, (int) CCOmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestris128", IX86_BUILTIN_PCMPESTRS128, UNKNOWN, (int) CCSmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestriz128", IX86_BUILTIN_PCMPESTRZ128, UNKNOWN, (int) CCZmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestria128", IX86_BUILTIN_PCMPESTRA128, UNKNOWN, (int) E_CCAmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestric128", IX86_BUILTIN_PCMPESTRC128, UNKNOWN, (int) E_CCCmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestrio128", IX86_BUILTIN_PCMPESTRO128, UNKNOWN, (int) E_CCOmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestris128", IX86_BUILTIN_PCMPESTRS128, UNKNOWN, (int) E_CCSmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpestr, "__builtin_ia32_pcmpestriz128", IX86_BUILTIN_PCMPESTRZ128, UNKNOWN, (int) E_CCZmode)
 
 BDESC_END (PCMPESTR, PCMPISTR)
 
@@ -78,11 +78,11 @@ BDESC_END (PCMPESTR, PCMPISTR)
 BDESC_FIRST (pcmpistr, PCMPISTR,
        OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistri128", IX86_BUILTIN_PCMPISTRI128, UNKNOWN, 0)
 BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistrm128", IX86_BUILTIN_PCMPISTRM128, UNKNOWN, 0)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistria128", IX86_BUILTIN_PCMPISTRA128, UNKNOWN, (int) CCAmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistric128", IX86_BUILTIN_PCMPISTRC128, UNKNOWN, (int) CCCmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistrio128", IX86_BUILTIN_PCMPISTRO128, UNKNOWN, (int) CCOmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistris128", IX86_BUILTIN_PCMPISTRS128, UNKNOWN, (int) CCSmode)
-BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistriz128", IX86_BUILTIN_PCMPISTRZ128, UNKNOWN, (int) CCZmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistria128", IX86_BUILTIN_PCMPISTRA128, UNKNOWN, (int) E_CCAmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistric128", IX86_BUILTIN_PCMPISTRC128, UNKNOWN, (int) E_CCCmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistrio128", IX86_BUILTIN_PCMPISTRO128, UNKNOWN, (int) E_CCOmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistris128", IX86_BUILTIN_PCMPISTRS128, UNKNOWN, (int) E_CCSmode)
+BDESC (OPTION_MASK_ISA_SSE4_2, CODE_FOR_sse4_2_pcmpistr, "__builtin_ia32_pcmpistriz128", IX86_BUILTIN_PCMPISTRZ128, UNKNOWN, (int) E_CCZmode)
 
 BDESC_END (PCMPISTR, SPECIAL_ARGS)
 
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index edd6cbe..0e4b4b3 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -316,7 +316,7 @@ extern enum attr_cpu ix86_schedule;
 
 extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
 extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
-						enum machine_mode mode);
+						machine_mode mode);
 
 #ifdef RTX_CODE
 /* Target data for multipass lookahead scheduling.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a3ebd11..8d4c1db 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10938,7 +10938,7 @@ ix86_setup_incoming_varargs (cumulative_args_t cum_v, machine_mode mode,
 
 static void
 ix86_setup_incoming_vararg_bounds (cumulative_args_t cum_v,
-				   enum machine_mode mode,
+				   machine_mode mode,
 				   tree type,
 				   int *pretend_size ATTRIBUTE_UNUSED,
 				   int no_rtl)
@@ -24456,7 +24456,7 @@ struct expand_vec_perm_d
 {
   rtx target, op0, op1;
   unsigned char perm[MAX_VECT_LEN];
-  machine_mode vmode;
+  machine_mode_enum vmode;
   unsigned char nelt;
   bool one_operand_p;
   bool testing_p;
@@ -30180,7 +30180,7 @@ ix86_constant_alignment (tree exp, int align)
 static int
 iamcu_alignment (tree type, int align)
 {
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (align < 32 || TYPE_USER_ALIGN (type))
     return align;
@@ -34619,7 +34619,7 @@ ix86_expand_sse_pcmpestr (const struct builtin_description *d,
       emit_insn
 	(gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
 		      gen_rtx_fmt_ee (EQ, QImode,
-				      gen_rtx_REG ((machine_mode) d->flag,
+				      gen_rtx_REG ((machine_mode_enum) d->flag,
 						   FLAGS_REG),
 				      const0_rtx)));
       return SUBREG_REG (target);
@@ -34714,7 +34714,7 @@ ix86_expand_sse_pcmpistr (const struct builtin_description *d,
       emit_insn
 	(gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
 		      gen_rtx_fmt_ee (EQ, QImode,
-				      gen_rtx_REG ((machine_mode) d->flag,
+				      gen_rtx_REG ((machine_mode_enum) d->flag,
 						   FLAGS_REG),
 				      const0_rtx)));
       return SUBREG_REG (target);
@@ -46153,7 +46153,7 @@ canonicalize_vector_int_perm (const struct expand_vec_perm_d *d,
 			      struct expand_vec_perm_d *nd)
 {
   int i;
-  enum machine_mode mode = VOIDmode;
+  machine_mode mode = VOIDmode;
 
   switch (d->vmode)
     {
@@ -50842,7 +50842,7 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
 /* Return mode to be used for bounds or VOIDmode
    if bounds are not supported.  */
 
-static enum machine_mode
+static machine_mode
 ix86_mpx_bound_mode ()
 {
   /* Do not support pointer checker if MPX
@@ -50962,7 +50962,7 @@ extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset)
 
 bool
 ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
-				    enum machine_mode mode)
+				    machine_mode mode)
 {
   HOST_WIDE_INT offval_1, offval_2, msize;
   rtx mem_1, mem_2, reg_1, reg_2, base_1, base_2, offset_1, offset_2;
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index 5664360..96a35aa 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -1360,7 +1360,7 @@ iq2000_function_arg (cumulative_args_t cum_v, machine_mode mode,
   if (mode == VOIDmode)
     {
       if (cum->num_adjusts > 0)
-	ret = gen_rtx_PARALLEL ((machine_mode) cum->fp_code,
+	ret = gen_rtx_PARALLEL ((machine_mode_enum) cum->fp_code,
 		       gen_rtvec_v (cum->num_adjusts, cum->adjust));
     }
 
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 41c6b60..7c09cc9 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -287,7 +287,7 @@ init_reg_tables (void)
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
-      machine_mode m = (machine_mode) i;
+      machine_mode m = (machine_mode_enum) i;
       
       switch (GET_MODE_CLASS (m))
 	{
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index 1cfaf08..956bc7e 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -33,7 +33,7 @@ extern bool microblaze_expand_move (machine_mode, rtx *);
 extern bool microblaze_expand_block_move (rtx, rtx, rtx, rtx);
 extern void microblaze_expand_divide (rtx *);
 extern void microblaze_expand_conditional_branch (machine_mode, rtx *);
-extern void microblaze_expand_conditional_branch_reg (enum machine_mode, rtx *);
+extern void microblaze_expand_conditional_branch_reg (machine_mode, rtx *);
 extern void microblaze_expand_conditional_branch_sf (rtx *); 
 extern int microblaze_can_use_return_insn (void);
 extern void print_operand (FILE *, rtx, int);
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 3b3ae40..8c98d3f 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -374,7 +374,7 @@ double_memory_operand (rtx op, machine_mode mode)
     return 1;
 
   return memory_address_p ((GET_MODE_CLASS (mode) == MODE_INT
-			    ? SImode : SFmode),
+			    ? E_SImode : E_SFmode),
 			   plus_constant (Pmode, addr, 4));
 }
 
@@ -1572,7 +1572,7 @@ microblaze_function_arg (cumulative_args_t cum_v, machine_mode mode,
   if (mode == VOIDmode)
     {
       if (cum->num_adjusts > 0)
-	ret = gen_rtx_PARALLEL ((machine_mode) cum->fp_code,
+	ret = gen_rtx_PARALLEL ((machine_mode_enum) cum->fp_code,
 				gen_rtvec_v (cum->num_adjusts, cum->adjust));
     }
 
@@ -1674,7 +1674,7 @@ microblaze_option_override (void)
 {
   register int i, start;
   register int regno;
-  register machine_mode mode;
+  machine_mode mode;
   int ver;
 
   microblaze_section_threshold = (global_options_set.x_g_switch_value
@@ -1822,7 +1822,7 @@ microblaze_option_override (void)
   /* Set up array giving whether a given register can hold a given mode.   */
 
   for (mode = VOIDmode;
-       mode != MAX_MACHINE_MODE; mode = (machine_mode) ((int) mode + 1))
+       mode != MAX_MACHINE_MODE; mode = (machine_mode_enum) ((int) mode + 1))
     {
       register int size = GET_MODE_SIZE (mode);
 
@@ -3434,8 +3434,7 @@ microblaze_expand_conditional_branch (machine_mode mode, rtx operands[])
 }
 
 void
-microblaze_expand_conditional_branch_reg (enum machine_mode mode,
-                                          rtx operands[])
+microblaze_expand_conditional_branch_reg (machine_mode mode, rtx operands[])
 {
   enum rtx_code code = GET_CODE (operands[0]);
   rtx cmp_op0 = operands[1];
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 5f764b3..7eca000 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -5928,7 +5928,7 @@ mips_function_arg (cumulative_args_t cum_v, machine_mode mode,
   if (mode == VOIDmode)
     {
       if (TARGET_MIPS16 && cum->fp_code != 0)
-	return gen_rtx_REG ((machine_mode) cum->fp_code, 0);
+	return gen_rtx_REG ((machine_mode_enum) cum->fp_code, 0);
       else
 	return NULL;
     }
@@ -20065,7 +20065,7 @@ mips_option_override (void)
   for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
     for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
       mips_hard_regno_mode_ok[mode][regno]
-	= mips_hard_regno_mode_ok_p (regno, (machine_mode) mode);
+	= mips_hard_regno_mode_ok_p (regno, (machine_mode_enum) mode);
 
   /* Function to allocate machine-dependent function status.  */
   init_machine_status = &mips_init_machine_status;
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 79ffd86..dee687e 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -715,7 +715,7 @@ write_return_type (std::stringstream &s, bool for_proto, tree type)
 	 optimization-level specific, so no caller can make use of
 	 this data, but more importantly for us, we must ensure it
 	 doesn't change the PTX prototype.  */
-      mode = (machine_mode) cfun->machine->return_mode;
+      mode = (machine_mode_enum) cfun->machine->return_mode;
 
       if (mode == VOIDmode)
 	return return_in_mem;
@@ -1286,7 +1286,7 @@ nvptx_output_set_softstack (unsigned src_regno)
 const char *
 nvptx_output_return (void)
 {
-  machine_mode mode = (machine_mode)cfun->machine->return_mode;
+  machine_mode mode = (machine_mode_enum) cfun->machine->return_mode;
 
   if (mode != VOIDmode)
     fprintf (asm_out_file, "\tst.param%s\t[%s_out], %s;\n",
diff --git a/gcc/config/rl78/rl78-protos.h b/gcc/config/rl78/rl78-protos.h
index c4860df..1f8cd55 100644
--- a/gcc/config/rl78/rl78-protos.h
+++ b/gcc/config/rl78/rl78-protos.h
@@ -22,7 +22,7 @@ const char *    rl78_addsi3_internal (rtx *, unsigned int);
 void		rl78_emit_eh_epilogue (rtx);
 void		rl78_expand_compare (rtx *);
 void		rl78_expand_movsi (rtx *);
-void		rl78_split_movsi (rtx *, enum machine_mode);
+void		rl78_split_movsi (rtx *, machine_mode);
 int		rl78_force_nonfar_2 (rtx *, rtx (*gen)(rtx,rtx));
 int		rl78_force_nonfar_3 (rtx *, rtx (*gen)(rtx,rtx,rtx));
 void		rl78_expand_eh_epilogue (rtx);
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index b8fe4c97..d5ea068 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -80,8 +80,8 @@ static const char * const word_regnames[] =
 /* Structure for G13 MDUC registers.  */
 struct mduc_reg_type
 {
-  unsigned int       address;
-  enum machine_mode  mode;
+  unsigned int address;
+  machine_mode mode;
 };
 
 struct mduc_reg_type  mduc_regs[] =
@@ -539,7 +539,7 @@ rl78_expand_movsi (rtx *operands)
 
 /* Generate code to move an SImode value.  */
 void
-rl78_split_movsi (rtx *operands, enum machine_mode omode)
+rl78_split_movsi (rtx *operands, machine_mode omode)
 {
   rtx op00, op02, op10, op12;
 
@@ -997,7 +997,7 @@ rl78_hl_b_c_addr_p (rtx op)
 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
 #define TARGET_ADDR_SPACE_ADDRESS_MODE rl78_addr_space_address_mode
 
-static enum machine_mode
+static machine_mode
 rl78_addr_space_address_mode (addr_space_t addrspace)
 {
   switch (addrspace)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7fa5a98..e868cef 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -180,9 +180,8 @@ int dot_symbols;
 
 /* Specify the machine mode that pointers have.  After generation of rtl, the
    compiler makes no further distinction between pointers and any other objects
-   of this machine mode.  The type is unsigned since not all things that
-   include rs6000.h also include machmode.h.  */
-unsigned rs6000_pmode;
+   of this machine mode.  */
+machine_mode rs6000_pmode;
 
 /* Width in bits of a pointer.  */
 unsigned rs6000_pointer_size;
@@ -2789,7 +2788,7 @@ rs6000_setup_reg_addr_masks (void)
 
   for (m = 0; m < NUM_MACHINE_MODES; ++m)
     {
-      machine_mode m2 = (machine_mode) m;
+      machine_mode m2 = (machine_mode_enum) m;
       bool complex_p = false;
       bool small_int_p = (m2 == QImode || m2 == HImode || m2 == SImode);
       size_t msize;
@@ -3432,8 +3431,8 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_P9_FUSION)
     {
       struct fuse_insns {
-	enum machine_mode mode;			/* mode of the fused type.  */
-	enum machine_mode pmode;		/* pointer mode.  */
+	machine_mode_enum mode;			/* mode of the fused type.  */
+	machine_mode_enum pmode;		/* pointer mode.  */
 	enum rs6000_reload_reg_type rtype;	/* register type.  */
 	enum insn_code load;			/* load insn.  */
 	enum insn_code store;			/* store insn.  */
@@ -3505,12 +3504,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
 	  CODE_FOR_fusion_gpr_di_df_store },
       };
 
-      enum machine_mode cur_pmode = Pmode;
+      machine_mode cur_pmode = Pmode;
       size_t i;
 
       for (i = 0; i < ARRAY_SIZE (addis_insns); i++)
 	{
-	  enum machine_mode xmode = addis_insns[i].mode;
+	  machine_mode xmode = addis_insns[i].mode;
 	  enum rs6000_reload_reg_type rtype = addis_insns[i].rtype;
 
 	  if (addis_insns[i].pmode != cur_pmode)
@@ -3555,12 +3554,12 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
     for (m = 0; m < NUM_MACHINE_MODES; ++m)
       rs6000_hard_regno_nregs[m][r]
-	= rs6000_hard_regno_nregs_internal (r, (machine_mode)m);
+	= rs6000_hard_regno_nregs_internal (r, (machine_mode_enum) m);
 
   /* Precalculate HARD_REGNO_MODE_OK.  */
   for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
     for (m = 0; m < NUM_MACHINE_MODES; ++m)
-      if (rs6000_hard_regno_mode_ok (r, (machine_mode)m))
+      if (rs6000_hard_regno_mode_ok (r, (machine_mode_enum) m))
 	rs6000_hard_regno_mode_ok_p[m][r] = true;
 
   /* Precalculate CLASS_MAX_NREGS sizes.  */
@@ -3582,7 +3581,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
 
       for (m = 0; m < NUM_MACHINE_MODES; ++m)
 	{
-	  machine_mode m2 = (machine_mode)m;
+	  machine_mode m2 = (machine_mode_enum) m;
 	  int reg_size2 = reg_size;
 
 	  /* TDmode & IBM 128-bit floating point always takes 2 registers, even
@@ -3861,12 +3860,12 @@ rs6000_option_override_internal (bool global_init_p)
   /* Set the pointer size.  */
   if (TARGET_64BIT)
     {
-      rs6000_pmode = (int)DImode;
+      rs6000_pmode = DImode;
       rs6000_pointer_size = 64;
     }
   else
     {
-      rs6000_pmode = (int)SImode;
+      rs6000_pmode = SImode;
       rs6000_pointer_size = 32;
     }
 
@@ -9866,7 +9865,7 @@ rs6000_offsettable_memref_p (rtx op, machine_mode reg_mode)
  
 static int
 rs6000_reassociation_width (unsigned int opc ATTRIBUTE_UNUSED,
-                            enum machine_mode mode)
+                            machine_mode mode)
 {
   switch (rs6000_cpu)
     {
@@ -14839,7 +14838,7 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp)
 
 	if (nonvoid)
 	  {
-	    machine_mode tmode = (uses_spr) ? insn_op->mode : SImode;
+	    machine_mode tmode = (uses_spr) ? insn_op->mode : E_SImode;
 	    if (!target
 		|| GET_MODE (target) != tmode
 		|| (uses_spr && !(*insn_op->predicate) (target, tmode)))
@@ -23392,8 +23391,8 @@ rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED,
 			  const_tree type1,
 			  const_tree type2)
 {
-  enum machine_mode mode1 = TYPE_MODE (type1);
-  enum machine_mode mode2 = TYPE_MODE (type2);
+  machine_mode mode1 = TYPE_MODE (type1);
+  machine_mode mode2 = TYPE_MODE (type2);
 
   /* For complex modes, use the inner type.  */
   if (COMPLEX_MODE_P (mode1))
@@ -39694,7 +39693,7 @@ fusion_p9_p (rtx addis_reg,		/* register set via addis.  */
 	     rtx src)			/* source (register or memory).  */
 {
   rtx addr, mem, offset;
-  enum machine_mode mode = GET_MODE (src);
+  machine_mode mode = GET_MODE (src);
 
   /* Validate arguments.  */
   if (!base_reg_operand (addis_reg, GET_MODE (addis_reg)))
@@ -39868,7 +39867,7 @@ expand_fusion_p9_store (rtx *operands)
 const char *
 emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
 {
-  enum machine_mode mode = GET_MODE (reg);
+  machine_mode mode = GET_MODE (reg);
   rtx hi;
   rtx lo;
   rtx addr;
@@ -39961,7 +39960,7 @@ emit_fusion_p9_load (rtx reg, rtx mem, rtx tmp_reg)
 const char *
 emit_fusion_p9_store (rtx mem, rtx reg, rtx tmp_reg)
 {
-  enum machine_mode mode = GET_MODE (reg);
+  machine_mode mode = GET_MODE (reg);
   rtx hi;
   rtx lo;
   rtx addr;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 5d56927..0c68f28 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2211,8 +2211,8 @@ do {									     \
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
-extern unsigned rs6000_pmode;
-#define Pmode ((machine_mode)rs6000_pmode)
+extern machine_mode rs6000_pmode;
+#define Pmode rs6000_pmode
 
 /* Supply definition of STACK_SIZE_MODE for allocate_dynamic_stack_space.  */
 #define STACK_SIZE_MODE (TARGET_32BIT ? SImode : DImode)
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b6740dc..a48663d 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -975,7 +975,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 	     so we cannot use this.  */
 	  machine_mode target_mode =
 	    (insn_op->predicate == address_operand
-	     ? Pmode : insn_op->mode);
+	     ? (machine_mode_enum) Pmode : insn_op->mode);
 	  op[arity] = copy_to_mode_reg (target_mode, op[arity]);
 	}
 
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 1d6d7b2..d7c9b34 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -1032,7 +1032,7 @@ do {									\
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
    between pointers and any other objects of this machine mode.  */
-#define Pmode ((machine_mode) (TARGET_64BIT ? DImode : SImode))
+#define Pmode (TARGET_64BIT ? DImode : SImode)
 
 /* This is -1 for "pointer mode" extend.  See ptr_extend in s390.md.  */
 #define POINTERS_EXTEND_UNSIGNED -1
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index fe6623e..2e9876c 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -689,7 +689,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 /* The mode that should be generally used to store a register by
    itself in the stack, or to load it back.  */
 #define REGISTER_NATURAL_MODE(REGNO) \
-  (FP_REGISTER_P (REGNO) ? SFmode : XD_REGISTER_P (REGNO) ? DFmode : SImode)
+  (FP_REGISTER_P (REGNO) ? E_SFmode \
+   : XD_REGISTER_P (REGNO) ? E_DFmode : E_SImode)
 
 
 #define FIRST_PSEUDO_REGISTER 156
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 37814d6..995b0af 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -4895,7 +4895,7 @@ sparc_init_modes (void)
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {
-      machine_mode m = (machine_mode) i;
+      machine_mode m = (machine_mode_enum) i;
       unsigned int size = GET_MODE_SIZE (m);
 
       switch (GET_MODE_CLASS (m))
@@ -5370,17 +5370,17 @@ emit_save_or_restore_regs (unsigned int low, unsigned int high, rtx base,
 
 	  if (reg0 && reg1)
 	    {
-	      mode = SPARC_INT_REG_P (i) ? DImode : DFmode;
+	      mode = SPARC_INT_REG_P (i) ? E_DImode : E_DFmode;
 	      regno = i;
 	    }
 	  else if (reg0)
 	    {
-	      mode = SPARC_INT_REG_P (i) ? SImode : SFmode;
+	      mode = SPARC_INT_REG_P (i) ? E_SImode : E_SFmode;
 	      regno = i;
 	    }
 	  else if (reg1)
 	    {
-	      mode = SPARC_INT_REG_P (i) ? SImode : SFmode;
+	      mode = SPARC_INT_REG_P (i) ? E_SImode : E_SFmode;
 	      regno = i + 1;
 	      offset += 4;
 	    }
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index f74b4d9..50cd3e1 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -2336,7 +2336,7 @@ xstormy16_expand_builtin (tree exp, rtx target,
 
       copyto[o] = 0;
 
-      omode = (machine_mode) insn_data[code].operand[o].mode;
+      omode = (machine_mode_enum) insn_data[code].operand[o].mode;
       if (ao == 'r')
 	op[o] = target ? target : gen_reg_rtx (omode);
       else if (ao == 't')
diff --git a/gcc/config/visium/visium-protos.h b/gcc/config/visium/visium-protos.h
index 9dcbc67..0eef532 100644
--- a/gcc/config/visium/visium-protos.h
+++ b/gcc/config/visium/visium-protos.h
@@ -32,28 +32,28 @@ extern void visium_profile_hook (void);
 extern int visium_hard_regno_rename_ok (unsigned int, unsigned int);
 extern int visium_initial_elimination_offset (int from, int to);
 #ifdef RTX_CODE
-extern void prepare_move_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_move_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_move_strict_operands (rtx *, enum machine_mode);
-extern bool ok_for_simple_arith_logic_operands (rtx *, enum machine_mode);
+extern void prepare_move_operands (rtx *, machine_mode);
+extern bool ok_for_simple_move_operands (rtx *, machine_mode);
+extern bool ok_for_simple_move_strict_operands (rtx *, machine_mode);
+extern bool ok_for_simple_arith_logic_operands (rtx *, machine_mode);
 extern void visium_initialize_trampoline (rtx, rtx, rtx);
 extern int empty_delay_slot (rtx_insn *);
 extern int gr5_hazard_bypass_p (rtx_insn *, rtx_insn *);
 extern rtx visium_return_addr_rtx (int, rtx);
 extern rtx visium_eh_return_handler_rtx (void);
 extern rtx visium_dynamic_chain_address (rtx);
-extern rtx visium_legitimize_reload_address (rtx, enum machine_mode, int, int,
+extern rtx visium_legitimize_reload_address (rtx, machine_mode, int, int,
 					     int);
-extern enum machine_mode visium_select_cc_mode (enum rtx_code, rtx, rtx);
+extern machine_mode visium_select_cc_mode (enum rtx_code, rtx, rtx);
 extern void visium_split_cbranch (enum rtx_code, rtx, rtx, rtx);
 extern const char *output_ubranch (rtx, rtx_insn *);
-extern const char *output_cbranch (rtx, enum rtx_code, enum machine_mode, int,
+extern const char *output_cbranch (rtx, enum rtx_code, machine_mode, int,
 				   rtx_insn *);
-extern void visium_split_double_move (rtx *, enum machine_mode);
+extern void visium_split_double_move (rtx *, machine_mode);
 extern void visium_split_double_add (enum rtx_code, rtx, rtx, rtx);
-extern void visium_expand_copysign (rtx *, enum machine_mode);
-extern void visium_expand_int_cstore (rtx *, enum machine_mode);
-extern void visium_expand_fp_cstore (rtx *, enum machine_mode);
+extern void visium_expand_copysign (rtx *, machine_mode);
+extern void visium_expand_int_cstore (rtx *, machine_mode);
+extern void visium_expand_fp_cstore (rtx *, machine_mode);
 extern void visium_split_cstore (enum rtx_code, rtx, rtx,
 				 enum rtx_code, rtx, rtx);
 extern int visium_expand_block_move (rtx *);
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c
index bd73136..a5ad410 100644
--- a/gcc/config/visium/visium.c
+++ b/gcc/config/visium/visium.c
@@ -154,13 +154,13 @@ static struct machine_function *visium_init_machine_status (void);
 
 /* Target hooks and TARGET_INITIALIZER  */
 
-static bool visium_pass_by_reference (cumulative_args_t, enum machine_mode,
+static bool visium_pass_by_reference (cumulative_args_t, machine_mode,
 				      const_tree, bool);
 
-static rtx visium_function_arg (cumulative_args_t, enum machine_mode,
+static rtx visium_function_arg (cumulative_args_t, machine_mode,
 				const_tree, bool);
 
-static void visium_function_arg_advance (cumulative_args_t, enum machine_mode,
+static void visium_function_arg_advance (cumulative_args_t, machine_mode,
 					 const_tree, bool);
 
 static bool visium_return_in_memory (const_tree, const_tree fntype);
@@ -168,10 +168,10 @@ static bool visium_return_in_memory (const_tree, const_tree fntype);
 static rtx visium_function_value (const_tree, const_tree fn_decl_or_type,
 				  bool);
 
-static rtx visium_libcall_value (enum machine_mode, const_rtx);
+static rtx visium_libcall_value (machine_mode, const_rtx);
 
 static void visium_setup_incoming_varargs (cumulative_args_t,
-					   enum machine_mode,
+					   machine_mode,
 					   tree, int *, int);
 
 static void visium_va_start (tree valist, rtx nextarg);
@@ -188,9 +188,9 @@ static rtx_insn *visium_md_asm_adjust (vec<rtx> &, vec<rtx> &,
 				       vec<const char *> &,
 				       vec<rtx> &, HARD_REG_SET &);
 
-static bool visium_legitimate_constant_p (enum machine_mode, rtx);
+static bool visium_legitimate_constant_p (machine_mode, rtx);
 
-static bool visium_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool visium_legitimate_address_p (machine_mode, rtx, bool);
 
 static bool visium_print_operand_punct_valid_p (unsigned char);
 static void visium_print_operand (FILE *, rtx, int);
@@ -198,10 +198,10 @@ static void visium_print_operand_address (FILE *, machine_mode, rtx);
 
 static void visium_conditional_register_usage (void);
 
-static rtx visium_legitimize_address (rtx, rtx, enum machine_mode);
+static rtx visium_legitimize_address (rtx, rtx, machine_mode);
 
 static reg_class_t visium_secondary_reload (bool, rtx, reg_class_t,
-					    enum machine_mode,
+					    machine_mode,
 					    secondary_reload_info *);
 
 static bool visium_class_likely_spilled_p (reg_class_t);
@@ -214,10 +214,10 @@ static int visium_adjust_priority (rtx_insn *, int);
 
 static int visium_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
 
-static int visium_register_move_cost (enum machine_mode, reg_class_t,
+static int visium_register_move_cost (machine_mode, reg_class_t,
 				      reg_class_t);
 
-static int visium_memory_move_cost (enum machine_mode, reg_class_t, bool);
+static int visium_memory_move_cost (machine_mode, reg_class_t, bool);
 
 static bool visium_rtx_costs (rtx, machine_mode, int, int, int *, bool);
 
@@ -786,7 +786,7 @@ visium_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
    X is guaranteed to satisfy the CONSTANT_P predicate.  */
 
 static bool
-visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+visium_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
 			      rtx x ATTRIBUTE_UNUSED)
 {
   return true;
@@ -849,7 +849,7 @@ visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
 /* Prepare operands for a move define_expand in MODE.  */
 
 void
-prepare_move_operands (rtx *operands, enum machine_mode mode)
+prepare_move_operands (rtx *operands, machine_mode mode)
 {
   /* If the output is not a register, the input must be.  */
   if (GET_CODE (operands[0]) == MEM && !reg_or_0_operand (operands[1], mode))
@@ -859,7 +859,7 @@ prepare_move_operands (rtx *operands, enum machine_mode mode)
 /* Return true if the operands are valid for a simple move insn.  */
 
 bool
-ok_for_simple_move_operands (rtx *operands, enum machine_mode mode)
+ok_for_simple_move_operands (rtx *operands, machine_mode mode)
 {
   /* One of the operands must be a register.  */
   if (!register_operand (operands[0], mode)
@@ -878,7 +878,7 @@ ok_for_simple_move_operands (rtx *operands, enum machine_mode mode)
 /* Return true if the operands are valid for a simple move strict insn.  */
 
 bool
-ok_for_simple_move_strict_operands (rtx *operands, enum machine_mode mode)
+ok_for_simple_move_strict_operands (rtx *operands, machine_mode mode)
 {
   /* Once the flags are exposed, no simple moves between integer registers.
      Note that, in QImode only, a zero source counts as an integer register
@@ -896,7 +896,7 @@ ok_for_simple_move_strict_operands (rtx *operands, enum machine_mode mode)
    insn.  */
 
 bool
-ok_for_simple_arith_logic_operands (rtx *, enum machine_mode)
+ok_for_simple_arith_logic_operands (rtx *, machine_mode)
 {
   /* Once the flags are exposed, no simple arithmetic or logical operations
      between integer registers.  */
@@ -1244,7 +1244,7 @@ visium_reorg (void)
 
 static bool
 visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
-			  enum machine_mode mode ATTRIBUTE_UNUSED,
+			  machine_mode mode ATTRIBUTE_UNUSED,
 			  const_tree type,
 			  bool named ATTRIBUTE_UNUSED)
 {
@@ -1265,7 +1265,7 @@ visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
    in general registers.  */
 
 static rtx
-visium_function_arg (cumulative_args_t pcum_v, enum machine_mode mode,
+visium_function_arg (cumulative_args_t pcum_v, machine_mode mode,
 		     const_tree type ATTRIBUTE_UNUSED,
 		     bool named ATTRIBUTE_UNUSED)
 {
@@ -1303,7 +1303,7 @@ visium_function_arg (cumulative_args_t pcum_v, enum machine_mode mode,
 
 static void
 visium_function_arg_advance (cumulative_args_t pcum_v,
-			     enum machine_mode mode,
+			     machine_mode mode,
 			     const_tree type ATTRIBUTE_UNUSED,
 			     bool named)
 {
@@ -1355,7 +1355,7 @@ visium_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
 /* Define how scalar values are returned.  */
 
 static rtx
-visium_function_value_1 (enum machine_mode mode)
+visium_function_value_1 (machine_mode mode)
 {
   /* Scalar or complex single precision floating point values
      are returned in floating register f1.  */
@@ -1385,7 +1385,7 @@ visium_function_value (const_tree ret_type,
    be returned.  */
 
 static rtx
-visium_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+visium_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
 {
   return visium_function_value_1 (mode);
 }
@@ -1395,7 +1395,7 @@ visium_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
 
 static void
 visium_setup_incoming_varargs (cumulative_args_t pcum_v,
-			       enum machine_mode mode,
+			       machine_mode mode,
 			       tree type,
 			       int *pretend_size ATTRIBUTE_UNUSED,
 			       int no_rtl)
@@ -1711,7 +1711,7 @@ visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
    address of a memory access in mode MODE.  */
 
 static bool
-rtx_ok_for_offset_p (enum machine_mode mode, rtx op)
+rtx_ok_for_offset_p (machine_mode mode, rtx op)
 {
   if (!CONST_INT_P (op) || INTVAL (op) < 0)
     return false;
@@ -1759,7 +1759,7 @@ rtx_ok_for_offset_p (enum machine_mode mode, rtx op)
    kind of register is required.  */
 
 static bool
-visium_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+visium_legitimate_address_p (machine_mode mode, rtx x, bool strict)
 {
   rtx base;
   unsigned int regno;
@@ -1832,7 +1832,7 @@ visium_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 
 static rtx
 visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
-			   enum machine_mode mode)
+			   machine_mode mode)
 {
   if (GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -1866,7 +1866,7 @@ visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
    that need reloading are indicated by calling push_reload.  */
 
 rtx
-visium_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum,
+visium_legitimize_reload_address (rtx x, machine_mode mode, int opnum,
 				  int type, int ind ATTRIBUTE_UNUSED)
 {
   rtx newrtx, tem = NULL_RTX;
@@ -1915,7 +1915,7 @@ visium_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum,
    relative to that.  */
 
 static int
-visium_register_move_cost (enum machine_mode mode, reg_class_t from,
+visium_register_move_cost (machine_mode mode, reg_class_t from,
 			   reg_class_t to)
 {
   const int numwords = (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) ? 1 : 2;
@@ -1934,7 +1934,7 @@ visium_register_move_cost (enum machine_mode mode, reg_class_t from,
    visium_register_move_cost.  */
 
 static int
-visium_memory_move_cost (enum machine_mode mode,
+visium_memory_move_cost (machine_mode mode,
 			 reg_class_t to ATTRIBUTE_UNUSED,
 			 bool in)
 {
@@ -2042,7 +2042,7 @@ visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
 /* Split a double move of OPERANDS in MODE.  */
 
 void
-visium_split_double_move (rtx *operands, enum machine_mode mode)
+visium_split_double_move (rtx *operands, machine_mode mode)
 {
   bool swap = false;
 
@@ -2152,7 +2152,7 @@ visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2)
 /* Expand a copysign of OPERANDS in MODE.  */
 
 void
-visium_expand_copysign (rtx *operands, enum machine_mode mode)
+visium_expand_copysign (rtx *operands, machine_mode mode)
 {
   rtx op0 = operands[0];
   rtx op1 = operands[1];
@@ -2206,7 +2206,7 @@ visium_expand_copysign (rtx *operands, enum machine_mode mode)
    generated code.  */
 
 void
-visium_expand_int_cstore (rtx *operands, enum machine_mode mode)
+visium_expand_int_cstore (rtx *operands, machine_mode mode)
 {
   enum rtx_code code = GET_CODE (operands[1]);
   rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], sltu;
@@ -2265,7 +2265,7 @@ visium_expand_int_cstore (rtx *operands, enum machine_mode mode)
 
 void
 visium_expand_fp_cstore (rtx *operands,
-			 enum machine_mode mode ATTRIBUTE_UNUSED)
+			 machine_mode mode ATTRIBUTE_UNUSED)
 {
   enum rtx_code code = GET_CODE (operands[1]);
   rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], slt;
@@ -2314,7 +2314,7 @@ void
 visium_split_cstore (enum rtx_code op_code, rtx op0, rtx op1,
 		     enum rtx_code code, rtx op2, rtx op3)
 {
-  enum machine_mode cc_mode = visium_select_cc_mode (code, op2, op3);
+  machine_mode cc_mode = visium_select_cc_mode (code, op2, op3);
 
   /* If a FP cstore was reversed, then it was originally UNGE/UNLE.  */
   if (cc_mode == CCFPEmode && (op_code == NEG || op_code == MINUS))
@@ -2792,7 +2792,7 @@ visium_init_expanders (void)
 /* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE,
    return the mode to be used for the comparison.  */
 
-enum machine_mode
+machine_mode
 visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
 {
   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
@@ -2896,7 +2896,7 @@ visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1)
 void
 visium_split_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx label)
 {
-  enum machine_mode cc_mode = visium_select_cc_mode (code, op0, op1);
+  machine_mode cc_mode = visium_select_cc_mode (code, op0, op1);
   rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM);
 
   rtx x = gen_rtx_COMPARE (cc_mode, op0, op1);
@@ -3091,7 +3091,7 @@ output_ubranch (rtx label, rtx_insn *insn)
    should reverse the sense of the comparison.  INSN is the instruction.  */
 
 const char *
-output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode,
+output_cbranch (rtx label, enum rtx_code code, machine_mode cc_mode,
 		int reversed, rtx_insn *insn)
 {
   const char *cond;
@@ -3299,7 +3299,7 @@ visium_print_operand (FILE *file, rtx op, int letter)
    whose address is ADDR.  */
 
 static void
-visium_print_operand_address (FILE *file, enum machine_mode mode, rtx addr)
+visium_print_operand_address (FILE *file, machine_mode mode, rtx addr)
 {
   switch (GET_CODE (addr))
     {
@@ -4180,7 +4180,7 @@ visium_can_use_return_insn_p (void)
 static reg_class_t
 visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
 			 reg_class_t rclass,
-			 enum machine_mode mode ATTRIBUTE_UNUSED,
+			 machine_mode mode ATTRIBUTE_UNUSED,
 			 secondary_reload_info *sri ATTRIBUTE_UNUSED)
 {
   int regno = true_regnum (x);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index d67c8d3..6e100bb 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -2187,7 +2187,7 @@ xtensa_option_override (void)
   /* Set up array giving whether a given register can hold a given mode.  */
   for (mode = VOIDmode;
        mode != MAX_MACHINE_MODE;
-       mode = (machine_mode) ((int) mode + 1))
+       mode = (machine_mode_enum) ((int) mode + 1))
     {
       int size = GET_MODE_SIZE (mode);
       enum mode_class mclass = GET_MODE_CLASS (mode);
@@ -2323,7 +2323,8 @@ print_operand (FILE *file, rtx x, int letter)
       if (GET_CODE (x) == MEM
 	  && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
 	{
-	  x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
+	  x = adjust_address (x, GET_MODE (x) == DFmode ? E_SFmode : E_SImode,
+			      4);
 	  output_address (GET_MODE (x), XEXP (x, 0));
 	}
       else
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index d618788..f26c1a0 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -55,6 +55,7 @@ typedef const struct simple_bitmap_def *const_sbitmap;
 struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
+class machine_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
    hierarchy, along with the relevant invariant.
diff --git a/gcc/cse.c b/gcc/cse.c
index 72f1c4f..2567765 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -248,7 +248,7 @@ struct qty_table_elem
   /* The sizes of these fields should match the sizes of the
      code and mode fields of struct rtx_def (see rtl.h).  */
   ENUM_BITFIELD(rtx_code) comparison_code : 16;
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
 };
 
 /* The table of all qtys, indexed by qty number.  */
@@ -416,7 +416,7 @@ struct table_elt
   int regcost;
   /* The size of this field should match the size
      of the mode field of struct rtx_def (see rtl.h).  */
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
   char in_memory;
   char is_const;
   char flag;
@@ -4153,7 +4153,7 @@ struct set
   /* Original machine mode, in case it becomes a CONST_INT.
      The size of this field should match the size of the mode
      field of struct rtx_def (see rtl.h).  */
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
   /* A constant equivalent for SET_SRC, if any.  */
   rtx src_const;
   /* Hash value of constant equivalent for SET_SRC.  */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cdf5f48..199ec75 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5163,7 +5163,7 @@ returns bounds for returned pointers.  Arguments meaning is similar to
 @code{TARGET_FUNCTION_VALUE}.
 @end deftypefn
 
-@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARG_BOUNDS (cumulative_args_t @var{args_so_far}, enum machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
+@deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARG_BOUNDS (cumulative_args_t @var{args_so_far}, machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
 Use it to store bounds for anonymous register arguments stored
 into the stack.  Arguments meaning is similar to
 @code{TARGET_SETUP_INCOMING_VARARGS}.
@@ -11323,7 +11323,7 @@ returns upper bound of bounds @var{b}.
 @deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void)
 Return type to be used for bounds
 @end deftypefn
-@deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void)
+@deftypefn {Target Hook} machine_mode TARGET_CHKP_BOUND_MODE (void)
 Return mode to be used for bounds.
 @end deftypefn
 @deftypefn {Target Hook} tree TARGET_CHKP_MAKE_BOUNDS_CONSTANT (HOST_WIDE_INT @var{lb}, HOST_WIDE_INT @var{ub})
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 9eccd68..f0243c7 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5819,7 +5819,7 @@ init_emit_regs (void)
 
   for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
     {
-      mode = (machine_mode) i;
+      mode = (machine_mode_enum) i;
       attrs = ggc_cleared_alloc<mem_attrs> ();
       attrs->align = BITS_PER_UNIT;
       attrs->addrspace = ADDR_SPACE_GENERIC;
@@ -5947,7 +5947,7 @@ init_emit_once (void)
 
       for (mode = MIN_MODE_PARTIAL_INT;
 	   mode <= MAX_MODE_PARTIAL_INT;
-	   mode = (machine_mode)((int)(mode) + 1))
+	   mode = (machine_mode_enum) ((int) mode + 1))
 	const_tiny_rtx[i][(int) mode] = GEN_INT (i);
     }
 
@@ -5960,7 +5960,7 @@ init_emit_once (void)
 
   for (mode = MIN_MODE_PARTIAL_INT;
        mode <= MAX_MODE_PARTIAL_INT;
-       mode = (machine_mode)((int)(mode) + 1))
+       mode = (machine_mode_enum) ((int) mode + 1))
     const_tiny_rtx[3][(int) mode] = constm1_rtx;
       
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT);
@@ -6093,7 +6093,7 @@ init_emit_once (void)
     }
 
   for (i = (int) CCmode; i < (int) MAX_MACHINE_MODE; ++i)
-    if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
+    if (GET_MODE_CLASS ((machine_mode_enum) i) == MODE_CC)
       const_tiny_rtx[0][i] = const0_rtx;
 
   const_tiny_rtx[0][(int) BImode] = const0_rtx;
diff --git a/gcc/expmed.c b/gcc/expmed.c
index fa71056..92c895c 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -205,7 +205,7 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
   if (SCALAR_INT_MODE_P (mode))
     {
       for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;
-	   mode_from = (machine_mode)(mode_from + 1))
+	   mode_from = (machine_mode_enum) (mode_from + 1))
 	init_expmed_one_conv (all, mode, mode_from, speed);
     }
   if (GET_MODE_CLASS (mode) == MODE_INT)
@@ -266,17 +266,17 @@ init_expmed (void)
       set_zero_cost (speed, set_src_cost (const0_rtx, mode, speed));
 
       for (mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
-	   mode = (machine_mode)(mode + 1))
+	   mode = (machine_mode_enum) (mode + 1))
 	init_expmed_one_mode (&all, mode, speed);
 
       if (MIN_MODE_PARTIAL_INT != VOIDmode)
 	for (mode = MIN_MODE_PARTIAL_INT; mode <= MAX_MODE_PARTIAL_INT;
-	     mode = (machine_mode)(mode + 1))
+	     mode = (machine_mode_enum) (mode + 1))
 	  init_expmed_one_mode (&all, mode, speed);
 
       if (MIN_MODE_VECTOR_INT != VOIDmode)
 	for (mode = MIN_MODE_VECTOR_INT; mode <= MAX_MODE_VECTOR_INT;
-	     mode = (machine_mode)(mode + 1))
+	     mode = (machine_mode_enum) (mode + 1))
 	  init_expmed_one_mode (&all, mode, speed);
     }
 
@@ -363,9 +363,9 @@ check_reverse_float_storage_order_support (void)
    useful if X is a CONST_INT.  */
 
 rtx
-flip_storage_order (enum machine_mode mode, rtx x)
+flip_storage_order (machine_mode mode, rtx x)
 {
-  enum machine_mode int_mode;
+  machine_mode int_mode;
   rtx result;
 
   if (mode == QImode)
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 8d0af3c..f22fa1e 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -136,10 +136,10 @@ struct alg_hash_entry {
 #define NUM_MODE_INT \
   (MAX_MODE_INT - MIN_MODE_INT + 1)
 #define NUM_MODE_PARTIAL_INT \
-  (MIN_MODE_PARTIAL_INT == VOIDmode ? 0 \
+  (MIN_MODE_PARTIAL_INT == E_VOIDmode ? 0 \
    : MAX_MODE_PARTIAL_INT - MIN_MODE_PARTIAL_INT + 1)
 #define NUM_MODE_VECTOR_INT \
-  (MIN_MODE_VECTOR_INT == VOIDmode ? 0 \
+  (MIN_MODE_VECTOR_INT == E_VOIDmode ? 0 \
    : MAX_MODE_VECTOR_INT - MIN_MODE_VECTOR_INT + 1)
 
 #define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT)
@@ -679,9 +679,9 @@ convert_cost (machine_mode to_mode, machine_mode from_mode,
 
 extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
 extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
-			enum machine_mode mode, enum machine_mode compare_mode,
+			machine_mode mode, machine_mode compare_mode,
 			int unsignedp, rtx x, rtx y, int normalizep,
-			enum machine_mode target_mode);
+			machine_mode target_mode);
 
 /* Arguments MODE, RTX: return an rtx for the negation of that value.
    May emit insns.  */
@@ -689,7 +689,7 @@ extern rtx negate_rtx (machine_mode, rtx);
 
 /* Arguments MODE, RTX: return an rtx for the flipping of that value.
    May emit insns.  */
-extern rtx flip_storage_order (enum machine_mode, rtx);
+extern rtx flip_storage_order (machine_mode, rtx);
 
 /* Expand a logical AND operation.  */
 extern rtx expand_and (machine_mode, rtx, rtx, rtx);
diff --git a/gcc/expr.c b/gcc/expr.c
index fe752fb..923d258 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -130,7 +130,7 @@ init_expr_target (void)
   PATTERN (insn) = pat;
 
   for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
-       mode = (machine_mode) ((int) mode + 1))
+       mode = (machine_mode_enum) ((int) mode + 1))
     {
       int regno;
 
diff --git a/gcc/fixed-value.h b/gcc/fixed-value.h
index 5532a73..d0d7e63 100644
--- a/gcc/fixed-value.h
+++ b/gcc/fixed-value.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 struct GTY(()) fixed_value
 {
   double_int data;		/* Store data up to 2 wide integers.  */
-  machine_mode mode;	/* Use machine mode to know IBIT and FBIT.  */
+  machine_mode_enum mode;	/* Use machine mode to know IBIT and FBIT.  */
 };
 
 #define FIXED_VALUE_TYPE struct fixed_value
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 354308f..c0d1a17 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -347,22 +347,23 @@ gfc_init_c_interop_kinds (void)
 void
 gfc_init_kinds (void)
 {
-  unsigned int mode;
+  machine_mode_enum mode;
   int i_index, r_index, kind;
   bool saw_i4 = false, saw_i8 = false;
   bool saw_r4 = false, saw_r8 = false, saw_r10 = false, saw_r16 = false;
 
-  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT; mode++)
+  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
+       mode = (machine_mode_enum) ((int) mode + 1))
     {
       int kind, bitsize;
 
-      if (!targetm.scalar_mode_supported_p ((machine_mode) mode))
+      if (!targetm.scalar_mode_supported_p (mode))
 	continue;
 
       /* The middle end doesn't support constants larger than 2*HWI.
 	 Perhaps the target hook shouldn't have accepted these either,
 	 but just to be safe...  */
-      bitsize = GET_MODE_BITSIZE ((machine_mode) mode);
+      bitsize = GET_MODE_BITSIZE (mode);
       if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
 	continue;
 
@@ -402,22 +403,21 @@ gfc_init_kinds (void)
   /* Set the maximum integer kind.  Used with at least BOZ constants.  */
   gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
 
-  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT; mode++)
+  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT;
+       mode = (machine_mode_enum) ((int) mode + 1))
     {
-      const struct real_format *fmt =
-	REAL_MODE_FORMAT ((machine_mode) mode);
+      const struct real_format *fmt = REAL_MODE_FORMAT (mode);
       int kind;
 
       if (fmt == NULL)
 	continue;
-      if (!targetm.scalar_mode_supported_p ((machine_mode) mode))
+      if (!targetm.scalar_mode_supported_p (mode))
 	continue;
 
       /* Only let float, double, long double and __float128 go through.
 	 Runtime support for others is not provided, so they would be
 	 useless.  */
-      if (!targetm.libgcc_floating_mode_supported_p ((machine_mode)
-						       mode))
+      if (!targetm.libgcc_floating_mode_supported_p (mode))
 	continue;
       if (mode != TYPE_MODE (float_type_node)
 	    && (mode != TYPE_MODE (double_type_node))
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 652ee91..e745eb9e 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -550,7 +550,7 @@ compute_can_copy (void)
 #ifdef AVOID_CCMODE_COPIES
 	can_copy[i] = 0;
 #else
-	reg = gen_rtx_REG ((machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
+	reg = gen_rtx_REG ((machine_mode_enum) i, LAST_VIRTUAL_REGISTER + 1);
 	insn = emit_insn (gen_rtx_SET (reg, reg));
 	if (recog (PATTERN (insn), insn, NULL) >= 0)
 	  can_copy[i] = 1;
diff --git a/gcc/genconditions.c b/gcc/genconditions.c
index 63e0784..b54d2de 100644
--- a/gcc/genconditions.c
+++ b/gcc/genconditions.c
@@ -67,6 +67,7 @@ write_header (void)
 #undef ENABLE_RTL_FLAG_CHECKING\n\
 #undef ENABLE_GC_CHECKING\n\
 #undef ENABLE_GC_ALWAYS_COLLECT\n\
+#define USE_ENUM_MODES\n\
 \n\
 #include \"coretypes.h\"\n\
 #include \"tm.h\"\n\
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index a579547..f6041fc 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -5195,7 +5195,7 @@ main (int argc, char **argv)
       POS_HERE (do_scalar_typedef ("jword", &pos));
       POS_HERE (do_scalar_typedef ("JCF_u2", &pos));
       POS_HERE (do_scalar_typedef ("void", &pos));
-      POS_HERE (do_scalar_typedef ("machine_mode", &pos));
+      POS_HERE (do_scalar_typedef ("machine_mode_enum", &pos));
       POS_HERE (do_typedef ("PTR", 
 			    create_pointer (resolve_typedef ("void", &pos)),
 			    &pos));
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 4940079..4dbced2 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -974,7 +974,7 @@ inline __attribute__((__always_inline__))\n\
 extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 #endif\n\
 unsigned short\n\
-mode_size_inline (machine_mode mode)\n\
+mode_size_inline (machine_mode_enum mode)\n\
 {\n\
   extern %sunsigned short mode_size[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
@@ -1005,7 +1005,7 @@ inline __attribute__((__always_inline__))\n\
 extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 #endif\n\
 unsigned char\n\
-mode_nunits_inline (machine_mode mode)\n\
+mode_nunits_inline (machine_mode_enum mode)\n\
 {\n\
   extern const unsigned char mode_nunits[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
@@ -1035,7 +1035,7 @@ inline __attribute__((__always_inline__))\n\
 extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 #endif\n\
 unsigned char\n\
-mode_inner_inline (machine_mode mode)\n\
+mode_inner_inline (machine_mode_enum mode)\n\
 {\n\
   extern const unsigned char mode_inner[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
@@ -1067,7 +1067,7 @@ inline __attribute__((__always_inline__))\n\
 extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 #endif\n\
 unsigned char\n\
-mode_unit_size_inline (machine_mode mode)\n\
+mode_unit_size_inline (machine_mode_enum mode)\n\
 {\n\
   extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];\
 \n\
@@ -1105,7 +1105,7 @@ inline __attribute__((__always_inline__))\n\
 extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 #endif\n\
 unsigned short\n\
-mode_unit_precision_inline (machine_mode mode)\n\
+mode_unit_precision_inline (machine_mode_enum mode)\n\
 {\n\
   extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
@@ -1146,7 +1146,7 @@ emit_insn_modes_h (void)
 #ifndef GCC_INSN_MODES_H\n\
 #define GCC_INSN_MODES_H\n\
 \n\
-enum machine_mode\n{");
+enum machine_mode_enum\n{");
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     for (m = modes[c]; m; m = m->next)
@@ -1155,8 +1155,12 @@ enum machine_mode\n{");
 	printf ("%*s/* %s:%d */\n", 27 - count_, "",
 		 trim_filename (m->file), m->line);
 	printf ("#define HAVE_%smode\n", m->name);
+	printf ("#ifdef USE_ENUM_MODES\n");
+	printf ("#define %smode E_%smode\n", m->name, m->name);
+	printf ("#else\n");
 	printf ("#define %smode (machine_mode (E_%smode))\n",
 		m->name, m->name);
+	printf ("#endif\n");
       }
 
   puts ("  MAX_MACHINE_MODE,\n");
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index fd36c04..021b424 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -115,7 +115,7 @@ struct operand_data
   int index;
   const char *predicate;
   const char *constraint;
-  machine_mode mode;
+  machine_mode_enum mode;
   unsigned char n_alternatives;
   char address_p;
   char strict_low;
@@ -127,7 +127,7 @@ struct operand_data
 
 static struct operand_data null_operand =
 {
-  0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0
+  0, 0, "", "", E_VOIDmode, 0, 0, 0, 0, 0
 };
 
 static struct operand_data *odata = &null_operand;
@@ -253,7 +253,7 @@ output_operand_data (void)
 
       printf ("    \"%s\",\n", d->constraint ? d->constraint : "");
 
-      printf ("    %smode,\n", GET_MODE_NAME (d->mode));
+      printf ("    E_%smode,\n", GET_MODE_NAME (d->mode));
 
       printf ("    %d,\n", d->strict_low);
 
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index e4377c3..ba2df46 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -4058,7 +4058,8 @@ match_pattern_2 (state *s, md_rtx_info *info, position *pos, rtx pattern)
 		   and DImode register_operands, as described above.  */
 		machine_mode mode = GET_MODE (e->pattern);
 		if (pred && safe_predicate_mode (pred, mode))
-		  s = add_decision (s, rtx_test::mode (e->pos), mode, true);
+		  s = add_decision (s, rtx_test::mode (e->pos),
+				    (machine_mode_enum) mode, true);
 
 		/* Assign to operands[] first, so that the rtx usually doesn't
 		   need to be live across the call to the predicate.
@@ -4082,7 +4083,7 @@ match_pattern_2 (state *s, md_rtx_info *info, position *pos, rtx pattern)
 
 	default:
 	  s = add_decision (s, rtx_test::mode (e->pos),
-			    GET_MODE (e->pattern), false);
+			    (machine_mode_enum) GET_MODE (e->pattern), false);
 	  break;
 	}
     }
@@ -4461,7 +4462,7 @@ print_parameter_value (const parameter &param)
 	break;
 
       case parameter::MODE:
-	printf ("%smode", GET_MODE_NAME ((machine_mode) param.value));
+	printf ("E_%smode", GET_MODE_NAME ((machine_mode_enum) param.value));
 	break;
 
       case parameter::INT:
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index a88294e..dd4b45c 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -1929,7 +1929,7 @@ gen_hsa_addr (tree ref, hsa_bb *hbb, HOST_WIDE_INT *output_bitsize = NULL,
 
   if (handled_component_p (ref))
     {
-      enum machine_mode mode;
+      machine_mode mode;
       int unsignedp, volatilep, preversep;
 
       ref = get_inner_reference (ref, &bitsize, &bitpos, &varoffset, &mode,
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 0fdd5b7..b22ed41 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -409,7 +409,7 @@ cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
 
       if (CALL_P (insn) && prob_val >= 0)
 	validate_change (insn, &REG_NOTES (insn),
-			 gen_rtx_INT_LIST ((machine_mode) REG_BR_PROB,
+			 gen_rtx_INT_LIST ((machine_mode_enum) REG_BR_PROB,
 					   prob_val, REG_NOTES (insn)), 1);
 
     insn_done:
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index b1dbc98..0d91b8e 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2117,7 +2117,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
 	  /* The infinity precision result will always fit into result.  */
 	  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
 	  write_complex_part (target, const0_rtx, true);
-	  enum machine_mode mode = TYPE_MODE (type);
+	  machine_mode mode = TYPE_MODE (type);
 	  struct separate_ops ops;
 	  ops.code = code;
 	  ops.type = type;
@@ -2170,7 +2170,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
       if (orig_precres == precres && precop <= BITS_PER_WORD)
 	{
 	  int p = MAX (min_precision, precop);
-	  enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
+	  machine_mode m = smallest_mode_for_size (p, MODE_INT);
 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
 							uns0_p && uns1_p
 							&& unsr_p);
@@ -2212,7 +2212,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
       if (orig_precres == precres)
 	{
 	  int p = MAX (prec0, prec1);
-	  enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
+	  machine_mode m = smallest_mode_for_size (p, MODE_INT);
 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
 							uns0_p && uns1_p
 							&& unsr_p);
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index 5bbb33af..edf8829 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -2735,7 +2735,7 @@ static int
 allocno_copy_cost_saving (ira_allocno_t allocno, int hard_regno)
 {
   int cost = 0;
-  enum machine_mode allocno_mode = ALLOCNO_MODE (allocno);
+  machine_mode allocno_mode = ALLOCNO_MODE (allocno);
   enum reg_class rclass;
   ira_copy_t cp, next_cp;
 
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 52ec090..e59384f 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -280,10 +280,10 @@ struct ira_allocno
   int regno;
   /* Mode of the allocno which is the mode of the corresponding
      pseudo-register.  */
-  ENUM_BITFIELD (machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
   /* Widest mode of the allocno which in at least one case could be
      for paradoxical subregs where wmode > mode.  */
-  ENUM_BITFIELD (machine_mode) wmode : 8;
+  machine_mode_enum wmode : 8;
   /* Register class which should be used for allocation for given
      allocno.  NO_REGS means that we should use memory.  */
   ENUM_BITFIELD (reg_class) aclass : 16;
diff --git a/gcc/ira.c b/gcc/ira.c
index 4a95e3d..70fd884 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -580,11 +580,11 @@ setup_class_subset_and_memory_move_costs (void)
 	  {
 	    ira_max_memory_move_cost[mode][cl][0]
 	      = ira_memory_move_cost[mode][cl][0]
-	      = memory_move_cost ((machine_mode) mode,
+	      = memory_move_cost ((machine_mode_enum) mode,
 				  (reg_class_t) cl, false);
 	    ira_max_memory_move_cost[mode][cl][1]
 	      = ira_memory_move_cost[mode][cl][1]
-	      = memory_move_cost ((machine_mode) mode,
+	      = memory_move_cost ((machine_mode_enum) mode,
 				  (reg_class_t) cl, true);
 	    /* Costs for NO_REGS are used in cost calculation on the
 	       1st pass when the preferred register classes are not
@@ -821,7 +821,8 @@ setup_pressure_classes (void)
 					  ira_prohibited_class_mode_regs[cl][m]);
 		  if (hard_reg_set_empty_p (temp_hard_regset))
 		    continue;
-		  ira_init_register_move_cost_if_necessary ((machine_mode) m);
+		  ira_init_register_move_cost_if_necessary
+		    ((machine_mode_enum) m);
 		  cost = ira_register_move_cost[m][cl][cl];
 		  if (cost <= ira_max_memory_move_cost[m][cl][1]
 		      || cost <= ira_max_memory_move_cost[m][cl][0])
@@ -948,7 +949,8 @@ setup_uniform_class_p (void)
       	  for (m = 0; m < NUM_MACHINE_MODES; m++)
 	    if (contains_reg_of_mode[cl][m] && contains_reg_of_mode[cl2][m])
 	      {
-		ira_init_register_move_cost_if_necessary ((machine_mode) m);
+		ira_init_register_move_cost_if_necessary
+		  ((machine_mode_enum) m);
 		if (ira_register_move_cost[m][cl][cl]
 		    != ira_register_move_cost[m][cl2][cl2])
 		  break;
@@ -1476,7 +1478,7 @@ setup_reg_class_nregs (void)
       for (cl = 0; cl < N_REG_CLASSES; cl++)
 	ira_reg_class_max_nregs[cl][m]
 	  = ira_reg_class_min_nregs[cl][m]
-	  = targetm.class_max_nregs ((reg_class_t) cl, (machine_mode) m);
+	  = targetm.class_max_nregs ((reg_class_t) cl, (machine_mode_enum) m);
       for (cl = 0; cl < N_REG_CLASSES; cl++)
 	for (i = 0;
 	     (cl2 = alloc_reg_class_subclasses[cl][i]) != LIM_REG_CLASSES;
@@ -1508,11 +1510,11 @@ setup_prohibited_class_mode_regs (void)
 	  for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
 	    {
 	      hard_regno = ira_class_hard_regs[cl][k];
-	      if (! HARD_REGNO_MODE_OK (hard_regno, (machine_mode) j))
+	      if (! HARD_REGNO_MODE_OK (hard_regno, (machine_mode_enum) j))
 		SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
 				  hard_regno);
 	      else if (in_hard_reg_set_p (temp_hard_regset,
-					  (machine_mode) j, hard_regno))
+					  (machine_mode_enum) j, hard_regno))
 		{
 		  last_hard_regno = hard_regno;
 		  count++;
@@ -1560,7 +1562,7 @@ clarify_prohibited_class_mode_regs (void)
 	    if (!TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
 				    hard_regno))
 	      add_to_hard_reg_set (&ira_useful_class_mode_regs[cl][j],
-				   (machine_mode) j, hard_regno);
+				   (machine_mode_enum) j, hard_regno);
 	  }
       }
 }
@@ -1754,10 +1756,10 @@ setup_prohibited_mode_move_regs (void)
       SET_HARD_REG_SET (ira_prohibited_mode_move_regs[i]);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
 	{
-	  if (! HARD_REGNO_MODE_OK (j, (machine_mode) i))
+	  if (! HARD_REGNO_MODE_OK (j, (machine_mode_enum) i))
 	    continue;
-	  set_mode_and_regno (test_reg1, (machine_mode) i, j);
-	  set_mode_and_regno (test_reg2, (machine_mode) i, j);
+	  set_mode_and_regno (test_reg1, (machine_mode_enum) i, j);
+	  set_mode_and_regno (test_reg2, (machine_mode_enum) i, j);
 	  INSN_CODE (move_insn) = -1;
 	  recog_memoized (move_insn);
 	  if (INSN_CODE (move_insn) < 0)
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 2631153..e5a54bc 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -163,7 +163,7 @@ jit_langhook_parse_file (void)
 }
 
 static tree
-jit_langhook_type_for_mode (enum machine_mode mode, int unsignedp)
+jit_langhook_type_for_mode (machine_mode mode, int unsignedp)
 {
   if (mode == TYPE_MODE (float_type_node))
     return float_type_node;
diff --git a/gcc/lists.c b/gcc/lists.c
index 96b4bc7..adb0e33 100644
--- a/gcc/lists.c
+++ b/gcc/lists.c
@@ -137,7 +137,7 @@ alloc_EXPR_LIST (int kind, rtx val, rtx next)
       PUT_REG_NOTE_KIND (r, kind);
     }
   else
-    r = gen_rtx_EXPR_LIST ((machine_mode) kind, val, next);
+    r = gen_rtx_EXPR_LIST ((machine_mode_enum) kind, val, next);
 
   return r;
 }
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index 6b75f62..ca4582f 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -197,7 +197,7 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes)
 
   for (i = 0; i < MAX_MACHINE_MODE; i++)
     {
-      machine_mode mode = (machine_mode) i;
+      machine_mode mode = (machine_mode_enum) i;
       int factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
       if (factor > 1)
 	{
@@ -1352,12 +1352,12 @@ dump_choices (bool speed_p, const char *description)
   fprintf (dump_file, "Choices when optimizing for %s:\n", description);
 
   for (i = 0; i < MAX_MACHINE_MODE; i++)
-    if (GET_MODE_SIZE ((machine_mode) i) > UNITS_PER_WORD)
+    if (GET_MODE_SIZE ((machine_mode_enum) i) > UNITS_PER_WORD)
       fprintf (dump_file, "  %s mode %s for copy lowering.\n",
 	       choices[speed_p].move_modes_to_split[i]
 	       ? "Splitting"
 	       : "Skipping",
-	       GET_MODE_NAME ((machine_mode) i));
+	       GET_MODE_NAME ((machine_mode_enum) i));
 
   fprintf (dump_file, "  %s mode %s for zero_extend lowering.\n",
 	   choices[speed_p].splitting_zext ? "Splitting" : "Skipping",
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index e661aef..2ef9ad3 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1789,7 +1789,7 @@ reg_in_class_p (rtx reg, enum reg_class cl)
 static bool
 prohibited_class_reg_set_mode_p (enum reg_class rclass,
 				 HARD_REG_SET &set,
-				 enum machine_mode mode)
+				 machine_mode mode)
 {
   HARD_REG_SET temp;
   
@@ -5513,7 +5513,7 @@ process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx)
   int insn_regno;
   bool succ_p = false;
   int dst_regno = REGNO (dst_reg);
-  enum machine_mode dst_mode = GET_MODE (dst_reg);
+  machine_mode dst_mode = GET_MODE (dst_reg);
   enum reg_class cl = lra_get_allocno_class (dst_regno), insn_reg_cl;
 
   invariant_ptr = insert_invariant (invariant_rtx);
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index b90cbed..c4408dc 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -279,7 +279,7 @@ static rtx
 move_plus_up (rtx x)
 {
   rtx subreg_reg;
-  enum machine_mode x_mode, subreg_reg_mode;
+  machine_mode x_mode, subreg_reg_mode;
   
   if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
     return x;
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index cfab209..688fe20 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -132,7 +132,7 @@ struct lra_operand_data
   const char *constraint;
   /* It is taken only from machine description (which is different
      from recog_data.operand_mode) and can be of VOIDmode.  */
-  ENUM_BITFIELD(machine_mode) mode : 16;
+  machine_mode_enum mode : 16;
   /* The type of the operand (in/out/inout).  */
   ENUM_BITFIELD (op_type) type : 8;
   /* Through if accessed through STRICT_LOW.  */
@@ -153,7 +153,7 @@ struct lra_insn_reg
   /* The biggest mode through which the insn refers to the register
      occurrence (remember the register can be accessed through a
      subreg in the insn).  */
-  ENUM_BITFIELD(machine_mode) biggest_mode : 16;
+  machine_mode_enum biggest_mode : 16;
   /* The type of the corresponding operand which is the register.  */
   ENUM_BITFIELD (op_type) type : 8;
   /* True if the reg is accessed through a subreg and the subreg is
diff --git a/gcc/lra.c b/gcc/lra.c
index 4165492..1e9aead 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -590,7 +590,7 @@ struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES];
 static struct lra_operand_data debug_operand_data =
   {
     NULL, /* alternative  */
-    VOIDmode, /* We are not interesting in the operand mode.  */
+    E_VOIDmode, /* We are not interesting in the operand mode.  */
     OP_IN,
     0, 0, 0, 0
   };
@@ -2275,7 +2275,7 @@ setup_reg_spill_flag (void)
     for (cl = 0; cl < (int) LIM_REG_CLASSES; cl++)
       for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
 	if (targetm.spill_class ((enum reg_class) cl,
-				 (machine_mode) mode) != NO_REGS)
+				 (machine_mode_enum) mode) != NO_REGS)
 	  {
 	    lra_reg_spill_p = true;
 	    return;
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 1f39e6b..69d87e6 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1525,7 +1525,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
 	= bp_unpack_enum (&bp, mode_class, MAX_MODE_CLASS);
       unsigned int size = bp_unpack_value (&bp, 8);
       unsigned int prec = bp_unpack_value (&bp, 16);
-      machine_mode inner = (machine_mode) bp_unpack_value (&bp, 8);
+      machine_mode inner = (machine_mode_enum) bp_unpack_value (&bp, 8);
       unsigned int nunits = bp_unpack_value (&bp, 8);
       unsigned int ibit = 0, fbit = 0;
       unsigned int real_fmt_len = 0;
@@ -1554,7 +1554,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
 	for (machine_mode mr = pass ? VOIDmode
 				    : GET_CLASS_NARROWEST_MODE (mclass);
 	     pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode;
-	     pass ? mr = (machine_mode) (mr + 1)
+	     pass ? mr = (machine_mode_enum) (mr + 1)
 		  : mr = GET_MODE_WIDER_MODE (mr))
 	  if (GET_MODE_CLASS (mr) != mclass
 	      || GET_MODE_SIZE (mr) != size
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 22d8ac9..7dad259 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2719,7 +2719,7 @@ lto_write_mode_table (void)
   for (int i = 0; i < (int) MAX_MACHINE_MODE; i++)
     if (streamer_mode_table[i])
       {
-	machine_mode m = (machine_mode) i;
+	machine_mode m = (machine_mode_enum) i;
 	machine_mode inner_m = GET_MODE_INNER (m);
 	if (inner_m != m)
 	  streamer_mode_table[(int) inner_m] = 1;
@@ -2730,7 +2730,7 @@ lto_write_mode_table (void)
     for (int i = 0; i < (int) MAX_MACHINE_MODE; i++)
       if (streamer_mode_table[i] && i != (int) VOIDmode && i != (int) BLKmode)
 	{
-	  machine_mode m = (machine_mode) i;
+	  machine_mode m = (machine_mode_enum) i;
 	  if ((GET_MODE_INNER (m) == m) ^ (pass == 0))
 	    continue;
 	  bp_pack_value (&bp, m, 8);
diff --git a/gcc/machmode.h b/gcc/machmode.h
index ac2e72c..83878d6 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -20,6 +20,15 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef HAVE_MACHINE_MODES
 #define HAVE_MACHINE_MODES
 
+extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
+extern const unsigned short mode_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_inner[NUM_MACHINE_MODES];
+extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
+extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
+extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_wider[NUM_MACHINE_MODES];
+extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
+
 /* Get the name of mode MODE as a string.  */
 
 extern const char * const mode_name[NUM_MACHINE_MODES];
@@ -174,22 +183,111 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
 #define POINTER_BOUNDS_MODE_P(MODE)      \
   (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
 
-/* Get the size in bytes and bits of an object of mode MODE.  */
+/* Represents a general machine mode (scalar or non-scalar).  */
+class machine_mode
+{
+public:
+  ALWAYS_INLINE machine_mode () {}
+  template<typename T>
+  ALWAYS_INLINE machine_mode (const T &m) : m_mode (m) {}
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
 
-extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
+protected:
+  machine_mode_enum m_mode;
+};
+
+/* Return the base GET_MODE_SIZE value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_bytes (machine_mode_enum mode)
+{
 #if GCC_VERSION >= 4001
-#define GET_MODE_SIZE(MODE) \
-  ((unsigned short) (__builtin_constant_p (MODE) \
-		     ? mode_size_inline (MODE) : mode_size[MODE]))
+  return __builtin_constant_p (mode) ?
+	 mode_size_inline (mode) : mode_size[mode];
 #else
-#define GET_MODE_SIZE(MODE)    ((unsigned short) mode_size[MODE])
+  return mode_size[mode];
 #endif
-#define GET_MODE_BITSIZE(MODE) \
-  ((unsigned short) (GET_MODE_SIZE (MODE) * BITS_PER_UNIT))
+}
+
+/* Return the base GET_MODE_BITSIZE value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_bits (machine_mode_enum mode)
+{
+  return mode_to_bytes (mode) * BITS_PER_UNIT;
+}
+
+/* Return the base GET_MODE_PRECISION value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_precision (machine_mode_enum mode)
+{
+  return mode_precision[mode];
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE.  */
+
+ALWAYS_INLINE machine_mode
+mode_to_inner (machine_mode_enum mode)
+{
+#if GCC_VERSION >= 4001
+  return (machine_mode_enum) (__builtin_constant_p (mode) ?
+			      mode_inner_inline (mode) : mode_inner[mode]);
+#else
+  return (machine_mode_enum) mode_inner[mode];
+#endif
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE.  */
+
+ALWAYS_INLINE unsigned char
+mode_to_unit_size (machine_mode_enum mode)
+{
+#if GCC_VERSION >= 4001
+  return (__builtin_constant_p (mode)
+	  ? mode_unit_size_inline (mode) : mode_unit_size[mode]);
+#else
+  return mode_unit_size[mode];
+#endif
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_unit_precision (machine_mode_enum mode)
+{
+#if GCC_VERSION >= 4001
+  return (__builtin_constant_p (mode)
+	  ? mode_unit_precision_inline (mode) : mode_unit_precision[mode]);
+#else
+  return mode_unit_precision[mode];
+#endif
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_nunits (machine_mode_enum mode)
+{
+#if GCC_VERSION >= 4001
+  return __builtin_constant_p (mode) ?
+         mode_nunits_inline (mode) : mode_nunits[mode];
+#else
+  return mode_nunits[mode];
+#endif
+}
+
+/* Get the size in bytes of an object of mode MODE.  */
+
+#define GET_MODE_SIZE(MODE) (mode_to_bytes (MODE))
+
+/* Get the size in bits of an object of mode MODE.  */
+
+#define GET_MODE_BITSIZE(MODE) (mode_to_bits (MODE))
 
 /* Get the number of value bits of an object of mode MODE.  */
-extern const unsigned short mode_precision[NUM_MACHINE_MODES];
-#define GET_MODE_PRECISION(MODE)  mode_precision[MODE]
+
+#define GET_MODE_PRECISION(MODE) (mode_to_precision (MODE))
 
 /* Get the number of integral bits of an object of mode MODE.  */
 extern CONST_MODE_IBIT unsigned char mode_ibit[NUM_MACHINE_MODES];
@@ -210,65 +308,39 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES];
    mode of the vector elements.  For complex modes it is the mode of the real
    and imaginary parts.  For other modes it is MODE itself.  */
 
-extern const unsigned char mode_inner[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_INNER(MODE) \
-  ((machine_mode) (__builtin_constant_p (MODE) \
-			? mode_inner_inline (MODE) : mode_inner[MODE]))
-#else
-#define GET_MODE_INNER(MODE) ((machine_mode) mode_inner[MODE])
-#endif
+#define GET_MODE_INNER(MODE) (mode_to_inner (MODE))
 
 /* Get the size in bytes or bits of the basic parts of an
    object of mode MODE.  */
 
-extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_UNIT_SIZE(MODE) \
-  ((unsigned char) (__builtin_constant_p (MODE) \
-		   ? mode_unit_size_inline (MODE) : mode_unit_size[MODE]))
-#else
-#define GET_MODE_UNIT_SIZE(MODE) mode_unit_size[MODE]
-#endif
+#define GET_MODE_UNIT_SIZE(MODE) mode_to_unit_size (MODE)
 
 #define GET_MODE_UNIT_BITSIZE(MODE) \
   ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))
 
-extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_UNIT_PRECISION(MODE) \
-  ((unsigned short) (__builtin_constant_p (MODE) \
-		    ? mode_unit_precision_inline (MODE)\
-		    : mode_unit_precision[MODE]))
-#else
-#define GET_MODE_UNIT_PRECISION(MODE) mode_unit_precision[MODE]
-#endif
-
+#define GET_MODE_UNIT_PRECISION(MODE) (mode_to_unit_precision (MODE))
 
-/* Get the number of units in the object.  */
+/* Get the number of units in an object of mode MODE.  This is 2 for
+   complex modes and the number of elements for vector modes.  */
 
-extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_NUNITS(MODE) \
-  ((unsigned char) (__builtin_constant_p (MODE) \
-		    ? mode_nunits_inline (MODE) : mode_nunits[MODE]))
-#else
-#define GET_MODE_NUNITS(MODE)  mode_nunits[MODE]
-#endif
+#define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE))
 
 /* 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])
+#define GET_MODE_WIDER_MODE(MODE) \
+  (machine_mode ((machine_mode_enum) mode_wider[MODE]))
 
 /* 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])
+#define GET_MODE_2XWIDER_MODE(MODE) \
+  (machine_mode ((machine_mode_enum) mode_2xwider[MODE]))
 
 /* Get the complex mode from the component mode.  */
 extern const unsigned char mode_complex[NUM_MACHINE_MODES];
-#define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
+#define GET_MODE_COMPLEX_MODE(MODE) \
+  (machine_mode ((machine_mode_enum) mode_complex[MODE]))
 
 /* Return the mode for data of a given size SIZE and mode class CLASS.
    If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
@@ -337,7 +409,7 @@ extern unsigned get_mode_alignment (machine_mode);
 
 extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
 #define GET_CLASS_NARROWEST_MODE(CLASS) \
-  ((machine_mode) class_narrowest_mode[CLASS])
+  (machine_mode ((machine_mode_enum) class_narrowest_mode[CLASS]))
 
 /* 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.  */
@@ -360,7 +432,7 @@ extern void init_adjust_machine_modes (void);
 struct int_n_data_t {
   /* These parts are initailized by genmodes output */
   unsigned int bitsize;
-  machine_mode m;
+  machine_mode_enum m;
   /* RID_* is RID_INTN_BASE + index into this array */
 };
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 7bcaeee..54cc8b8 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5899,7 +5899,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
 
 	/* Determine position in reduction buffer, which may be used
 	   by target.  */
-	enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
+	machine_mode mode = TYPE_MODE (TREE_TYPE (var));
 	unsigned align = GET_MODE_ALIGNMENT (mode) /  BITS_PER_UNIT;
 	offset = (offset + align - 1) & ~(align - 1);
 	tree off = build_int_cst (sizetype, offset);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index bee1a21..9468c7c 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5140,7 +5140,7 @@ debug_optab_libfuncs (void)
   for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       {
-	rtx l = optab_libfunc ((optab) i, (machine_mode) j);
+	rtx l = optab_libfunc ((optab) i, (machine_mode_enum) j);
 	if (l)
 	  {
 	    gcc_assert (GET_CODE (l) == SYMBOL_REF);
@@ -5156,8 +5156,8 @@ debug_optab_libfuncs (void)
     for (j = 0; j < NUM_MACHINE_MODES; ++j)
       for (k = 0; k < NUM_MACHINE_MODES; ++k)
 	{
-	  rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j,
-					 (machine_mode) k);
+	  rtx l = convert_optab_libfunc ((optab) i, (machine_mode_enum) j,
+					 (machine_mode_enum) k);
 	  if (l)
 	    {
 	      gcc_assert (GET_CODE (l) == SYMBOL_REF);
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 9ab8cb1..24948bb 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -53,7 +53,7 @@ struct expand_operand {
 
   /* The mode passed to the convert_*_operand function.  It has a
      type-dependent meaning.  */
-  ENUM_BITFIELD (machine_mode) mode : 16;
+  machine_mode_enum mode : 16;
 
   /* The value of the operand.  */
   rtx value;
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index f74c875..288eb04 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -139,7 +139,7 @@ find_mode (const char *name)
 static void
 apply_mode_iterator (void *loc, int mode)
 {
-  PUT_MODE ((rtx) loc, (machine_mode) mode);
+  PUT_MODE ((rtx) loc, (machine_mode_enum) mode);
 }
 
 /* Implementations of the iterator_group callbacks for codes.  */
diff --git a/gcc/recog.h b/gcc/recog.h
index 9f6c42c..b4cb72c 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -331,7 +331,7 @@ struct insn_operand_data
 
   const char *const constraint;
 
-  ENUM_BITFIELD(machine_mode) const mode : 16;
+  machine_mode_enum const mode : 16;
 
   const char strict_low;
 
diff --git a/gcc/ree.c b/gcc/ree.c
index a7a6526..6d489b9 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -565,7 +565,7 @@ enum ext_modified_kind
 struct ATTRIBUTE_PACKED ext_modified
 {
   /* Mode from which ree has zero or sign extended the destination.  */
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
 
   /* Kind of modification of the insn.  */
   ENUM_BITFIELD(ext_modified_kind) kind : 2;
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 3171559..161bd84 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -471,11 +471,11 @@ init_reg_sets_1 (void)
       HARD_REG_SET ok_regs;
       CLEAR_HARD_REG_SET (ok_regs);
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-	if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (machine_mode) m))
+	if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (machine_mode_enum) m))
 	  SET_HARD_REG_BIT (ok_regs, j);
 
       for (i = 0; i < N_REG_CLASSES; i++)
-	if ((targetm.class_max_nregs ((reg_class_t) i, (machine_mode) m)
+	if ((targetm.class_max_nregs ((reg_class_t) i, (machine_mode_enum) m)
 	     <= reg_class_size[i])
 	    && hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
 	  {
@@ -498,7 +498,7 @@ init_reg_modes_target (void)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     for (j = 0; j < MAX_MACHINE_MODE; j++)
-      hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (machine_mode)j);
+      hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (machine_mode_enum) j);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -550,7 +550,7 @@ init_fake_stack_mems (void)
   int i;
 
   for (i = 0; i < MAX_MACHINE_MODE; i++)
-    top_of_stack[i] = gen_rtx_MEM ((machine_mode) i, stack_pointer_rtx);
+    top_of_stack[i] = gen_rtx_MEM ((machine_mode_enum) i, stack_pointer_rtx);
 }
 
 
@@ -664,7 +664,7 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
   /* Iterate over all of the CCmodes.  */
   for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
     {
-      mode = (machine_mode) m;
+      mode = (machine_mode_enum) m;
       if ((unsigned) hard_regno_nregs[regno][mode] == nregs
 	  && HARD_REGNO_MODE_OK (regno, mode)
 	  && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
diff --git a/gcc/reload1.c b/gcc/reload1.c
index b855268..3998e50 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -450,7 +450,7 @@ init_reload (void)
 
       for (int mode = 0; mode < MAX_MACHINE_MODE; mode++)
 	if (!double_reg_address_ok[mode]
-	    && memory_address_p ((enum machine_mode)mode, tem))
+	    && memory_address_p ((machine_mode_enum) mode, tem))
 	  double_reg_address_ok[mode] = 1;
     }
 
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 6f91fcb..5a77c4f 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -199,7 +199,7 @@ union rtunion
   const char *rt_str;
   rtx rt_rtx;
   rtvec rt_rtvec;
-  machine_mode rt_type;
+  machine_mode_enum rt_type;
   addr_diff_vec_flags rt_addr_diff_vec_flags;
   struct cselib_val *rt_cselib;
   tree rt_tree;
@@ -302,7 +302,7 @@ struct GTY((desc("0"), tag("0"),
   ENUM_BITFIELD(rtx_code) code: 16;
 
   /* The kind of value the expression has.  */
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
 
   /* 1 in a MEM if we should keep the alias set for this mem unchanged
      when we access a component.
@@ -698,7 +698,7 @@ class GTY(()) rtx_note : public rtx_insn
 #define GET_CODE(RTX)	    ((enum rtx_code) (RTX)->code)
 #define PUT_CODE(RTX, CODE) ((RTX)->code = (CODE))
 
-#define GET_MODE(RTX)		((machine_mode) (RTX)->mode)
+#define GET_MODE(RTX)		(machine_mode ((RTX)->mode))
 #define PUT_MODE_RAW(RTX, MODE)	((RTX)->mode = (MODE))
 
 /* RTL vector.  These appear inside RTX's when there is a need
@@ -1548,9 +1548,9 @@ enum reg_note
 };
 
 /* Define macros to extract and insert the reg-note kind in an EXPR_LIST.  */
-#define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
+#define REG_NOTE_KIND(LINK) ((enum reg_note) (LINK)->mode)
 #define PUT_REG_NOTE_KIND(LINK, KIND) \
-  PUT_MODE_RAW (LINK, (machine_mode) (KIND))
+  PUT_MODE_RAW (LINK, (machine_mode_enum) KIND)
 
 /* Names for REG_NOTE's in EXPR_LIST insn's.  */
 
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 60550ad..8699d33 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -2291,7 +2291,7 @@ void
 add_int_reg_note (rtx_insn *insn, enum reg_note kind, int datum)
 {
   gcc_checking_assert (int_reg_note_p (kind));
-  REG_NOTES (insn) = gen_rtx_INT_LIST ((machine_mode) kind,
+  REG_NOTES (insn) = gen_rtx_INT_LIST ((machine_mode_enum) kind,
 				       datum, REG_NOTES (insn));
 }
 
@@ -2313,7 +2313,8 @@ duplicate_reg_note (rtx note)
   reg_note kind = REG_NOTE_KIND (note);
 
   if (GET_CODE (note) == INT_LIST)
-    return gen_rtx_INT_LIST ((machine_mode) kind, XINT (note, 0), NULL_RTX);
+    return gen_rtx_INT_LIST ((machine_mode_enum) kind,
+			     XINT (note, 0), NULL_RTX);
   else if (GET_CODE (note) == EXPR_LIST)
     return alloc_reg_note (kind, copy_insn_1 (XEXP (note, 0)), NULL_RTX);
   else
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 165af23..0251bd4 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -5119,7 +5119,9 @@ simplify_const_relational_operation (enum rtx_code code,
       /* It would be nice if we really had a mode here.  However, the
 	 largest int representable on the target is as good as
 	 infinite.  */
-      machine_mode cmode = (mode == VOIDmode) ? MAX_MODE_INT : mode;
+      machine_mode cmode = mode;
+      if (cmode == VOIDmode)
+	cmode = MAX_MODE_INT;
       rtx_mode_t ptrueop0 = rtx_mode_t (trueop0, cmode);
       rtx_mode_t ptrueop1 = rtx_mode_t (trueop1, cmode);
 
@@ -6198,7 +6200,7 @@ simplify_subreg (machine_mode outermode, rtx op,
       unsigned int part_size, final_offset;
       rtx part, res;
 
-      enum machine_mode part_mode = GET_MODE (XEXP (op, 0));
+      machine_mode part_mode = GET_MODE (XEXP (op, 0));
       if (part_mode == VOIDmode)
 	part_mode = GET_MODE_INNER (GET_MODE (op));
       part_size = GET_MODE_SIZE (part_mode);
diff --git a/gcc/system.h b/gcc/system.h
index cf86235..848669d 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -744,6 +744,12 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 #define gcc_checking_assert(EXPR) ((void)(0 && (EXPR)))
 #endif
 
+#if GCC_VERSION >= 4000
+#define ALWAYS_INLINE inline __attribute__ ((always_inline))
+#else
+#define ALWAYS_INLINE inline
+#endif
+
 /* Use gcc_unreachable() to mark unreachable locations (like an
    unreachable default case of a switch.  Do not use gcc_assert(0).  */
 #if (GCC_VERSION >= 4005) && !ENABLE_ASSERT_CHECKING
diff --git a/gcc/target.def b/gcc/target.def
index ac3470e..3574ea8 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2360,7 +2360,7 @@ DEFHOOK
 DEFHOOK
 (chkp_bound_mode,
  "Return mode to be used for bounds.",
- enum machine_mode, (void),
+ machine_mode, (void),
  default_chkp_bound_mode)
 
 DEFHOOK
@@ -4351,7 +4351,7 @@ DEFHOOK
  "Use it to store bounds for anonymous register arguments stored\n\
 into the stack.  Arguments meaning is similar to\n\
 @code{TARGET_SETUP_INCOMING_VARARGS}.",
- void, (cumulative_args_t args_so_far, enum machine_mode mode, tree type,
+ void, (cumulative_args_t args_so_far, machine_mode mode, tree type,
 	int *pretend_args_size, int second_time),
  default_setup_incoming_vararg_bounds)
 
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 0991409..6178096 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2016,7 +2016,7 @@ default_chkp_bound_type (void)
   return res;
 }
 
-enum machine_mode
+machine_mode
 default_chkp_bound_mode (void)
 {
   return VOIDmode;
@@ -2054,7 +2054,7 @@ default_chkp_initialize_bounds (tree var ATTRIBUTE_UNUSED,
 
 void
 default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE_UNUSED,
-				      enum machine_mode mode ATTRIBUTE_UNUSED,
+				      machine_mode mode ATTRIBUTE_UNUSED,
 				      tree type ATTRIBUTE_UNUSED,
 				      int *pretend_arg_size ATTRIBUTE_UNUSED,
 				      int second_time ATTRIBUTE_UNUSED)
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 3a9271f..933b70c 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -243,14 +243,14 @@ extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx);
 extern rtx default_load_returned_bounds (rtx);
 extern void default_store_returned_bounds (rtx,rtx);
 extern tree default_chkp_bound_type (void);
-extern enum machine_mode default_chkp_bound_mode (void);
+extern machine_mode default_chkp_bound_mode (void);
 extern tree default_builtin_chkp_function (unsigned int);
 extern rtx default_chkp_function_value_bounds (const_tree, const_tree, bool);
 extern tree default_chkp_make_bounds_constant (HOST_WIDE_INT lb, HOST_WIDE_INT ub);
 extern int default_chkp_initialize_bounds (tree var, tree lb, tree ub,
 					   tree *stmts);
 extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE_UNUSED,
-						  enum machine_mode mode ATTRIBUTE_UNUSED,
+						  machine_mode mode ATTRIBUTE_UNUSED,
 						  tree type ATTRIBUTE_UNUSED,
 						  int *pretend_arg_size ATTRIBUTE_UNUSED,
 						  int second_time ATTRIBUTE_UNUSED);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index eec2d4f3..4ebe1ba 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1488,7 +1488,7 @@ struct GTY(()) tree_type_common {
   unsigned restrict_flag : 1;
   unsigned contains_placeholder_bits : 2;
 
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
 
   unsigned string_flag : 1;
   unsigned lang_flag_0 : 1;
@@ -1564,7 +1564,7 @@ struct GTY(()) tree_decl_common {
   struct tree_decl_minimal common;
   tree size;
 
-  ENUM_BITFIELD(machine_mode) mode : 8;
+  machine_mode_enum mode : 8;
 
   unsigned nonlocal_flag : 1;
   unsigned virtual_flag : 1;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 4a47254..687d9ef 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3842,7 +3842,7 @@ static bool
 divmod_candidate_p (gassign *stmt)
 {
   tree type = TREE_TYPE (gimple_assign_lhs (stmt));
-  enum machine_mode mode = TYPE_MODE (type);
+  machine_mode mode = TYPE_MODE (type);
   optab divmod_optab, div_optab;
 
   if (TYPE_UNSIGNED (type))
diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h
index 1daf259..989674d 100644
--- a/gcc/tree-streamer.h
+++ b/gcc/tree-streamer.h
@@ -107,18 +107,19 @@ streamer_tree_cache_get_hash (struct streamer_tree_cache_d *cache, unsigned ix)
 }
 
 static inline void
-bp_pack_machine_mode (struct bitpack_d *bp, machine_mode mode)
+bp_pack_machine_mode (struct bitpack_d *bp, machine_mode_enum mode)
 {
   streamer_mode_table[mode] = 1;
-  bp_pack_enum (bp, machine_mode, 1 << 8, mode);
+  bp_pack_enum (bp, machine_mode_enum, 1 << 8, mode);
 }
 
-static inline machine_mode
+static inline machine_mode_enum
 bp_unpack_machine_mode (struct bitpack_d *bp)
 {
-  return (machine_mode)
+  return (machine_mode_enum)
 	   ((struct lto_input_block *)
-	    bp->stream)->mode_table[bp_unpack_enum (bp, machine_mode, 1 << 8)];
+	    bp->stream)->mode_table[bp_unpack_enum (bp, machine_mode_enum,
+						    1 << 8)];
 }
 
 #endif  /* GCC_TREE_STREAMER_H  */
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 6e8b89c..4280914 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -3566,7 +3566,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo,
 /* Writes into SEL a mask for a vec_perm, equivalent to a vec_shr by OFFSET
    vector elements (not bits) for a vector of mode MODE.  */
 static void
-calc_vec_perm_mask_for_shift (enum machine_mode mode, unsigned int offset,
+calc_vec_perm_mask_for_shift (machine_mode mode, unsigned int offset,
 			      unsigned char *sel)
 {
   unsigned int i, nelt = GET_MODE_NUNITS (mode);
@@ -3579,7 +3579,7 @@ calc_vec_perm_mask_for_shift (enum machine_mode mode, unsigned int offset,
    MODE.  This is the case if _either_ the platform handles vec_shr_optab, _or_
    it supports vec_perm_const with masks for all necessary shift amounts.  */
 static bool
-have_whole_vector_shift (enum machine_mode mode)
+have_whole_vector_shift (machine_mode mode)
 {
   if (optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
     return true;
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index b0b131d..4618dd3 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6992,9 +6992,9 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
 		 to a larger load.  */
 	      unsigned lsize
 		= group_size * TYPE_PRECISION (TREE_TYPE (vectype));
-	      enum machine_mode elmode = mode_for_size (lsize, MODE_INT, 0);
-	      enum machine_mode vmode = mode_for_vector (elmode,
-							 nunits / group_size);
+	      machine_mode elmode = mode_for_size (lsize, MODE_INT, 0);
+	      machine_mode vmode = mode_for_vector (elmode,
+						    nunits / group_size);
 	      /* If we can't construct such a vector fall back to
 		 element loads of the original vector type.  */
 	      if (VECTOR_MODE_P (vmode)
diff --git a/gcc/tree.c b/gcc/tree.c
index 0f0e675..da295ab 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10836,7 +10836,7 @@ build_common_builtin_nodes (void)
 	if (targetm.libfunc_gnu_prefix)
 	  prefix = "__gnu_";
 
-	type = lang_hooks.types.type_for_mode ((machine_mode) mode, 0);
+	type = lang_hooks.types.type_for_mode ((machine_mode_enum) mode, 0);
 	if (type == NULL)
 	  continue;
 	inner_type = TREE_TYPE (type);
diff --git a/gcc/tree.h b/gcc/tree.h
index 62cd7bb..f432546 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1826,8 +1826,9 @@ extern void protected_set_expr_location (tree, location_t);
 
 #define TYPE_MODE_RAW(NODE) (TYPE_CHECK (NODE)->type_common.mode)
 #define TYPE_MODE(NODE) \
-  (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
-   ? vector_type_mode (NODE) : (NODE)->type_common.mode)
+   ((const machine_mode &) \
+    (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
+     ? vector_type_mode (NODE) : machine_mode ((NODE)->type_common.mode)))
 #define SET_TYPE_MODE(NODE, MODE) \
   (TYPE_CHECK (NODE)->type_common.mode = (MODE))
 
@@ -2349,7 +2350,9 @@ extern machine_mode element_mode (const_tree t);
 /* Holds the machine mode corresponding to the declaration of a variable or
    field.  Always equal to TYPE_MODE (TREE_TYPE (decl)) except for a
    FIELD_DECL.  */
-#define DECL_MODE(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.mode)
+#define DECL_MODE(NODE) \
+  ((const machine_mode &) \
+   machine_mode (DECL_COMMON_CHECK (NODE)->decl_common.mode))
 #define SET_DECL_MODE(NODE, MODE) \
   (DECL_COMMON_CHECK (NODE)->decl_common.mode = (MODE))
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [3/67] Add GDB pretty printer for machine mode classes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
  2016-12-09 12:50 ` [1/67] Add an E_ prefix to mode names and update case statements Richard Sandiford
  2016-12-09 12:52 ` [2/67] Make machine_mode a class Richard Sandiford
@ 2016-12-09 12:53 ` Richard Sandiford
  2016-12-09 12:54 ` [4/67] Add FOR_EACH iterators for modes Richard Sandiford
                   ` (66 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:53 UTC (permalink / raw)
  To: gcc-patches

This patch adds gdb hooks for printing machine_modes in the
natural way.

gcc/
	* gdbhooks.py (MachineModePrinter): New class.
	(build_pretty_printer): Use it for machine_modes.

diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 1212312..95f4b95 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -422,6 +422,16 @@ class VecPrinter:
 
 ######################################################################
 
+class MachineModePrinter:
+    def __init__(self, gdbval):
+        self.gdbval = gdbval
+
+    def to_string (self):
+	name = str(self.gdbval['m_mode'])
+	return name[2:] if name.startswith('E_') else name
+
+######################################################################
+
 # TODO:
 #   * hashtab
 #   * location_t
@@ -518,6 +528,9 @@ def build_pretty_printer():
                              'vec',
                              VecPrinter)
 
+    pp.add_printer_for_types(['machine_mode'],
+			     'machine_mode', MachineModePrinter)
+
     return pp
 
 gdb.printing.register_pretty_printer(

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [4/67] Add FOR_EACH iterators for modes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (2 preceding siblings ...)
  2016-12-09 12:53 ` [3/67] Add GDB pretty printer for machine mode classes Richard Sandiford
@ 2016-12-09 12:54 ` Richard Sandiford
  2016-12-09 12:55 ` [6/67] Make GET_MODE_WIDER return an opt_mode Richard Sandiford
                   ` (65 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:54 UTC (permalink / raw)
  To: gcc-patches

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.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

	* machmode.h (machine_mode::from_int): New function.
	(get_narrowest_mode): Likewise.
	(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/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

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

gcc/c-family/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

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

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index cef4b3a..4bb22ed 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -1280,8 +1280,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);
 
@@ -1295,8 +1294,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);
 
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b58056c..1f942b3 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -2766,7 +2766,7 @@ expand_builtin_strlen (tree exp, rtx target,
       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;
 
@@ -2794,13 +2794,11 @@ expand_builtin_strlen (tree exp, rtx target,
 	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;
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 51253ce..cb04536 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2119,13 +2119,14 @@ tree
 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;
 
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 418f601..0d6f538 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1184,9 +1184,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
diff --git a/gcc/combine.c b/gcc/combine.c
index 4d9cd09..8b08b14 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -11792,9 +11792,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	    }
 
 	  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);
@@ -12667,75 +12665,81 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
   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.  */
+    FOR_EACH_WIDER_MODE (tmode, mode)
+      {
+	if (!HWI_COMPUTABLE_MODE_P (tmode))
+	  break;
+	if (have_insn_for (COMPARE, tmode))
+	  {
+	    int zero_extended;
 
-	  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 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 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))
+	    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))
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8d4c1db..616b514 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -8610,7 +8610,7 @@ type_natural_mode (const_tree type, const CUMULATIVE_ARGS *cum,
 	    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)
 	      {
diff --git a/gcc/cse.c b/gcc/cse.c
index 2567765..eda6177 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -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);
diff --git a/gcc/dse.c b/gcc/dse.c
index a7ae022..ef7a5c8 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -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.  */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index f0243c7..3bcafbb 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5842,9 +5842,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)
@@ -5926,23 +5925,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;
@@ -5953,52 +5946,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_enum) ((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;
@@ -6007,9 +5988,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;
@@ -6018,9 +5997,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;
@@ -6040,9 +6017,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;
@@ -6062,31 +6037,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);
@@ -6100,9 +6067,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);
diff --git a/gcc/explow.c b/gcc/explow.c
index 6758cca..65b78ab 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -1917,9 +1917,7 @@ hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
 	 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)
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 92c895c..9a0aa7e 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -204,8 +204,7 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
 
   if (SCALAR_INT_MODE_P (mode))
     {
-      for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;
-	   mode_from = (machine_mode_enum) (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)
@@ -1580,7 +1579,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       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))
@@ -2019,8 +2018,7 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
 
   /* 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);
@@ -4084,15 +4082,13 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
   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;
@@ -5494,8 +5490,7 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
     }
 
   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);
diff --git a/gcc/expr.c b/gcc/expr.c
index 923d258..1bcf6c6 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -175,12 +175,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;
 
@@ -547,8 +545,7 @@ convert_move (rtx to, rtx from, int unsignedp)
 	  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)
@@ -700,12 +697,14 @@ alignment_for_piecewise_move (unsigned int max_pieces, unsigned int align)
     {
       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));
     }
@@ -721,8 +720,7 @@ widest_int_mode_for_size (unsigned int size)
 {
   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;
 
@@ -1725,8 +1723,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
      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);
 
@@ -2783,9 +2780,7 @@ copy_blkmode_to_reg (machine_mode mode, tree src)
     {
       /* 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;
@@ -3041,8 +3036,7 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
 	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);
 
@@ -3781,9 +3775,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;
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 83878d6..be389a2 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -192,10 +192,19 @@ public:
   ALWAYS_INLINE machine_mode (const T &m) : m_mode (m) {}
   ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
 
+  static ALWAYS_INLINE bool includes_p (machine_mode_enum) { return true; }
+  static machine_mode from_int (int i);
+
 protected:
   machine_mode_enum m_mode;
 };
 
+ALWAYS_INLINE machine_mode
+machine_mode::from_int (int i)
+{
+  return (machine_mode_enum) i;
+}
+
 /* Return the base GET_MODE_SIZE value for MODE.  */
 
 ALWAYS_INLINE unsigned short
@@ -411,6 +420,15 @@ extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
 #define GET_CLASS_NARROWEST_MODE(CLASS) \
   (machine_mode ((machine_mode_enum) class_narrowest_mode[CLASS]))
 
+/* Return the narrowest mode in T's class.  */
+
+template<typename T>
+inline T
+get_narrowest_mode (T mode)
+{
+  return 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.  */
 
@@ -441,4 +459,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 */
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 54cc8b8..3041a67 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4307,9 +4307,7 @@ omp_clause_aligned_alignment (tree clause)
   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])
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index 7cff5cc..b60362a 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -194,21 +194,20 @@ get_best_extraction_insn (extraction_insn *insn,
 			  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;
 }
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 9468c7c..6c859b2 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1249,9 +1249,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   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
@@ -1792,9 +1790,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   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
@@ -1950,9 +1946,7 @@ expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
 
   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)
 	    {
@@ -2033,9 +2027,7 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
 
   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)
 	    {
@@ -2137,9 +2129,7 @@ widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab)
   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)
 	    {
@@ -2309,9 +2299,7 @@ widen_bswap (machine_mode mode, rtx op0, rtx target)
   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;
@@ -2373,8 +2361,7 @@ expand_parity (machine_mode mode, rtx op0, rtx target)
   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)
 	    {
@@ -2826,9 +2813,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
     }
 
   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)
 	  {
@@ -2995,9 +2980,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 
   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))
@@ -3797,9 +3780,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
       /* 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)
@@ -3861,9 +3842,8 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
   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
@@ -3887,9 +3867,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 
       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;
@@ -4071,9 +4049,7 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
   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)))
@@ -4626,10 +4602,8 @@ expand_float (rtx to, rtx from, int unsignedp)
      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;
 
@@ -4676,8 +4650,7 @@ expand_float (rtx to, rtx from, int unsignedp)
 	 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;
@@ -4824,10 +4797,8 @@ expand_fix (rtx to, rtx from, int unsignedp)
      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;
 
@@ -4887,8 +4858,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
      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))))
@@ -5089,10 +5059,8 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab)
      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)
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 539ad33..052b52a 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1765,10 +1765,7 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
       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))
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 4e86fa9..d2732a0 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -3237,13 +3237,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);
     }
 
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 161bd84..c4cf711 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -622,36 +622,28 @@ choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
      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))
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 8699d33..a1070fb 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5605,10 +5605,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;
 
@@ -5619,7 +5617,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);
 
diff --git a/gcc/stmt.c b/gcc/stmt.c
index f1bf6e4..c8cb694 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -866,8 +866,7 @@ emit_case_decision_tree (tree index_expr, tree index_type,
     {
       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);
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 5a4bcf1..954e046 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -306,8 +306,7 @@ mode_for_size (unsigned int size, enum mode_class mclass, int limit)
     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 size, enum mode_class mclass)
 
   /* 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, unsigned nunits)
 
   /* 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;
@@ -1885,8 +1883,7 @@ finish_bitfield_representative (tree repr, tree field)
   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
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 687d9ef..b3edcc0 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3824,9 +3824,8 @@ target_supports_divmod_p (optab divmod_optab, optab div_optab, machine_mode mode
     {
       /* 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;
 
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index b0b37c7..91c5f93 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -1114,7 +1114,7 @@ type_for_widest_vector_mode (tree type, optab op)
   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)
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 4618dd3..787ecea 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4213,12 +4213,12 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
 	      <= 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);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 89788f1..74101d2 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -6305,13 +6305,14 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
 	    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);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [5/67] Small tweak to array_value_type
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (4 preceding siblings ...)
  2016-12-09 12:55 ` [6/67] Make GET_MODE_WIDER return an opt_mode Richard Sandiford
@ 2016-12-09 12:55 ` Richard Sandiford
  2016-12-09 12:57 ` [8/67] Simplify gen_trunc/extend_conv_libfunc Richard Sandiford
                   ` (63 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:55 UTC (permalink / raw)
  To: gcc-patches

Store the type mode in a variable so that a later,
more mechanical patch can change its type.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* tree-switch-conversion.c (array_value_type): Only read TYPE_MODE
	once.  Use get_narrowest_mode instead of GET_CLASS_NARROWEST_MODE.

diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index b063c46..8b64f4b 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -945,15 +945,15 @@ array_value_type (gswitch *swtch, tree type, int num,
 {
   unsigned int i, len = vec_safe_length (info->constructors[num]);
   constructor_elt *elt;
-  machine_mode mode;
   int sign = 0;
   tree smaller_type;
 
   if (!INTEGRAL_TYPE_P (type))
     return type;
 
-  mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (TYPE_MODE (type)));
-  if (GET_MODE_SIZE (TYPE_MODE (type)) <= GET_MODE_SIZE (mode))
+  machine_mode type_mode = TYPE_MODE (type);
+  machine_mode mode = get_narrowest_mode (type_mode);
+  if (GET_MODE_SIZE (type_mode) <= GET_MODE_SIZE (mode))
     return type;
 
   if (len < (optimize_bb_for_size_p (gimple_bb (swtch)) ? 2 : 32))
@@ -991,7 +991,7 @@ array_value_type (gswitch *swtch, tree type, int num,
 
 	  mode = GET_MODE_WIDER_MODE (mode);
 	  if (mode == VOIDmode
-	      || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (TYPE_MODE (type)))
+	      || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (type_mode))
 	    return type;
 	}
     }

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [6/67] Make GET_MODE_WIDER return an opt_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (3 preceding siblings ...)
  2016-12-09 12:54 ` [4/67] Add FOR_EACH iterators for modes Richard Sandiford
@ 2016-12-09 12:55 ` Richard Sandiford
  2016-12-09 12:55 ` [5/67] Small tweak to array_value_type Richard Sandiford
                   ` (64 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:55 UTC (permalink / raw)
  To: gcc-patches

GET_MODE_WIDER previously returned VOIDmode if no wider
mode exists.  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.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* 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): Likewise GET_MODE_2XWIDER_MODE.
	* config/ia64/ia64.c (expand_vselect_vconcat): Check whether
	a 2x wider mode exists.
	* 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_WIDER_MODE.
	* tree-ssa-math-opts.c (convert_mult_to_widen): Likewise.
	(convert_plusminus_to_widen): Likewise.
	* omp-low.c (omp_clause_aligned_alignment): 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.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/decl.c (validate_size): Update use of
	GET_MODE_WIDER_MODE, forcing a wider mode to exist.

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 18ec63d..d3bee34 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -8528,7 +8528,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
     {
       machine_mode p_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
       while (!targetm.valid_pointer_mode (p_mode))
-	p_mode = GET_MODE_WIDER_MODE (p_mode);
+	p_mode = *GET_MODE_WIDER_MODE (p_mode);
       type_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
     }
 
diff --git a/gcc/combine.c b/gcc/combine.c
index 8b08b14..e8e0b3f 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7592,10 +7592,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
       wanted_inner_mode = smallest_mode_for_size (len, MODE_INT);
       while (pos % GET_MODE_BITSIZE (wanted_inner_mode) + len
 	     > GET_MODE_BITSIZE (wanted_inner_mode))
-	{
-	  wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode);
-	  gcc_assert (wanted_inner_mode != VOIDmode);
-	}
+	wanted_inner_mode = *GET_MODE_WIDER_MODE (wanted_inner_mode);
     }
 
   orig_pos = pos;
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index fcb5b01..7e059b2 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -6063,7 +6063,7 @@ c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
       /* Recognize a mult_highpart operation.  */
       if ((mode == HImode || mode == SImode)
 	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT
-	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode)
+	  && GET_MODE (XEXP (x, 0)) == *GET_MODE_2XWIDER_MODE (mode)
 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
 	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode))
diff --git a/gcc/config/cr16/cr16.h b/gcc/config/cr16/cr16.h
index 2d08c2b..2dcad94 100644
--- a/gcc/config/cr16/cr16.h
+++ b/gcc/config/cr16/cr16.h
@@ -197,9 +197,7 @@ while (0)
 
 /* Returns 1 if the register is longer than word size, 0 otherwise.  */
 #define LONG_REG_P(REGNO)                                                    \
-  (HARD_REGNO_NREGS (REGNO,                                                  \
-		     GET_MODE_WIDER_MODE (smallest_mode_for_size	     \
-					 (BITS_PER_WORD, MODE_INT))) == 1)
+  (HARD_REGNO_NREGS (REGNO, *GET_MODE_WIDER_MODE (word_mode)) == 1)
 
 #define HARD_REGNO_NREGS(REGNO, MODE)                                         \
  ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                        \
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 616b514..0c58dae 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -27440,6 +27440,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
   bool need_zero_guard = false;
   bool noalign;
   machine_mode move_mode = VOIDmode;
+  machine_mode wider_mode;
   int unroll_factor = 1;
   /* TODO: Once value ranges are available, fill in proper data.  */
   unsigned HOST_WIDE_INT min_size = 0;
@@ -27533,9 +27534,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
       unroll_factor = 4;
       /* Find the widest supported mode.  */
       move_mode = word_mode;
-      while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
-	     != CODE_FOR_nothing)
-	  move_mode = GET_MODE_WIDER_MODE (move_mode);
+      while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode)
+	     && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing)
+	move_mode = wider_mode;
 
       /* Find the corresponding vector mode with the same size as MOVE_MODE.
 	 MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
@@ -42354,7 +42355,7 @@ static inline machine_mode
 get_mode_wider_vector (machine_mode o)
 {
   /* ??? Rely on the ordering that genmodes.c gives to vectors.  */
-  machine_mode n = GET_MODE_WIDER_MODE (o);
+  machine_mode n = *GET_MODE_WIDER_MODE (o);
   gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2);
   gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n));
   return n;
@@ -45616,7 +45617,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   if (vselect_insn == NULL_RTX)
     init_vselect_insn ();
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
   PUT_MODE (x, v2mode);
   XEXP (x, 0) = op0;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 21953d1..d43edc8 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -11297,7 +11297,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   machine_mode v2mode;
   rtx x;
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   return expand_vselect (target, x, perm, nelt);
 }
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 7eca000..6c08aed 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -21079,7 +21079,8 @@ mips_expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   machine_mode v2mode;
   rtx x;
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   return mips_expand_vselect (target, x, perm, nelt);
 }
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index f26c1a0..9f81995 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -56,6 +56,7 @@ struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
 class machine_mode;
+template<typename> class opt_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
    hierarchy, along with the relevant invariant.
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 9a0aa7e..737588b 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -206,11 +206,10 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
     {
       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);
@@ -3578,7 +3577,7 @@ extract_high_half (machine_mode mode, rtx op)
 
   gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
 
-  wider_mode = GET_MODE_WIDER_MODE (mode);
+  wider_mode = *GET_MODE_WIDER_MODE (mode);
   op = expand_shift (RSHIFT_EXPR, wider_mode, op,
 		     GET_MODE_BITSIZE (mode), 0, 1);
   return convert_modes (mode, wider_mode, op, 0);
@@ -3600,7 +3599,7 @@ expmed_mult_highpart_optab (machine_mode mode, rtx op0, rtx op1,
 
   gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
 
-  wider_mode = GET_MODE_WIDER_MODE (mode);
+  wider_mode = *GET_MODE_WIDER_MODE (mode);
   size = GET_MODE_BITSIZE (mode);
 
   /* Firstly, try using a multiplication insn that only generates the needed
@@ -3706,7 +3705,7 @@ static rtx
 expmed_mult_highpart (machine_mode mode, rtx op0, rtx op1,
 		      rtx target, int unsignedp, int max_cost)
 {
-  machine_mode wider_mode = GET_MODE_WIDER_MODE (mode);
+  machine_mode wider_mode = *GET_MODE_WIDER_MODE (mode);
   unsigned HOST_WIDE_INT cnst1;
   int extra_cost;
   bool sign_adjust = false;
diff --git a/gcc/expr.c b/gcc/expr.c
index 1bcf6c6..a3a3e86 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9090,7 +9090,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	    && target
 	    && REG_P (target)
 	    && ! unsignedp
-	    && mode == GET_MODE_WIDER_MODE (word_mode)
+	    && mode == GET_MODE_WIDER_MODE (word_mode).else_void ()
 	    && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode)
 	    && TREE_CONSTANT (treeop1)
 	    && TREE_CODE (treeop0) == SSA_NAME)
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 0d91b8e..3dbd2a1 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -1468,14 +1468,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
       struct separate_ops ops;
       int prec = GET_MODE_PRECISION (mode);
       machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
+      machine_mode wmode;
       ops.op0 = make_tree (type, op0);
       ops.op1 = make_tree (type, op1);
       ops.op2 = NULL_TREE;
       ops.location = loc;
-      if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
-	  && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
+      if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
+	  && targetm.scalar_mode_supported_p (wmode))
 	{
-	  machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
 	  ops.code = WIDEN_MULT_EXPR;
 	  ops.type
 	    = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index ca4582f..d378542 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -266,7 +266,7 @@ init_lower_subreg (void)
 
   memset (this_target_lower_subreg, 0, sizeof (*this_target_lower_subreg));
 
-  twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode);
+  twice_word_mode = *GET_MODE_2XWIDER_MODE (word_mode);
 
   rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
   rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 69d87e6..578b10f 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1555,7 +1555,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
 				    : GET_CLASS_NARROWEST_MODE (mclass);
 	     pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode;
 	     pass ? mr = (machine_mode_enum) (mr + 1)
-		  : mr = GET_MODE_WIDER_MODE (mr))
+		  : mr = GET_MODE_WIDER_MODE (mr).else_void ())
 	  if (GET_MODE_CLASS (mr) != mclass
 	      || GET_MODE_SIZE (mr) != size
 	      || GET_MODE_PRECISION (mr) != prec
diff --git a/gcc/machmode.h b/gcc/machmode.h
index be389a2..44a8ad4 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -183,6 +183,60 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
 #define POINTER_BOUNDS_MODE_P(MODE)      \
   (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
 
+/* An optional T (i.e. a T or nothing), where T is some form of mode class.
+   operator * gives the T value.  */
+template<typename T>
+class opt_mode
+{
+public:
+  ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
+  ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
+  machine_mode_enum else_void () const;
+  T operator * () const;
+
+  /* Return true if the object contains a T rather than nothing.  */
+  ALWAYS_INLINE bool exists () const { return m_mode != E_VOIDmode; }
+  template<typename U> bool exists (U *) const;
+
+private:
+  machine_mode_enum m_mode;
+};
+
+/* If the object contains a T, return its enum value, otherwise return
+   E_VOIDmode.  */
+
+template<typename T>
+ALWAYS_INLINE machine_mode_enum
+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 T::from_int (m_mode);
+}
+
+/* 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::from_int (m_mode);
+      return true;
+    }
+  return false;
+}
+
 /* Represents a general machine mode (scalar or non-scalar).  */
 class machine_mode
 {
@@ -336,15 +390,28 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES];
 
 /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI).  */
 
-extern const unsigned char mode_wider[NUM_MACHINE_MODES];
-#define GET_MODE_WIDER_MODE(MODE) \
-  (machine_mode ((machine_mode_enum) mode_wider[MODE]))
+template<typename T>
+ALWAYS_INLINE opt_mode<T>
+GET_MODE_WIDER_MODE (const T &m)
+{
+  machine_mode_enum wider = (machine_mode_enum) mode_wider[m];
+  if (wider != E_VOIDmode)
+    return T::from_int (wider);
+  return opt_mode<T> ();
+}
 
 /* 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 ((machine_mode_enum) mode_2xwider[MODE]))
+
+template<typename T>
+ALWAYS_INLINE opt_mode<T>
+GET_MODE_2XWIDER_MODE (const T &m)
+{
+  machine_mode_enum wider = (machine_mode_enum) mode_2xwider[m];
+  if (wider != E_VOIDmode)
+    return T::from_int (wider);
+  return opt_mode<T> ();
+}
 
 /* Get the complex mode from the component mode.  */
 extern const unsigned char mode_complex[NUM_MACHINE_MODES];
@@ -483,17 +550,17 @@ namespace mode_iterator
   inline void
   get_wider (machine_mode *iter)
   {
-    *iter = GET_MODE_WIDER_MODE (*iter);
+    *iter = GET_MODE_WIDER_MODE (*iter).else_void ();
   }
 
   /* Set mode iterator *ITER to the next widest mode in the same class.
      Such a mode is known to exist.  */
 
+  template<typename T>
   inline void
-  get_known_wider (machine_mode *iter)
+  get_known_wider (T *iter)
   {
-    *iter = GET_MODE_WIDER_MODE (*iter);
-    gcc_checking_assert (*iter != VOIDmode);
+    *iter = *GET_MODE_WIDER_MODE (*iter);
   }
 
   /* Set mode iterator *ITER to the mode that is two times wider than the
@@ -502,7 +569,7 @@ namespace mode_iterator
   inline void
   get_2xwider (machine_mode *iter)
   {
-    *iter = GET_MODE_2XWIDER_MODE (*iter);
+    *iter = GET_MODE_2XWIDER_MODE (*iter).else_void ();
   }
 }
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 3041a67..13f3435 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4314,8 +4314,8 @@ omp_clause_aligned_alignment (tree clause)
 	  continue;
 	while (vs
 	       && GET_MODE_SIZE (vmode) < vs
-	       && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
-	  vmode = GET_MODE_2XWIDER_MODE (vmode);
+	       && GET_MODE_2XWIDER_MODE (vmode).exists ())
+	  vmode = *GET_MODE_2XWIDER_MODE (vmode);
 	
 	tree type = lang_hooks.types.type_for_mode (mode, 1);
 	if (type == NULL_TREE || TYPE_MODE (type) != mode)
diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
index 79a07d6..9d9ffbd 100644
--- a/gcc/optabs-libfuncs.c
+++ b/gcc/optabs-libfuncs.c
@@ -918,9 +918,10 @@ init_sync_libfuncs_1 (optab tab, const char *base, int max)
   mode = QImode;
   for (i = 1; i <= max; i *= 2)
     {
+      if (i > 1)
+	mode = *GET_MODE_2XWIDER_MODE (mode);
       buf[len + 1] = '0' + i;
       set_optab_libfunc (tab, mode, buf);
-      mode = GET_MODE_2XWIDER_MODE (mode);
     }
 }
 
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index b60362a..fdde578 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -425,7 +425,7 @@ find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
   for (; (permit_non_widening || from_mode != to_mode)
 	 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
 	 && from_mode != VOIDmode;
-       from_mode = GET_MODE_WIDER_MODE (from_mode))
+       from_mode = GET_MODE_WIDER_MODE (from_mode).else_void ())
     {
       enum insn_code handler = widening_optab_handler (op, to_mode,
 						       from_mode);
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 6c859b2..5dab1b4 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1184,13 +1184,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
      takes operands of this mode and makes a wider mode.  */
 
   if (binoptab == smul_optab
-      && GET_MODE_2XWIDER_MODE (mode) != VOIDmode
-      && (widening_optab_handler ((unsignedp ? umul_widen_optab
-					     : smul_widen_optab),
-				  GET_MODE_2XWIDER_MODE (mode), mode)
-	  != CODE_FOR_nothing))
+      && GET_MODE_2XWIDER_MODE (mode).exists (&wider_mode)
+      && (convert_optab_handler ((unsignedp
+				  ? umul_widen_optab
+				  : smul_widen_optab),
+				 wider_mode, mode) != CODE_FOR_nothing))
     {
-      temp = expand_binop (GET_MODE_2XWIDER_MODE (mode),
+      temp = expand_binop (wider_mode,
 			   unsignedp ? umul_widen_optab : smul_widen_optab,
 			   op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
 
@@ -1251,14 +1251,14 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
     FOR_EACH_WIDER_MODE (wider_mode, mode)
       {
+	machine_mode next_mode;
 	if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
 	    || (binoptab == smul_optab
-		&& GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
+		&& GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode)
 		&& (find_widening_optab_handler ((unsignedp
 						  ? umul_widen_optab
 						  : smul_widen_optab),
-						 GET_MODE_WIDER_MODE (wider_mode),
-						 mode, 0)
+						 next_mode, mode, 0)
 		    != CODE_FOR_nothing)))
 	  {
 	    rtx xop0 = op0, xop1 = op1;
@@ -3699,7 +3699,7 @@ can_compare_p (enum rtx_code code, machine_mode mode,
 	  && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
 	return 1;
 
-      mode = GET_MODE_WIDER_MODE (mode);
+      mode = GET_MODE_WIDER_MODE (mode).else_void ();
       PUT_MODE (test, mode);
     }
   while (mode != VOIDmode);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index a1070fb..92b7580 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5613,13 +5613,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
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 954e046..834cf8b 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2709,7 +2709,8 @@ bit_field_mode_iterator
 bool
 bit_field_mode_iterator::next_mode (machine_mode *out_mode)
 {
-  for (; m_mode != VOIDmode; m_mode = GET_MODE_WIDER_MODE (m_mode))
+  for (; m_mode != VOIDmode;
+       m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ())
     {
       unsigned int unit = GET_MODE_BITSIZE (m_mode);
 
@@ -2746,7 +2747,7 @@ bit_field_mode_iterator::next_mode (machine_mode *out_mode)
 	break;
 
       *out_mode = m_mode;
-      m_mode = GET_MODE_WIDER_MODE (m_mode);
+      m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ();
       m_count++;
       return true;
     }
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index b3edcc0..e0883ff 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3160,8 +3160,8 @@ convert_mult_to_widen (gimple *stmt, gimple_stmt_iterator *gsi)
 	      || (TYPE_UNSIGNED (type2)
 		  && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
 	    {
-	      from_mode = GET_MODE_WIDER_MODE (from_mode);
-	      if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
+	      if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode)
+		  || GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
 		return false;
 	    }
 
@@ -3342,8 +3342,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple *stmt,
 	  || (from_unsigned2
 	      && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
 	{
-	  from_mode = GET_MODE_WIDER_MODE (from_mode);
-	  if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
+	  if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode)
+	      || GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
 	    return false;
 	}
 
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 8b64f4b..62c3a78 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -989,8 +989,7 @@ array_value_type (gswitch *swtch, tree type, int num,
 	  if (sign == 1)
 	    sign = 0;
 
-	  mode = GET_MODE_WIDER_MODE (mode);
-	  if (mode == VOIDmode
+	  if (!GET_MODE_WIDER_MODE (mode).exists (&mode)
 	      || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (type_mode))
 	    return type;
 	}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 600634d..f3322b6 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9995,7 +9995,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
   else
     {
       mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-      do
+      for (;;)
 	{
 	  /* If we cannot do a signed conversion to float from mode
 	     or if the value-range does not fit in the signed type
@@ -10004,15 +10004,12 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
 	      && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED))
 	    break;
 
-	  mode = GET_MODE_WIDER_MODE (mode);
 	  /* But do not widen the input.  Instead leave that to the
 	     optabs expansion code.  */
-	  if (GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1)))
+	  if (!GET_MODE_WIDER_MODE (mode).exists (&mode)
+	      || GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1)))
 	    return false;
 	}
-      while (mode != VOIDmode);
-      if (mode == VOIDmode)
-	return false;
     }
 
   /* It works, insert a truncation or sign-change before the
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 74101d2..cd29dc6 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -8705,12 +8705,11 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data)
       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
 
       /* Attempt to merge adjacent registers or memory.  */
-      wider_mode = GET_MODE_WIDER_MODE (mode);
       for (j = i + 1; j < var->n_var_parts; j++)
 	if (last_limit <= VAR_PART_OFFSET (var, j))
 	  break;
       if (j < var->n_var_parts
-	  && wider_mode != VOIDmode
+	  && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
 	  && var->var_part[j].cur_loc
 	  && mode == GET_MODE (var->var_part[j].cur_loc)
 	  && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [8/67] Simplify gen_trunc/extend_conv_libfunc
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (5 preceding siblings ...)
  2016-12-09 12:55 ` [5/67] Small tweak to array_value_type Richard Sandiford
@ 2016-12-09 12:57 ` Richard Sandiford
  2016-12-09 12:57 ` [7/67] Add scalar_float_mode Richard Sandiford
                   ` (62 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:57 UTC (permalink / raw)
  To: gcc-patches

Replace checks of:

  GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode)

with !is_a <scalar_float_mode> and use MODE_CLASS equality/inequality
instead of:

  (GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
  || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode))

and:

  (GET_MODE_CLASS (tmode) == MODE_FLOAT
   && GET_MODE_CLASS (fmode) == MODE_FLOAT)
  || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode))

gcc/
2016-11-30  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* optabs-libfuncs.c (gen_trunc_conv_libfunc): Use is_a
	 <scalar_float_mode>.  Simplify.
	(gen_extend_conv_libfunc): Likewise.

diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
index 9d9ffbd..75fd677 100644
--- a/gcc/optabs-libfuncs.c
+++ b/gcc/optabs-libfuncs.c
@@ -579,24 +579,20 @@ gen_trunc_conv_libfunc (convert_optab tab,
 			machine_mode tmode,
 			machine_mode fmode)
 {
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
-    return;
-  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
-    return;
-  if (tmode == fmode)
+  scalar_float_mode float_tmode, float_fmode;
+  if (!is_a <scalar_float_mode> (fmode, &float_fmode)
+      || !is_a <scalar_float_mode> (tmode, &float_tmode)
+      || float_tmode == float_fmode)
     return;
 
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
-      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
-     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+  if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
+    gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
 
-  if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
+  if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode))
     return;
 
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
-       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
-      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
-    gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
+  if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
+    gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
 }
 
 /* Pick proper libcall for extend_optab.  We need to chose if we do
@@ -608,23 +604,19 @@ gen_extend_conv_libfunc (convert_optab tab,
 			 machine_mode tmode,
 			 machine_mode fmode)
 {
-  if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
-    return;
-  if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
-    return;
-  if (tmode == fmode)
+  scalar_float_mode float_tmode, float_fmode;
+  if (!is_a <scalar_float_mode> (fmode, &float_fmode)
+      || !is_a <scalar_float_mode> (tmode, &float_tmode)
+      || float_tmode == float_fmode)
     return;
 
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
-      || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
-     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
+  if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
+    gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
 
-  if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
+  if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
     return;
 
-  if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
-       && GET_MODE_CLASS (fmode) == MODE_FLOAT)
-      || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
+  if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
 }
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [7/67] Add scalar_float_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (6 preceding siblings ...)
  2016-12-09 12:57 ` [8/67] Simplify gen_trunc/extend_conv_libfunc Richard Sandiford
@ 2016-12-09 12:57 ` Richard Sandiford
  2016-12-09 14:19   ` David Malcolm
  2016-12-09 12:58 ` [9/67] Add SCALAR_FLOAT_TYPE_MODE Richard Sandiford
                   ` (61 subsequent siblings)
  69 siblings, 1 reply; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:57 UTC (permalink / raw)
  To: gcc-patches

This patch adds a scalar_float_mode class, which wraps a mode enum
that is known to satisfy SCALAR_FLOAT_MODE_P.  Things like "SFmode"
now give a scalar_float_mode object instead of a machine_mode.
This in turn needs a change to the real.h format_helper, so that
it can accept both machine_modes and scalar_float_modes.

gcc/
2016-11-30  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* coretypes.h (scalar_float_mode): New type.
	* machmode.h (PROTECT_ENUM_CONVERSION): New macro.
	(is_a): New function.
	(as_a): Likewise.
	(dyn_cast): Likewise.
	(scalar_float_mode): New class.
	(scalar_float_mode::includes_p): New function.
	(scalar_float_mode::from_int): Likewise.
	* real.h (FLOAT_MODE_FORMAT): Use as_a <scalar_float_mode>.
	(format_helper::format_helper): Turn into a template.
	* genmodes.c (get_mode_class): New function.
	(emit_insn_modes_h): Give modes the class returned by get_mode_class,
	or machine_mode if none.
	* config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Use
	as_a <scalar_float_mode>.
	* dwarf2out.c (mem_loc_descriptor): Likewise.
	(insert_float): Likewise.
	(add_const_value_attribute): Likewise.
	* simplify-rtx.c (simplify_immed_subreg): Likewise.
	* optabs.c (expand_absneg_bit): Take a scalar_float_mode.
	(expand_unop): Update accordingly.
	(expand_abs_nojump): Likewise.
	(expand_copysign_absneg): Take a scalar_float_mode.
	(expand_copysign_bit): Likewise.
	(expand_copysign): Update accordingly.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/utils.c (gnat_type_for_mode): Use is_a
	<scalar_float_mode> instead of SCALAR_FLOAT_MODE_P.

diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 0ae381f..29e5203 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -3411,8 +3411,10 @@ gnat_type_for_mode (machine_mode mode, int unsignedp)
   if (COMPLEX_MODE_P (mode))
     return NULL_TREE;
 
-  if (SCALAR_FLOAT_MODE_P (mode))
-    return float_type_for_precision (GET_MODE_PRECISION (mode), mode);
+  scalar_float_mode float_mode;
+  if (is_a <scalar_float_mode> (mode, &float_mode))
+    return float_type_for_precision (GET_MODE_PRECISION (float_mode),
+				     float_mode);
 
   if (SCALAR_INT_MODE_P (mode))
     return gnat_type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 944577d..cc97b7a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -11035,8 +11035,12 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
 
       if (info)
 	{
-	  info->value = CONST_VECTOR_ELT (op, 0);
-	  info->element_width = GET_MODE_BITSIZE (GET_MODE (info->value));
+	  rtx elt = CONST_VECTOR_ELT (op, 0);
+	  scalar_float_mode elt_mode
+	    = as_a <scalar_float_mode> (GET_MODE (elt));
+
+	  info->value = elt;
+	  info->element_width = GET_MODE_BITSIZE (elt_mode);
 	  info->mvn = false;
 	  info->shift = 0;
 	}
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 9f81995..f4c1859 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -56,6 +56,7 @@ struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
 class machine_mode;
+class scalar_float_mode;
 template<typename> class opt_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 8dc8523..5130b64 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15121,7 +15121,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  else
 #endif
 	    {
-	      unsigned int length = GET_MODE_SIZE (mode);
+	      scalar_float_mode float_mode = as_a <scalar_float_mode> (mode);
+	      unsigned int length = GET_MODE_SIZE (float_mode);
 	      unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
 	      insert_float (rtl, array);
@@ -18343,11 +18344,12 @@ insert_float (const_rtx rtl, unsigned char *array)
 {
   long val[4];
   int i;
+  scalar_float_mode mode = as_a <scalar_float_mode> (GET_MODE (rtl));
 
-  real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), GET_MODE (rtl));
+  real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), mode);
 
   /* real_to_target puts 32-bit pieces in each long.  Pack them.  */
-  for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
+  for (i = 0; i < GET_MODE_SIZE (mode) / 4; i++)
     {
       insert_int (val[i], 4, array);
       array += 4;
@@ -18391,21 +18393,19 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
 	 floating-point constant.  A CONST_DOUBLE is used whenever the
 	 constant requires more than one word in order to be adequately
 	 represented.  */
-      {
-	machine_mode mode = GET_MODE (rtl);
-
-	if (TARGET_SUPPORTS_WIDE_INT == 0 && !SCALAR_FLOAT_MODE_P (mode))
-	  add_AT_double (die, DW_AT_const_value,
-			 CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
-	else
-	  {
-	    unsigned int length = GET_MODE_SIZE (mode);
-	    unsigned char *array = ggc_vec_alloc<unsigned char> (length);
+      if (TARGET_SUPPORTS_WIDE_INT == 0
+	  && !SCALAR_FLOAT_MODE_P (GET_MODE (rtl)))
+	add_AT_double (die, DW_AT_const_value,
+		       CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
+      else
+	{
+	  scalar_float_mode mode = as_a <scalar_float_mode> (GET_MODE (rtl));
+	  unsigned int length = GET_MODE_SIZE (mode);
+	  unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
-	    insert_float (rtl, array);
-	    add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
-	  }
-      }
+	  insert_float (rtl, array);
+	  add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
+	}
       return true;
 
     case CONST_VECTOR:
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 4dbced2..3cc426e 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1129,6 +1129,23 @@ mode_unit_precision_inline (machine_mode_enum mode)\n\
 }\n");
 }
 
+/* Return the best machine mode class for MODE, or null if machine_mode
+   should be used.  */
+
+static const char *
+get_mode_class (struct mode_data *mode)
+{
+  switch (mode->cl)
+    {
+    case MODE_FLOAT:
+    case MODE_DECIMAL_FLOAT:
+      return "scalar_float_mode";
+
+    default:
+      return NULL;
+    }
+}
+
 static void
 emit_insn_modes_h (void)
 {
@@ -1158,8 +1175,12 @@ enum machine_mode_enum\n{");
 	printf ("#ifdef USE_ENUM_MODES\n");
 	printf ("#define %smode E_%smode\n", m->name, m->name);
 	printf ("#else\n");
-	printf ("#define %smode (machine_mode (E_%smode))\n",
-		m->name, m->name);
+	if (const char *mode_class = get_mode_class (m))
+	  printf ("#define %smode (%s::from_int (E_%smode))\n",
+		  m->name, mode_class, m->name);
+	else
+	  printf ("#define %smode (machine_mode (E_%smode))\n",
+		  m->name, m->name);
 	printf ("#endif\n");
       }
 
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 44a8ad4..996f991 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -29,6 +29,16 @@ extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_wider[NUM_MACHINE_MODES];
 extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
 
+/* Allow direct conversion of enums to specific mode classes only
+   when USE_ENUM_MODES is defined.  This is only intended for use
+   by gencondmd, so that it can tell more easily when .md conditions
+   are always false.  */
+#ifdef USE_ENUM_MODES
+#define PROTECT_ENUM_CONVERSION public
+#else
+#define PROTECT_ENUM_CONVERSION protected
+#endif
+
 /* Get the name of mode MODE as a string.  */
 
 extern const char * const mode_name[NUM_MACHINE_MODES];
@@ -237,6 +247,85 @@ opt_mode<T>::exists (U *mode) const
   return false;
 }
 
+/* Return true if mode M has type T.  */
+
+template<typename T>
+inline bool
+is_a (machine_mode_enum m)
+{
+  return T::includes_p (m);
+}
+
+/* Assert that mode M has type T, and return it in that form.  */
+
+template<typename T>
+inline T
+as_a (machine_mode_enum m)
+{
+  gcc_checking_assert (T::includes_p (m));
+  return T::from_int (m);
+}
+
+/* Convert M to an opt_mode<T>.  */
+
+template<typename T>
+inline opt_mode<T>
+dyn_cast (machine_mode_enum m)
+{
+  if (T::includes_p (m))
+    return T::from_int (m);
+  return opt_mode<T> ();
+}
+
+/* Return true if mode M has type T, storing it as a T in *RESULT
+   if so.  */
+
+template<typename T, typename U>
+inline bool
+is_a (machine_mode_enum m, U *result)
+{
+  if (T::includes_p (m))
+    {
+      *result = T::from_int (m);
+      return true;
+    }
+  return false;
+}
+
+/* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P.  */
+class scalar_float_mode
+{
+public:
+  ALWAYS_INLINE scalar_float_mode () {}
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+
+  static bool includes_p (machine_mode_enum);
+  static scalar_float_mode from_int (int i);
+
+PROTECT_ENUM_CONVERSION:
+  ALWAYS_INLINE scalar_float_mode (machine_mode_enum m) : m_mode (m) {}
+
+protected:
+  machine_mode_enum m_mode;
+};
+
+/* Return true if M is a scalar_float_mode.  */
+
+inline bool
+scalar_float_mode::includes_p (machine_mode_enum m)
+{
+  return SCALAR_FLOAT_MODE_P (m);
+}
+
+/* Return M as a scalar_float_mode.  This function should only be used by
+   utility functions; general code should use as_a<T> instead.  */
+
+ALWAYS_INLINE scalar_float_mode
+scalar_float_mode::from_int (int i)
+{
+  return machine_mode_enum (i);
+}
+
 /* Represents a general machine mode (scalar or non-scalar).  */
 class machine_mode
 {
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 5dab1b4..58c26e4 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2550,7 +2550,7 @@ lowpart_subreg_maybe_copy (machine_mode omode, rtx val,
    logical operation on the sign bit.  */
 
 static rtx
-expand_absneg_bit (enum rtx_code code, machine_mode mode,
+expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
 		   rtx op0, rtx target)
 {
   const struct real_format *fmt;
@@ -2696,6 +2696,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
   machine_mode wider_mode;
+  scalar_float_mode float_mode;
   rtx temp;
   rtx libfunc;
 
@@ -2886,9 +2887,9 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
   if (optab_to_code (unoptab) == NEG)
     {
       /* Try negating floating point values by flipping the sign bit.  */
-      if (SCALAR_FLOAT_MODE_P (mode))
+      if (is_a <scalar_float_mode> (mode, &float_mode))
 	{
-	  temp = expand_absneg_bit (NEG, mode, op0, target);
+	  temp = expand_absneg_bit (NEG, float_mode, op0, target);
 	  if (temp)
 	    return temp;
 	}
@@ -3085,9 +3086,10 @@ expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
     return temp;
 
   /* For floating point modes, try clearing the sign bit.  */
-  if (SCALAR_FLOAT_MODE_P (mode))
+  scalar_float_mode float_mode;
+  if (is_a <scalar_float_mode> (mode, &float_mode))
     {
-      temp = expand_absneg_bit (ABS, mode, op0, target);
+      temp = expand_absneg_bit (ABS, float_mode, op0, target);
       if (temp)
 	return temp;
     }
@@ -3241,7 +3243,7 @@ expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
    and not playing with subregs so much, will help the register allocator.  */
 
 static rtx
-expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
 		        int bitpos, bool op0_is_abs)
 {
   machine_mode imode;
@@ -3325,7 +3327,7 @@ expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
    is true if op0 is known to have its sign bit clear.  */
 
 static rtx
-expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
 		     int bitpos, bool op0_is_abs)
 {
   machine_mode imode;
@@ -3423,12 +3425,12 @@ expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
 rtx
 expand_copysign (rtx op0, rtx op1, rtx target)
 {
-  machine_mode mode = GET_MODE (op0);
+  scalar_float_mode mode;
   const struct real_format *fmt;
   bool op0_is_abs;
   rtx temp;
 
-  gcc_assert (SCALAR_FLOAT_MODE_P (mode));
+  mode = as_a <scalar_float_mode> (GET_MODE (op0));
   gcc_assert (GET_MODE (op1) == mode);
 
   /* First try to do it with a special instruction.  */
diff --git a/gcc/real.h b/gcc/real.h
index 59af580..e861b03 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -183,8 +183,7 @@ extern const struct real_format *
 			: (gcc_unreachable (), 0)])
 
 #define FLOAT_MODE_FORMAT(MODE) \
-  (REAL_MODE_FORMAT (SCALAR_FLOAT_MODE_P (MODE)? (MODE) \
-					       : GET_MODE_INNER (MODE)))
+  (REAL_MODE_FORMAT (as_a <scalar_float_mode> (GET_MODE_INNER (MODE))))
 
 /* The following macro determines whether the floating point format is
    composite, i.e. may contain non-consecutive mantissa bits, in which
@@ -212,7 +211,7 @@ class format_helper
 {
 public:
   format_helper (const real_format *format) : m_format (format) {}
-  format_helper (machine_mode m);
+  template<typename T> format_helper (const T &);
   const real_format *operator-> () const { return m_format; }
   operator const real_format *() const { return m_format; }
 
@@ -222,7 +221,8 @@ private:
   const real_format *m_format;
 };
 
-inline format_helper::format_helper (machine_mode m)
+template<typename T>
+inline format_helper::format_helper (const T &m)
   : m_format (m == VOIDmode ? 0 : REAL_MODE_FORMAT (m))
 {}
 
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 0251bd4..907c1e7 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -5816,9 +5816,11 @@ simplify_immed_subreg (machine_mode outermode, rtx op,
 	    {
 	      /* This is big enough for anything on the platform.  */
 	      long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32];
-	      int bitsize = GET_MODE_BITSIZE (GET_MODE (el));
+	      scalar_float_mode el_mode;
+
+	      el_mode = as_a <scalar_float_mode> (GET_MODE (el));
+	      int bitsize = GET_MODE_BITSIZE (el_mode);
 
-	      gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (el)));
 	      gcc_assert (bitsize <= elem_bitsize);
 	      gcc_assert (bitsize % value_bit == 0);
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [9/67] Add SCALAR_FLOAT_TYPE_MODE
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (7 preceding siblings ...)
  2016-12-09 12:57 ` [7/67] Add scalar_float_mode Richard Sandiford
@ 2016-12-09 12:58 ` Richard Sandiford
  2016-12-09 12:59 ` [10/67] Make assemble_real take a scalar_float_mode Richard Sandiford
                   ` (60 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:58 UTC (permalink / raw)
  To: gcc-patches

This patch adds a macro that extracts the TYPE_MODE and forcibly
converts it to a scalar_float_mode.  The forcible conversion
includes a gcc_checking_assert that the mode is a SCALAR_FLOAT_MODE_P.

This becomes important as more static type checking is added by
later patches.  It has the additional benefit of bypassing the
VECTOR_TYPE_P (...) ? vector_type_mode (...) : ... condition
in TYPE_MODE; in release builds the new macro is a simple
field access.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* tree.h (SCALAR_FLOAT_TYPE_MODE): New macro.
	* builtins.c (expand_builtin_signbit): Use it instead of TYPE_MODE.
	* fold-const.c (fold_convert_const_real_from_fixed): Likewise.
	(native_encode_real): Likewise.
	(native_interpret_real): Likewise.
	* hsa-brig.c (emit_immediate_scalar_to_buffer): Likewise.
	* tree-vrp.c (simplify_float_conversion_using_ranges): Likeiwse.

gcc/cp/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* mangle.c (write_real_cst): Use SCALAR_FLOAT_TYPE_MODE
	instead of TYPE_MODE.

gcc/fortran/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* target-memory.c (size_float): Use SCALAR_FLOAT_TYPE_MODE
	instead of TYPE_MODE.

gcc/objc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* objc-encoding.c (encode_type): Use SCALAR_FLOAT_TYPE_MODE
	instead of TYPE_MODE.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 1f942b3..6de9a33 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5210,7 +5210,8 @@ static rtx
 expand_builtin_signbit (tree exp, rtx target)
 {
   const struct real_format *fmt;
-  machine_mode fmode, imode, rmode;
+  scalar_float_mode fmode;
+  machine_mode imode, rmode;
   tree arg;
   int word, bitpos;
   enum insn_code icode;
@@ -5221,7 +5222,7 @@ expand_builtin_signbit (tree exp, rtx target)
     return NULL_RTX;
 
   arg = CALL_EXPR_ARG (exp, 0);
-  fmode = TYPE_MODE (TREE_TYPE (arg));
+  fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
   rmode = TYPE_MODE (TREE_TYPE (exp));
   fmt = REAL_MODE_FORMAT (fmode);
 
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 4fffe0b..3cccb4f 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1795,7 +1795,7 @@ write_real_cst (const tree value)
   int i, limit, dir;
 
   tree type = TREE_TYPE (value);
-  int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
+  int words = GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)) / 32;
 
   real_to_target (target_real, &TREE_REAL_CST (value),
 		  TYPE_MODE (type));
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c649e54..6d7b839 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2007,7 +2007,8 @@ fold_convert_const_real_from_fixed (tree type, const_tree arg1)
   REAL_VALUE_TYPE value;
   tree t;
 
-  real_convert_from_fixed (&value, TYPE_MODE (type), &TREE_FIXED_CST (arg1));
+  real_convert_from_fixed (&value, SCALAR_FLOAT_TYPE_MODE (type),
+			   &TREE_FIXED_CST (arg1));
   t = build_real (type, value);
 
   TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
@@ -6970,7 +6971,7 @@ static int
 native_encode_real (const_tree expr, unsigned char *ptr, int len, int off)
 {
   tree type = TREE_TYPE (expr);
-  int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+  int total_bytes = GET_MODE_SIZE (SCALAR_FLOAT_TYPE_MODE (type));
   int byte, offset, word, words, bitpos;
   unsigned char value;
 
@@ -7215,7 +7216,7 @@ native_interpret_fixed (tree type, const unsigned char *ptr, int len)
 static tree
 native_interpret_real (tree type, const unsigned char *ptr, int len)
 {
-  machine_mode mode = TYPE_MODE (type);
+  scalar_float_mode mode = SCALAR_FLOAT_TYPE_MODE (type);
   int total_bytes = GET_MODE_SIZE (mode);
   unsigned char value;
   /* There are always 32 bits in each long, no matter the size of
diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c
index ac9cce2..b498f19 100644
--- a/gcc/fortran/target-memory.c
+++ b/gcc/fortran/target-memory.c
@@ -46,7 +46,7 @@ size_integer (int kind)
 static size_t
 size_float (int kind)
 {
-  return GET_MODE_SIZE (TYPE_MODE (gfc_get_real_type (kind)));;
+  return GET_MODE_SIZE (SCALAR_FLOAT_TYPE_MODE (gfc_get_real_type (kind)));
 }
 
 
diff --git a/gcc/hsa-brig.c b/gcc/hsa-brig.c
index acd9164..5591b5f 100644
--- a/gcc/hsa-brig.c
+++ b/gcc/hsa-brig.c
@@ -909,7 +909,7 @@ emit_immediate_scalar_to_buffer (tree value, char *data, unsigned need_len)
 		 "operands");
 	  return 2;
 	}
-      unsigned int_len = GET_MODE_SIZE (TYPE_MODE (type));
+      unsigned int_len = GET_MODE_SIZE (SCALAR_FLOAT_TYPE_MODE (type));
       /* There are always 32 bits in each long, no matter the size of
 	 the hosts long.  */
       long tmp[6];
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index 4496a09..3b72dd2 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -664,7 +664,7 @@ encode_type (tree type, int curtype, int format)
       {
 	char c;
 	/* Floating point types.  */
-	switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+	switch (GET_MODE_BITSIZE (SCALAR_FLOAT_TYPE_MODE (type)))
 	  {
 	  case 32:  c = 'f'; break;
 	  case 64:  c = 'd'; break;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index f3322b6..88ddbf8 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9969,7 +9969,8 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
   value_range *vr = get_value_range (rhs1);
-  machine_mode fltmode = TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
+  scalar_float_mode fltmode
+    = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
   machine_mode mode;
   tree tem;
   gassign *conv;
diff --git a/gcc/tree.h b/gcc/tree.h
index f432546..7791c22 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1829,6 +1829,8 @@ extern void protected_set_expr_location (tree, location_t);
    ((const machine_mode &) \
     (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
      ? vector_type_mode (NODE) : machine_mode ((NODE)->type_common.mode)))
+#define SCALAR_FLOAT_TYPE_MODE(NODE) \
+  (as_a <scalar_float_mode> (TYPE_CHECK (NODE)->type_common.mode))
 #define SET_TYPE_MODE(NODE, MODE) \
   (TYPE_CHECK (NODE)->type_common.mode = (MODE))
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [10/67] Make assemble_real take a scalar_float_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (8 preceding siblings ...)
  2016-12-09 12:58 ` [9/67] Add SCALAR_FLOAT_TYPE_MODE Richard Sandiford
@ 2016-12-09 12:59 ` Richard Sandiford
  2016-12-09 13:00 ` [0/67] Add wrapper classes for machine_modes Richard Biener
                   ` (59 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 12:59 UTC (permalink / raw)
  To: gcc-patches

As per subject.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* output.h (assemble_real): Take a scalar_float_mode.
	* config/arm/arm.c (arm_assemble_integer): Update accordingly.
	* config/arm/arm.md (consttable_4): Likewise.
	(consttable_8): Likewise.
	(consttable_16): Likewise.
	* config/mips/mips.md (consttable_float): Likewise.
	* config/s390/s390.c (s390_output_pool_entry): Likewise.
	* varasm.c (assemble_real): Take a scalar_float_mode.
	(output_constant_pool_2): Update accordingly.
	(output_constant): Likewise.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index aeec412..6922c4e 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -22397,8 +22397,9 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
         for (i = 0; i < units; i++)
           {
             rtx elt = CONST_VECTOR_ELT (x, i);
-            assemble_real
-              (*CONST_DOUBLE_REAL_VALUE (elt), GET_MODE_INNER (mode),
+	    assemble_real
+	      (*CONST_DOUBLE_REAL_VALUE (elt),
+	       as_a <scalar_float_mode> (GET_MODE_INNER (mode)),
 	       i == 0 ? BIGGEST_ALIGNMENT : size * BITS_PER_UNIT);
           }
 
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index d561a4b..4a911a0 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -11226,13 +11226,11 @@
   {
     rtx x = operands[0];
     making_const_table = TRUE;
-    switch (GET_MODE_CLASS (GET_MODE (x)))
+    scalar_float_mode float_mode;
+    if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
+      assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
+    else
       {
-      case MODE_FLOAT:
-	assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
-		       BITS_PER_WORD);
-	break;
-      default:
 	/* XXX: Sometimes gcc does something really dumb and ends up with
 	   a HIGH in a constant pool entry, usually because it's trying to
 	   load into a VFP register.  We know this will always be used in
@@ -11242,7 +11240,6 @@
 	  x = XEXP (x, 0);
         assemble_integer (x, 4, BITS_PER_WORD, 1);
 	mark_symbol_refs_as_used (x);
-        break;
       }
     return \"\";
   }"
@@ -11256,16 +11253,12 @@
   "*
   {
     making_const_table = TRUE;
-    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
-      {
-      case MODE_FLOAT:
-	assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
-		       GET_MODE (operands[0]), BITS_PER_WORD);
-	break;
-      default:
-        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
-        break;
-      }
+    scalar_float_mode float_mode;
+    if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
+      assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
+		     float_mode, BITS_PER_WORD);
+    else
+      assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
     return \"\";
   }"
   [(set_attr "length" "8")
@@ -11278,16 +11271,12 @@
   "*
   {
     making_const_table = TRUE;
-    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
-      {
-      case MODE_FLOAT:
-	assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
-		       GET_MODE (operands[0]), BITS_PER_WORD);
-	break;
-      default:
-        assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
-        break;
-      }
+    scalar_float_mode float_mode;
+    if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
+      assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
+		     float_mode, BITS_PER_WORD);
+    else
+      assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
     return \"\";
   }"
   [(set_attr "length" "16")
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index b2e5f97..73ca2fe 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -7371,7 +7371,7 @@
 {
   gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE);
   assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
-		 GET_MODE (operands[0]),
+		 as_a <scalar_float_mode> (GET_MODE (operands[0])),
 		 GET_MODE_BITSIZE (GET_MODE (operands[0])));
   return "";
 }
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index a48663d..a3bb952 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -9225,7 +9225,8 @@ s390_output_pool_entry (rtx exp, machine_mode mode, unsigned int align)
     case MODE_DECIMAL_FLOAT:
       gcc_assert (GET_CODE (exp) == CONST_DOUBLE);
 
-      assemble_real (*CONST_DOUBLE_REAL_VALUE (exp), mode, align);
+      assemble_real (*CONST_DOUBLE_REAL_VALUE (exp),
+		     as_a <scalar_float_mode> (mode), align);
       break;
 
     case MODE_INT:
diff --git a/gcc/output.h b/gcc/output.h
index 6c99381..c94fe08 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -281,7 +281,7 @@ extern section *get_named_text_section (tree, const char *, const char *);
 /* Assemble the floating-point constant D into an object of size MODE.  ALIGN
    is the alignment of the constant in bits.  If REVERSE is true, D is output
    in reverse storage order.  */
-extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned,
+extern void assemble_real (REAL_VALUE_TYPE, scalar_float_mode, unsigned,
 			   bool = false);
 
 /* Write the address of the entity given by SYMBOL to SEC.  */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 5b15847..320a5a6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -2764,7 +2764,7 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
    in reverse storage order.  */
 
 void
-assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align,
+assemble_real (REAL_VALUE_TYPE d, scalar_float_mode mode, unsigned int align,
 	       bool reverse)
 {
   long data[4] = {0, 0, 0, 0};
@@ -3830,7 +3830,8 @@ output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
     case MODE_DECIMAL_FLOAT:
       {
 	gcc_assert (CONST_DOUBLE_AS_FLOAT_P (x));
-	assemble_real (*CONST_DOUBLE_REAL_VALUE (x), mode, align, false);
+	assemble_real (*CONST_DOUBLE_REAL_VALUE (x),
+		       as_a <scalar_float_mode> (mode), align, false);
 	break;
       }
 
@@ -4805,7 +4806,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
       if (TREE_CODE (exp) != REAL_CST)
 	error ("initializer for floating value is not a floating constant");
       else
-	assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)),
+	assemble_real (TREE_REAL_CST (exp),
+		       SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (exp)),
 		       align, reverse);
       break;
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [0/67] Add wrapper classes for machine_modes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (9 preceding siblings ...)
  2016-12-09 12:59 ` [10/67] Make assemble_real take a scalar_float_mode Richard Sandiford
@ 2016-12-09 13:00 ` Richard Biener
  2016-12-09 13:54   ` Richard Sandiford
  2016-12-09 13:00 ` [12/67] Use opt_scalar_float_mode when iterating over float modes Richard Sandiford
                   ` (58 subsequent siblings)
  69 siblings, 1 reply; 79+ messages in thread
From: Richard Biener @ 2016-12-09 13:00 UTC (permalink / raw)
  To: GCC Patches, richard.sandiford

On Fri, Dec 9, 2016 at 1:48 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> This series includes most of the changes in group C from:
>
>     https://gcc.gnu.org/ml/gcc/2016-11/msg00033.html
>
> The idea is to add wrapper classes around machine_mode_enum
> for specific groups of modes, such as scalar integers, scalar floats,
> complex values, etc.  This has two main benefits: one specific to SVE
> and one not.
>
> The SVE-specific benefit is that it helps to introduce the concept
> of variable-length vectors.  To do that we need to change the size
> of a vector mode from being a known compile-time constant to being
> (possibly) a run-time invariant.  We then need to do the same for
> unconstrained machine_modes, which might or might not be vectors.
> Introducing these new constrained types means that we can continue
> to treat them as having a constant size.
>
> The other benefit is that it uses static type checking to enforce
> conditions that are easily forgotten otherwise.  The most common
> sources of problems seem to be:
>
> (a) using VOIDmode or BLKmode where a scalar integer was expected
>     (e.g. when getting the number of bits in the value).
>
> (b) simplifying vector operations in ways that only make sense for
>     scalars.
>
> The series helps with both of these, although we don't get the full
> benefit of (b) until variable-sized modes are introduced.
>
> I know of three specific cases in which the static type checking
> forced fixes for things that turned out to be real bugs (although
> we didn't know that at the time, otherwise we'd have posted patches).
> They were later fixed for trunk by:
>
>   https://gcc.gnu.org/ml/gcc-patches/2016-07/msg01783.html
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02983.html
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg02896.html
>
> The group C patches in ARM/sve-branch did slow compile time down a little.
> I've since taken steps to avoid that:
>
> - Make the tailcall pass handle aggregate parameters and return values
>   (already in trunk).
>
> - Turn some of the new wrapper functions into inline functions.
>
> - Make all the machmode.h macros that used:
>
>     __builtin_constant_p (M) ? foo_inline (M) : foo_array[M[
>
>   forward to an ALWAYS_INLINE function, so that (a) M is only evaluated
>   once and (b) __builtin_constant_p is applied to a variable, and so is
>   deferred until later passes.  This helped the optimisation to fire in
>   more cases and to continue firing when M is a class rather than a
>   raw enum.
>
> - In a similar vein, make sure that conditions like:
>
>      SImode == DImode
>
>   are treated as builtin_constant_p by gencondmd, so that .md patterns
>   with those conditions are dropped.
>
> With these changes the series is actually a very slight compile-time win.
> That might seem unlikely, but there are several possible reasons:
>
> 1. The machmode.h macro change above might allow more constant folding.
>
> 2. The series has a tendency to evaluate modes once, rather than
>    continually fetching them from (sometimes quite deep) rtx nests.
>    Refetching a mode is a particular problem if call comes between
>    two uses, since the compiler then has to re-evaluate the whole thing.
>
> 3. The series introduces many uses of new SCALAR_*TYPE_MODE macros,
>    as alternatives to TYPE_MODE.  The new macros avoid the usual:
>
>      (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
>       ? vector_type_mode (NODE) : (NODE)->type_common.mode)
>
>    and become direct field accesses in release builds.
>
>    VECTOR_TYPE_P would be consistently false for these uses,
>    but call-clobbered registers would usually be treated as clobbered
>    by the condition as a whole.
>
> Maybe (3) is the most likely reason.
>
> I tested this by compiling the testsuite for:
>
>     aarch64-linux-gnu alpha-linux-gnu arc-elf arm-linux-gnueabi
>     arm-linux-gnueabihf avr-elf bfin-elf c6x-elf cr16-elf cris-elf
>     epiphany-elf fr30-elf frv-linux-gnu ft32-elf h8300-elf
>     hppa64-hp-hpux11.23 ia64-linux-gnu i686-pc-linux-gnu
>     i686-apple-darwin iq2000-elf lm32-elf m32c-elf m32r-elf
>     m68k-linux-gnu mcore-elf microblaze-elf mips-linux-gnu
>     mipsisa64-linux-gnu mmix mn10300-elf moxie-rtems msp430-elf
>     nds32le-elf nios2-linux-gnu nvptx-none pdp11 powerpc-linux-gnuspe
>     powerpc-eabispe powerpc64-linux-gnu powerpc-ibm-aix7.0 rl78-elf
>     rx-elf s390-linux-gnu s390x-linux-gnu sh-linux-gnu sparc-linux-gnu
>     sparc64-linux-gnu sparc-wrs-vxworks spu-elf tilegx-elf tilepro-elf
>     xstormy16-elf v850-elf vax-netbsdelf visium-elf x86_64-darwin
>     x86_64-linux-gnu xtensa-elf
>
> and checking that there were no changes in assembly.  Also tested
> in the normal way on aarch64-linux-gnu and x86_64-linux-gnu.
>
> The series depends on the already-posted:
>
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg01657.html
>
> Sorry that this is so late, been distracted by other things.  Even if
> we're too far into stage 3 for SVE itself to go in, I was hoping this
> part (which was kind-of posted during stage 1) could go in independently.

What's the benefit of taking this but not SVE?

I'd say not at this stage please.

Richard.

> Thanks,
> Richard

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [12/67] Use opt_scalar_float_mode when iterating over float modes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (10 preceding siblings ...)
  2016-12-09 13:00 ` [0/67] Add wrapper classes for machine_modes Richard Biener
@ 2016-12-09 13:00 ` Richard Sandiford
  2016-12-09 13:00 ` [11/67] Add a float_mode_for_size helper function Richard Sandiford
                   ` (57 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:00 UTC (permalink / raw)
  To: gcc-patches

This means that we know when accessing the modes that the size is
a compile-time constant, even for SVE.  It also enables stricter
type safety in later patches.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (mode_iterator::start): Provide overload for opt_modes.
	(mode_iterator::iterate_p): Likewise.
	(mode_iterator::get_wider): Likewise.
	* expr.c (init_expr_target): Use opt_scalar_float_mode.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/misc.c (fp_prec_to_size): Use opt_scalar_float_mode.
	(fp_size_to_prec): Likewise.

gcc/c-family/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* c-cppbuiltin.c (c_cpp_builtins): Use opt_scalar_float_mode.

gcc/fortran/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* trans-types.c (gfc_init_kinds): Use opt_scalar_float_mode
	and FOR_EACH_MODE_IN_CLASS.

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 4bb22ed..cef8d84 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -1278,11 +1278,11 @@ enumerate_modes (void (*f) (const char *, int, int, int, int, int, int, int))
 int
 fp_prec_to_size (int prec)
 {
-  machine_mode mode;
+  opt_scalar_float_mode mode;
 
   FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
-    if (GET_MODE_PRECISION (mode) == prec)
-      return GET_MODE_BITSIZE (mode);
+    if (GET_MODE_PRECISION (*mode) == prec)
+      return GET_MODE_BITSIZE (*mode);
 
   gcc_unreachable ();
 }
@@ -1292,11 +1292,11 @@ fp_prec_to_size (int prec)
 int
 fp_size_to_prec (int size)
 {
-  machine_mode mode;
+  opt_scalar_float_mode mode;
 
   FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
-    if (GET_MODE_BITSIZE (mode) == size)
-      return GET_MODE_PRECISION (mode);
+    if (GET_MODE_BITSIZE (*mode) == size)
+      return GET_MODE_PRECISION (*mode);
 
   gcc_unreachable ();
 }
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 0d6f538..32a999a 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1184,9 +1184,10 @@ c_cpp_builtins (cpp_reader *pfile)
   if (flag_building_libgcc)
     {
       /* Properties of floating-point modes for libgcc2.c.  */
-      machine_mode mode;
-      FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+      opt_scalar_float_mode mode_iter;
+      FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_FLOAT)
 	{
+	  scalar_float_mode mode = *mode_iter;
 	  const char *name = GET_MODE_NAME (mode);
 	  char *macro_name
 	    = (char *) alloca (strlen (name)
diff --git a/gcc/expr.c b/gcc/expr.c
index a3a3e86..d277a88 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -110,7 +110,6 @@ void
 init_expr_target (void)
 {
   rtx pat;
-  machine_mode mode;
   int num_clobbers;
   rtx mem, mem1;
   rtx reg;
@@ -129,7 +128,7 @@ init_expr_target (void)
   pat = gen_rtx_SET (NULL_RTX, NULL_RTX);
   PATTERN (insn) = pat;
 
-  for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
+  for (machine_mode mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
        mode = (machine_mode_enum) ((int) mode + 1))
     {
       int regno;
@@ -175,9 +174,11 @@ init_expr_target (void)
 
   mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1));
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+  opt_scalar_float_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_FLOAT)
     {
-      machine_mode srcmode;
+      scalar_float_mode mode = *mode_iter;
+      scalar_float_mode srcmode;
       FOR_EACH_MODE_UNTIL (srcmode, mode)
 	{
 	  enum insn_code ic;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index c0d1a17..4c69237 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -348,6 +348,7 @@ void
 gfc_init_kinds (void)
 {
   machine_mode_enum mode;
+  opt_scalar_float_mode float_mode_iter;
   int i_index, r_index, kind;
   bool saw_i4 = false, saw_i8 = false;
   bool saw_r4 = false, saw_r8 = false, saw_r10 = false, saw_r16 = false;
@@ -403,9 +404,10 @@ gfc_init_kinds (void)
   /* Set the maximum integer kind.  Used with at least BOZ constants.  */
   gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
 
-  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT;
-       mode = (machine_mode_enum) ((int) mode + 1))
+  r_index = 0;
+  FOR_EACH_MODE_IN_CLASS (float_mode_iter, MODE_FLOAT)
     {
+      scalar_float_mode mode = *float_mode_iter;
       const struct real_format *fmt = REAL_MODE_FORMAT (mode);
       int kind;
 
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 41a3a00..2f4b076 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -628,6 +628,16 @@ namespace mode_iterator
 {
   /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */
 
+  template<typename T>
+  inline void
+  start (opt_mode<T> *iter, enum mode_class mclass)
+  {
+    if (GET_CLASS_NARROWEST_MODE (mclass) == E_VOIDmode)
+      *iter = opt_mode<T> ();
+    else
+      *iter = as_a<T> (GET_CLASS_NARROWEST_MODE (mclass));
+  }
+
   inline void
   start (machine_mode *iter, enum mode_class mclass)
   {
@@ -636,6 +646,13 @@ namespace mode_iterator
 
   /* Return true if mode iterator *ITER has not reached the end.  */
 
+  template<typename T>
+  inline bool
+  iterate_p (opt_mode<T> *iter)
+  {
+    return iter->exists ();
+  }
+
   inline bool
   iterate_p (machine_mode *iter)
   {
@@ -645,6 +662,13 @@ namespace mode_iterator
   /* Set mode iterator *ITER to the next widest mode in the same class,
      if any.  */
 
+  template<typename T>
+  inline void
+  get_wider (opt_mode<T> *iter)
+  {
+    *iter = GET_MODE_WIDER_MODE (**iter);
+  }
+
   inline void
   get_wider (machine_mode *iter)
   {

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [11/67] Add a float_mode_for_size helper function
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (11 preceding siblings ...)
  2016-12-09 13:00 ` [12/67] Use opt_scalar_float_mode when iterating over float modes Richard Sandiford
@ 2016-12-09 13:00 ` Richard Sandiford
  2016-12-09 13:01 ` [13/67] Make floatn_mode return an opt_scalar_float_mode Richard Sandiford
                   ` (56 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:00 UTC (permalink / raw)
  To: gcc-patches

This provides a type-safe way to ask for a float mode and get it as a
scalar_float_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* coretypes.h (opt_scalar_float_mode): New typedef.
	* machmode.h (float_mode_for_size): New function.
	* emit-rtl.c (double_mode): Delete.
	(init_emit_once): Use float_mode_for_size.
	* stor-layout.c (layout_type): Likewise.

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index f4c1859..8341cab 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -58,6 +58,7 @@ typedef const struct rtx_def *const_rtx;
 class machine_mode;
 class scalar_float_mode;
 template<typename> class opt_mode;
+typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
    hierarchy, along with the relevant invariant.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 3bcafbb..efddad4 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -71,7 +71,6 @@ struct target_rtl *this_target_rtl = &default_target_rtl;
 
 machine_mode byte_mode;	/* Mode whose width is BITS_PER_UNIT.  */
 machine_mode word_mode;	/* Mode whose width is BITS_PER_WORD.  */
-machine_mode double_mode;	/* Mode whose width is DOUBLE_TYPE_SIZE.  */
 machine_mode ptr_mode;	/* Mode whose width is POINTER_SIZE.  */
 
 /* Datastructures maintained for currently processed function in RTL form.  */
@@ -5864,7 +5863,7 @@ init_emit_once (void)
 {
   int i;
   machine_mode mode;
-  machine_mode double_mode;
+  scalar_float_mode double_mode;
 
   /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
      CONST_FIXED, and memory attribute hash tables.  */
@@ -5908,7 +5907,7 @@ init_emit_once (void)
   else
     const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);
 
-  double_mode = mode_for_size (DOUBLE_TYPE_SIZE, MODE_FLOAT, 0);
+  double_mode = *float_mode_for_size (DOUBLE_TYPE_SIZE);
 
   real_from_integer (&dconst0, double_mode, 0, SIGNED);
   real_from_integer (&dconst1, double_mode, 1, SIGNED);
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 996f991..41a3a00 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -513,7 +513,16 @@ extern const unsigned char mode_complex[NUM_MACHINE_MODES];
 
 extern machine_mode mode_for_size (unsigned int, enum mode_class, int);
 
-/* Similar, but find the smallest mode for a given width.  */
+/* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one
+   exists.  */
+
+inline opt_scalar_float_mode
+float_mode_for_size (unsigned int size)
+{
+  return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
+}
+
+/* Similar to mode_for_size, but find the smallest mode for a given width.  */
 
 extern machine_mode smallest_mode_for_size (unsigned int,
 						 enum mode_class);
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 834cf8b..2cde94e 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2132,14 +2132,16 @@ layout_type (tree type)
       break;
 
     case REAL_TYPE:
-      /* Allow the caller to choose the type mode, which is how decimal
-	 floats are distinguished from binary ones.  */
-      if (TYPE_MODE (type) == VOIDmode)
-	SET_TYPE_MODE (type,
-		       mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-      break;
+      {
+	/* Allow the caller to choose the type mode, which is how decimal
+	   floats are distinguished from binary ones.  */
+	if (TYPE_MODE (type) == VOIDmode)
+	  SET_TYPE_MODE (type, *float_mode_for_size (TYPE_PRECISION (type)));
+	scalar_float_mode mode = as_a <scalar_float_mode> (TYPE_MODE (type));
+	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+	break;
+      }
 
    case FIXED_POINT_TYPE:
      /* TYPE_MODE (type) has been set already.  */

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [13/67] Make floatn_mode return an opt_scalar_float_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (12 preceding siblings ...)
  2016-12-09 13:00 ` [11/67] Add a float_mode_for_size helper function Richard Sandiford
@ 2016-12-09 13:01 ` Richard Sandiford
  2016-12-09 13:02 ` [14/67] Make libgcc_floating_mode_supported_p take a scalar_float_mode Richard Sandiford
                   ` (55 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:01 UTC (permalink / raw)
  To: gcc-patches

As per subject.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* target.def (default_floatn_mode): Return an opt_scalar_float_mode.
	* doc/tm.texi: Regenerate.
	* config/arm/arm.c (arm_floatn_mode): Return an opt_scalar_float_mode.
	* config/rs6000/rs6000.c (rs6000_floatn_mode): Likewise.
	* targhooks.h (default_floatn_mode): Likewise.
	* targhooks.c (default_floatn_mode): Likewise.
	* tree.c (build_common_tree_nodes): Update accordingly.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6922c4e..45c08bf 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -303,7 +303,7 @@ static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
 static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
 						int reloc);
 static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
-static machine_mode arm_floatn_mode (int, bool);
+static opt_scalar_float_mode arm_floatn_mode (int, bool);
 \f
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -23372,11 +23372,15 @@ arm_excess_precision (enum excess_precision_type type)
 /* Implement TARGET_FLOATN_MODE.  Make very sure that we don't provide
    _Float16 if we are using anything other than ieee format for 16-bit
    floating point.  Otherwise, punt to the default implementation.  */
-static machine_mode
+static opt_scalar_float_mode
 arm_floatn_mode (int n, bool extended)
 {
   if (!extended && n == 16)
-    return arm_fp16_format == ARM_FP16_FORMAT_IEEE ? HFmode : VOIDmode;
+    {
+      if (arm_fp16_format == ARM_FP16_FORMAT_IEEE)
+	return HFmode;
+      return opt_scalar_float_mode ();
+    }
 
   return default_floatn_mode (n, extended);
 }
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e868cef..08a069d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -37693,7 +37693,7 @@ rs6000_vector_mode_supported_p (machine_mode mode)
 }
 
 /* Target hook for floatn_mode.  */
-static machine_mode
+static opt_scalar_float_mode
 rs6000_floatn_mode (int n, bool extended)
 {
   if (extended)
@@ -37707,10 +37707,10 @@ rs6000_floatn_mode (int n, bool extended)
 	  if (TARGET_FLOAT128_KEYWORD)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
-	    return VOIDmode;
+	    return opt_scalar_float_mode ();
 
 	case 128:
-	  return VOIDmode;
+	  return opt_scalar_float_mode ();
 
 	default:
 	  /* Those are the only valid _FloatNx types.  */
@@ -37731,10 +37731,10 @@ rs6000_floatn_mode (int n, bool extended)
 	  if (TARGET_FLOAT128_KEYWORD)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
-	    return VOIDmode;
+	    return opt_scalar_float_mode ();
 
 	default:
-	  return VOIDmode;
+	  return opt_scalar_float_mode ();
 	}
     }
 
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 199ec75..187d20d 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4258,22 +4258,22 @@ hook returns true for all of @code{SFmode}, @code{DFmode},
 @code{XFmode} and @code{TFmode}, if such modes exist.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_FLOATN_MODE (int @var{n}, bool @var{extended})
+@deftypefn {Target Hook} opt_scalar_float_mode TARGET_FLOATN_MODE (int @var{n}, bool @var{extended})
 Define this to return the machine mode to use for the type 
 @code{_Float@var{n}}, if @var{extended} is false, or the type 
-@code{_Float@var{n}x}, if @var{extended} is true.  If such a type 
-is not supported, return @code{VOIDmode}.  The default version of this 
-hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for 
+@code{_Float@var{n}x}, if @var{extended} is true.  If such a type is not
+supported, return @code{opt_scalar_float_mode ()}.  The default version of
+this hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for
 @code{_Float64} and @code{_Float32x} and @code{TFmode} for 
 @code{_Float128}, if those modes exist and satisfy the requirements for 
 those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and 
 @code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it 
 returns the first of @code{XFmode} and @code{TFmode} that exists and 
 satisfies the same requirements; for other types, it returns 
-@code{VOIDmode}.  The hook is only called for values of @var{n} and 
-@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that 
-is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or 
-greater than 128 and a multiple of 32.
+@code{opt_scalar_float_mode ()}.  The hook is only called for values
+of @var{n} and @var{extended} that are valid according to
+ISO/IEC TS 18661-3:2015; that is, @var{n} is one of 32, 64, 128, or,
+if @var{extended} is false, 16 or greater than 128 and a multiple of 32.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (machine_mode @var{mode})
diff --git a/gcc/target.def b/gcc/target.def
index 3574ea8..09b23b2 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3365,20 +3365,20 @@ DEFHOOK
 (floatn_mode,
  "Define this to return the machine mode to use for the type \n\
 @code{_Float@var{n}}, if @var{extended} is false, or the type \n\
-@code{_Float@var{n}x}, if @var{extended} is true.  If such a type \n\
-is not supported, return @code{VOIDmode}.  The default version of this \n\
-hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for \n\
+@code{_Float@var{n}x}, if @var{extended} is true.  If such a type is not\n\
+supported, return @code{opt_scalar_float_mode ()}.  The default version of\n\
+this hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for\n\
 @code{_Float64} and @code{_Float32x} and @code{TFmode} for \n\
 @code{_Float128}, if those modes exist and satisfy the requirements for \n\
 those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and \n\
 @code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it \n\
 returns the first of @code{XFmode} and @code{TFmode} that exists and \n\
 satisfies the same requirements; for other types, it returns \n\
-@code{VOIDmode}.  The hook is only called for values of @var{n} and \n\
-@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that \n\
-is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or \n\
-greater than 128 and a multiple of 32.",
- machine_mode, (int n, bool extended),
+@code{opt_scalar_float_mode ()}.  The hook is only called for values\n\
+of @var{n} and @var{extended} that are valid according to\n\
+ISO/IEC TS 18661-3:2015; that is, @var{n} is one of 32, 64, 128, or,\n\
+if @var{extended} is false, 16 or greater than 128 and a multiple of 32.",
+ opt_scalar_float_mode, (int n, bool extended),
  default_floatn_mode)
 
 /* Compute cost of moving data from a register of class FROM to one of
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 6178096..f8a9fae 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -467,12 +467,12 @@ default_libgcc_floating_mode_supported_p (machine_mode mode)
 /* Return the machine mode to use for the type _FloatN, if EXTENDED is
    false, or _FloatNx, if EXTENDED is true, or VOIDmode if not
    supported.  */
-machine_mode
+opt_scalar_float_mode
 default_floatn_mode (int n, bool extended)
 {
   if (extended)
     {
-      machine_mode cand1 = VOIDmode, cand2 = VOIDmode;
+      opt_scalar_float_mode cand1, cand2;
       switch (n)
 	{
 	case 32:
@@ -497,20 +497,20 @@ default_floatn_mode (int n, bool extended)
 	  /* Those are the only valid _FloatNx types.  */
 	  gcc_unreachable ();
 	}
-      if (cand1 != VOIDmode
-	  && REAL_MODE_FORMAT (cand1)->ieee_bits > n
-	  && targetm.scalar_mode_supported_p (cand1)
-	  && targetm.libgcc_floating_mode_supported_p (cand1))
+      if (cand1.exists ()
+	  && REAL_MODE_FORMAT (*cand1)->ieee_bits > n
+	  && targetm.scalar_mode_supported_p (*cand1)
+	  && targetm.libgcc_floating_mode_supported_p (*cand1))
 	return cand1;
-      if (cand2 != VOIDmode
-	  && REAL_MODE_FORMAT (cand2)->ieee_bits > n
-	  && targetm.scalar_mode_supported_p (cand2)
-	  && targetm.libgcc_floating_mode_supported_p (cand2))
+      if (cand2.exists ()
+	  && REAL_MODE_FORMAT (*cand2)->ieee_bits > n
+	  && targetm.scalar_mode_supported_p (*cand2)
+	  && targetm.libgcc_floating_mode_supported_p (*cand2))
 	return cand2;
     }
   else
     {
-      machine_mode cand = VOIDmode;
+      opt_scalar_float_mode cand;
       switch (n)
 	{
 	case 16:
@@ -543,13 +543,13 @@ default_floatn_mode (int n, bool extended)
 	default:
 	  break;
 	}
-      if (cand != VOIDmode
-	  && REAL_MODE_FORMAT (cand)->ieee_bits == n
-	  && targetm.scalar_mode_supported_p (cand)
-	  && targetm.libgcc_floating_mode_supported_p (cand))
+      if (cand.exists ()
+	  && REAL_MODE_FORMAT (*cand)->ieee_bits == n
+	  && targetm.scalar_mode_supported_p (*cand)
+	  && targetm.libgcc_floating_mode_supported_p (*cand))
 	return cand;
     }
-  return VOIDmode;
+  return opt_scalar_float_mode ();
 }
 
 /* Make some target macros useable by target-independent code.  */
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 933b70c..7b633c2 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -73,7 +73,7 @@ extern tree default_mangle_assembler_name (const char *);
 
 extern bool default_scalar_mode_supported_p (machine_mode);
 extern bool default_libgcc_floating_mode_supported_p (machine_mode);
-extern machine_mode default_floatn_mode (int, bool);
+extern opt_scalar_float_mode default_floatn_mode (int, bool);
 extern bool targhook_words_big_endian (void);
 extern bool targhook_float_words_big_endian (void);
 extern bool default_float_exceptions_rounding_supported_p (void);
diff --git a/gcc/tree.c b/gcc/tree.c
index da295ab..5124576 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10427,8 +10427,8 @@ build_common_tree_nodes (bool signed_char)
     {
       int n = floatn_nx_types[i].n;
       bool extended = floatn_nx_types[i].extended;
-      machine_mode mode = targetm.floatn_mode (n, extended);
-      if (mode == VOIDmode)
+      scalar_float_mode mode;
+      if (!targetm.floatn_mode (n, extended).exists (&mode))
 	continue;
       int precision = GET_MODE_PRECISION (mode);
       /* Work around the rs6000 KFmode having precision 113 not

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [14/67] Make libgcc_floating_mode_supported_p take a scalar_float_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (13 preceding siblings ...)
  2016-12-09 13:01 ` [13/67] Make floatn_mode return an opt_scalar_float_mode Richard Sandiford
@ 2016-12-09 13:02 ` Richard Sandiford
  2016-12-09 13:03 ` [16/67] Add scalar_int_mode_pod Richard Sandiford
                   ` (54 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:02 UTC (permalink / raw)
  To: gcc-patches

As per subject.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* target.def (default_libgcc_floating_mode_supported_p): Take
	a scalar_float_mode.
	* doc/tm.texi: Regenerate.
	* targhooks.h (default_floatn_mode): Take a scalar_float_mode.
	* targhooks.c (default_floatn_mode): Likewise.
	* config/aarch64/aarch64.c (aarch64_libgcc_floating_mode_supported_p):
	Likewise.

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index cc97b7a..f399514 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14547,7 +14547,7 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
    if MODE is HFmode, and punt to the generic implementation otherwise.  */
 
 static bool
-aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
+aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 {
   return (mode == HFmode
 	  ? true
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 187d20d..4993817 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4250,7 +4250,7 @@ If this hook allows @code{val} to have a scalar mode, then
 @code{int8x8x3_t}s in registers rather than forcing them onto the stack.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P (machine_mode @var{mode})
+@deftypefn {Target Hook} bool TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P (scalar_float_mode @var{mode})
 Define this to return nonzero if libgcc provides support for the 
 floating-point mode @var{mode}, which is known to pass 
 @code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this 
diff --git a/gcc/target.def b/gcc/target.def
index 09b23b2..fa765de 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3358,7 +3358,7 @@ floating-point mode @var{mode}, which is known to pass \n\
 @code{TARGET_SCALAR_MODE_SUPPORTED_P}.  The default version of this \n\
 hook returns true for all of @code{SFmode}, @code{DFmode}, \n\
 @code{XFmode} and @code{TFmode}, if such modes exist.",
- bool, (machine_mode mode),
+ bool, (scalar_float_mode mode),
  default_libgcc_floating_mode_supported_p)
 
 DEFHOOK
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index f8a9fae..90892fa 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -441,7 +441,7 @@ default_scalar_mode_supported_p (machine_mode mode)
    be supported as a scalar mode).  */
 
 bool
-default_libgcc_floating_mode_supported_p (machine_mode mode)
+default_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 7b633c2..1a56ec7 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -72,7 +72,7 @@ extern bool default_print_operand_punct_valid_p (unsigned char);
 extern tree default_mangle_assembler_name (const char *);
 
 extern bool default_scalar_mode_supported_p (machine_mode);
-extern bool default_libgcc_floating_mode_supported_p (machine_mode);
+extern bool default_libgcc_floating_mode_supported_p (scalar_float_mode);
 extern opt_scalar_float_mode default_floatn_mode (int, bool);
 extern bool targhook_words_big_endian (void);
 extern bool targhook_float_words_big_endian (void);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [15/67] Add scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (15 preceding siblings ...)
  2016-12-09 13:03 ` [16/67] Add scalar_int_mode_pod Richard Sandiford
@ 2016-12-09 13:03 ` Richard Sandiford
  2016-12-09 13:04 ` [17/67] Add an int_mode_for_size helper function Richard Sandiford
                   ` (52 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:03 UTC (permalink / raw)
  To: gcc-patches

Similar to the previous scalar_float_mode patch, but for modes that
satisfy SCALAR_INT_MODE_P.  There are very many uses of scalar integers,
so this patch only makes one token change to the types of byte_mode,
word_mode and ptr_mode.  The next patches in the series gradually
replace more uses.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* config/epiphany/epiphany.h (RTX_OK_FOR_OFFSET_P): Add casts
	to machine_mode.
	* coretypes.h (scalar_int_mode): New type.
	(opt_scalar_int_mode): New typedef.
	* machmode.h (scalar_int_mode): New class.
	(scalar_int_mode::includes_p): New function.
	(scalar_int_mode::from_int): New function.
	(byte_mode): Change type to scalar_int_mode.
	(word_mode): Likewise.
	(ptr_mode): Likewise.
	* emit-rtl.c (byte_mode): Likewise.
	(word_mode): Likewise.
	(ptr_mode): Likewise.
	(init_derived_machine_modes): Update accordingly.
	* genmodes.c (get_mode_class): Return scalar_int_mode for MODE_INT
	and MODE_PARTIAL_INT.

diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h
index 9e7ee50..3818af3 100644
--- a/gcc/config/epiphany/epiphany.h
+++ b/gcc/config/epiphany/epiphany.h
@@ -641,7 +641,8 @@ typedef struct GTY (()) machine_function
 
 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
   RTX_OK_FOR_OFFSET_1 (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
-		       && epiphany_vect_align == 4 ? SImode : (MODE), X)
+		       && epiphany_vect_align == 4 \
+		       ? (machine_mode) SImode : (machine_mode) (MODE), X)
 #define RTX_OK_FOR_OFFSET_1(MODE, X) \
   (GET_CODE (X) == CONST_INT \
    && !(INTVAL (X) & (GET_MODE_SIZE (MODE) - 1)) \
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 8341cab..6dc3e88 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -56,8 +56,10 @@ struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
 class machine_mode;
+class scalar_int_mode;
 class scalar_float_mode;
 template<typename> class opt_mode;
+typedef opt_mode<scalar_int_mode> opt_scalar_int_mode;
 typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index efddad4..b9d87d3 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -69,9 +69,9 @@ struct target_rtl *this_target_rtl = &default_target_rtl;
 
 /* Commonly used modes.  */
 
-machine_mode byte_mode;	/* Mode whose width is BITS_PER_UNIT.  */
-machine_mode word_mode;	/* Mode whose width is BITS_PER_WORD.  */
-machine_mode ptr_mode;	/* Mode whose width is POINTER_SIZE.  */
+scalar_int_mode byte_mode;	/* Mode whose width is BITS_PER_UNIT.  */
+scalar_int_mode word_mode;	/* Mode whose width is BITS_PER_WORD.  */
+scalar_int_mode ptr_mode;	/* Mode whose width is POINTER_SIZE.  */
 
 /* Datastructures maintained for currently processed function in RTL form.  */
 
@@ -5838,22 +5838,24 @@ init_emit_regs (void)
 void
 init_derived_machine_modes (void)
 {
-  byte_mode = VOIDmode;
-  word_mode = VOIDmode;
-
-  machine_mode mode;
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
+  opt_scalar_int_mode mode_iter, opt_byte_mode, opt_word_mode;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
     {
+      scalar_int_mode mode = *mode_iter;
+
       if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
-	  && byte_mode == VOIDmode)
-	byte_mode = mode;
+	  && !opt_byte_mode.exists ())
+	opt_byte_mode = mode;
 
       if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD
-	  && word_mode == VOIDmode)
-	word_mode = mode;
+	  && !opt_word_mode.exists ())
+	opt_word_mode = mode;
     }
 
-  ptr_mode = mode_for_size (POINTER_SIZE, GET_MODE_CLASS (Pmode), 0);
+  byte_mode = *opt_byte_mode;
+  word_mode = *opt_word_mode;
+  ptr_mode = as_a <scalar_int_mode> (mode_for_size (POINTER_SIZE,
+						    MODE_INT, 0));
 }
 
 /* Create some permanent unique rtl objects shared between all functions.  */
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 3cc426e..eddbff7 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1137,6 +1137,10 @@ get_mode_class (struct mode_data *mode)
 {
   switch (mode->cl)
     {
+    case MODE_INT:
+    case MODE_PARTIAL_INT:
+      return "scalar_int_mode";
+
     case MODE_FLOAT:
     case MODE_DECIMAL_FLOAT:
       return "scalar_float_mode";
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 2f4b076..8c8dd54 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -292,6 +292,40 @@ is_a (machine_mode_enum m, U *result)
   return false;
 }
 
+/* Represents a machine mode that is known to be a SCALAR_INT_MODE_P.  */
+class scalar_int_mode
+{
+public:
+  ALWAYS_INLINE scalar_int_mode () {}
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+
+  static bool includes_p (machine_mode_enum);
+  static scalar_int_mode from_int (int);
+
+PROTECT_ENUM_CONVERSION:
+  ALWAYS_INLINE scalar_int_mode (machine_mode_enum m) : m_mode (m) {}
+
+protected:
+  machine_mode_enum m_mode;
+};
+
+/* Return true if M is a scalar_int_mode.  */
+
+inline bool
+scalar_int_mode::includes_p (machine_mode_enum m)
+{
+  return SCALAR_INT_MODE_P (m);
+}
+
+/* Return M as a scalar_int_mode.  This function should only be used by
+   utility functions; general code should use as_a<T> instead.  */
+
+ALWAYS_INLINE scalar_int_mode
+scalar_int_mode::from_int (int i)
+{
+  return machine_mode_enum (i);
+}
+
 /* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P.  */
 class scalar_float_mode
 {
@@ -597,9 +631,9 @@ get_narrowest_mode (T 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.  */
 
-extern machine_mode byte_mode;
-extern machine_mode word_mode;
-extern machine_mode ptr_mode;
+extern scalar_int_mode byte_mode;
+extern scalar_int_mode word_mode;
+extern scalar_int_mode ptr_mode;
 
 /* Target-dependent machine mode initialization - in insn-modes.c.  */
 extern void init_adjust_machine_modes (void);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [16/67] Add scalar_int_mode_pod
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (14 preceding siblings ...)
  2016-12-09 13:02 ` [14/67] Make libgcc_floating_mode_supported_p take a scalar_float_mode Richard Sandiford
@ 2016-12-09 13:03 ` Richard Sandiford
  2016-12-09 13:03 ` [15/67] Add scalar_int_mode Richard Sandiford
                   ` (53 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:03 UTC (permalink / raw)
  To: gcc-patches

This patch adds a POD class for scalar integers, as an instance
of a new pod_mode template.  Later patches will use pod_mode in
situations that really do need to be POD; in this patch we're
simply using PODs to remove load-time initialisation.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* coretypes.h (pod_mode): New type.
	(scalar_int_mode_pod): New typedef.
	* machmode.h (pod_mode): New class.
	(int_n_data_t::m): Change type to scalar_int_mode_pod.
	* genmodes.c (emit_mode_int_n): Update accordingly.

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 6dc3e88..5073f35 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -61,6 +61,8 @@ class scalar_float_mode;
 template<typename> class opt_mode;
 typedef opt_mode<scalar_int_mode> opt_scalar_int_mode;
 typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
+template<typename> class pod_mode;
+typedef pod_mode<scalar_int_mode> scalar_int_mode_pod;
 
 /* Subclasses of rtx_def, using indentation to show the class
    hierarchy, along with the relevant invariant.
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index eddbff7..8ee0fae6 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1799,7 +1799,7 @@ emit_mode_int_n (void)
       m = mode_sort[i];
       printf(" {\n");
       tagged_printf ("%u", m->int_n, m->name);
-      printf ("E_%smode,", m->name);
+      printf ("{ E_%smode },", m->name);
       printf(" },\n");
     }
 
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 8c8dd54..bf568c9 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -247,6 +247,17 @@ opt_mode<T>::exists (U *mode) const
   return false;
 }
 
+/* A POD version of mode class T.  */
+
+template<typename T>
+struct pod_mode
+{
+  machine_mode_enum m_mode;
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+  ALWAYS_INLINE operator T () const { return T::from_int (m_mode); }
+  ALWAYS_INLINE pod_mode &operator = (const T &m) { m_mode = m; return *this; }
+};
+
 /* Return true if mode M has type T.  */
 
 template<typename T>
@@ -649,7 +660,7 @@ extern void init_adjust_machine_modes (void);
 struct int_n_data_t {
   /* These parts are initailized by genmodes output */
   unsigned int bitsize;
-  machine_mode_enum m;
+  scalar_int_mode_pod m;
   /* RID_* is RID_INTN_BASE + index into this array */
 };
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [17/67] Add an int_mode_for_size helper function
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (16 preceding siblings ...)
  2016-12-09 13:03 ` [15/67] Add scalar_int_mode Richard Sandiford
@ 2016-12-09 13:04 ` Richard Sandiford
  2016-12-09 13:05 ` [19/67] Add a smallest_int_mode_for_size " Richard Sandiford
                   ` (51 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:04 UTC (permalink / raw)
  To: gcc-patches

This patch adds a wrapper around mode_for_size for cases in which
the mode class is MODE_INT (the commonest case).  The return type
can then be an opt_scalar_int_mode instead of a machine_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (int_mode_for_size): New function.
	* builtins.c (set_builtin_user_assembler_name): Use int_mode_for_size
	instead of mode_for_size.
	* calls.c (save_fixed_argument_area): Likewise.  Make use of BLKmode
	explicit.
	* combine.c (expand_field_assignment): Use int_mode_for_size
	instead of mode_for_size.
	(make_extraction): Likewise.
	(simplify_shift_const_1): Likewise.
	(simplify_comparison): Likewise.
	* dojump.c (do_jump): Likewise.
	* dwarf2out.c (mem_loc_descriptor): Likewise.
	* emit-rtl.c (init_derived_machine_modes): Likewise.
	* expmed.c (flip_storage_order): Likewise.
	(convert_extracted_bit_field): Likewise.
	* expr.c (copy_blkmode_from_reg): Likewise.
	* graphite-isl-ast-to-gimple.c (max_mode_int_precision): Likewise.
	* internal-fn.c (expand_mul_overflow): Likewise.
	* lower-subreg.c (simple_move): Likewise.
	* optabs-libfuncs.c (init_optabs): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.
	* stor-layout.c (vector_type_mode): Likewise.
	* tree-ssa-strlen.c (handle_builtin_memcmp): Likewise.
	* tree-vect-data-refs.c (vect_lanes_optab_supported_p): Likewise.
	* tree-vect-generic.c (expand_vector_parallel): Likewise.
	* tree-vect-stmts.c (vectorizable_load): Likewise.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/decl.c (gnat_to_gnu_entity): Use int_mode_for_size
	instead of mode_for_size.
	(gnat_to_gnu_subprog_type): Likewise.
	* gcc-interface/utils.c (make_type_from_size): Likewise.

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index d3bee34..843024e 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -3859,11 +3859,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
 	/* True if we make a dummy type here.  */
 	bool made_dummy = false;
 	/* The mode to be used for the pointer type.  */
-	machine_mode p_mode = mode_for_size (esize, MODE_INT, 0);
+	scalar_int_mode p_mode;
 	/* The GCC type used for the designated type.  */
 	tree gnu_desig_type = NULL_TREE;
 
-	if (!targetm.valid_pointer_mode (p_mode))
+	if (!int_mode_for_size (esize, 0).exists (&p_mode)
+	    || !targetm.valid_pointer_mode (p_mode))
 	  p_mode = ptr_mode;
 
 	/* If either the designated type or its full view is an unconstrained
@@ -6113,12 +6114,11 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
 	      unsigned int size
 		= TREE_INT_CST_LOW (TYPE_SIZE (gnu_cico_return_type));
 	      unsigned int i = BITS_PER_UNIT;
-	      machine_mode mode;
+	      scalar_int_mode mode;
 
 	      while (i < size)
 		i <<= 1;
-	      mode = mode_for_size (i, MODE_INT, 0);
-	      if (mode != BLKmode)
+	      if (int_mode_for_size (i, 0).exists (&mode))
 		{
 		  SET_TYPE_MODE (gnu_cico_return_type, mode);
 		  SET_TYPE_ALIGN (gnu_cico_return_type,
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 29e5203..937691c 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -1151,8 +1151,9 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
 	 may need to return the thin pointer.  */
       if (TYPE_FAT_POINTER_P (type) && size < POINTER_SIZE * 2)
 	{
-	  machine_mode p_mode = mode_for_size (size, MODE_INT, 0);
-	  if (!targetm.valid_pointer_mode (p_mode))
+	  scalar_int_mode p_mode;
+	  if (!int_mode_for_size (size, 0).exists (&p_mode)
+	      || !targetm.valid_pointer_mode (p_mode))
 	    p_mode = ptr_mode;
 	  return
 	    build_pointer_type_for_mode
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 6de9a33..655ae27 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -10250,9 +10250,9 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
   if (DECL_FUNCTION_CODE (decl) == BUILT_IN_FFS
       && INT_TYPE_SIZE < BITS_PER_WORD)
     {
+      scalar_int_mode mode = *int_mode_for_size (INT_TYPE_SIZE, 0);
       set_user_assembler_libfunc ("ffs", asmspec);
-      set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
-			 "ffs");
+      set_optab_libfunc (ffs_optab, mode, "ffs");
     }
 }
 
diff --git a/gcc/calls.c b/gcc/calls.c
index fcfee25..7e58e14 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1025,7 +1025,6 @@ save_fixed_argument_area (int reg_parm_stack_space, rtx argblock, int *low_to_sa
     if (stack_usage_map[low] != 0)
       {
 	int num_to_save;
-	machine_mode save_mode;
 	int delta;
 	rtx addr;
 	rtx stack_area;
@@ -1038,13 +1037,16 @@ save_fixed_argument_area (int reg_parm_stack_space, rtx argblock, int *low_to_sa
 	*high_to_save = high;
 
 	num_to_save = high - low + 1;
-	save_mode = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
+
+	opt_scalar_int_mode save_mode
+	  = int_mode_for_size (num_to_save * BITS_PER_UNIT, 1);
 
 	/* If we don't have the required alignment, must do this
 	   in BLKmode.  */
-	if ((low & (MIN (GET_MODE_SIZE (save_mode),
-			 BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
-	  save_mode = BLKmode;
+	if (save_mode.exists ()
+	    && (low & (MIN (GET_MODE_SIZE (*save_mode),
+			    BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
+	  save_mode = opt_scalar_int_mode ();
 
 	if (ARGS_GROW_DOWNWARD)
 	  delta = -high;
@@ -1052,18 +1054,21 @@ save_fixed_argument_area (int reg_parm_stack_space, rtx argblock, int *low_to_sa
 	  delta = low;
 
 	addr = plus_constant (Pmode, argblock, delta);
-	stack_area = gen_rtx_MEM (save_mode, memory_address (save_mode, addr));
 
-	set_mem_align (stack_area, PARM_BOUNDARY);
-	if (save_mode == BLKmode)
+	if (!save_mode.exists ())
 	  {
+	    stack_area = gen_rtx_MEM (BLKmode, memory_address (BLKmode, addr));
+	    set_mem_align (stack_area, PARM_BOUNDARY);
 	    save_area = assign_stack_temp (BLKmode, num_to_save);
 	    emit_block_move (validize_mem (save_area), stack_area,
 			     GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
 	  }
 	else
 	  {
-	    save_area = gen_reg_rtx (save_mode);
+	    stack_area = gen_rtx_MEM (*save_mode,
+				      memory_address (*save_mode, addr));
+	    set_mem_align (stack_area, PARM_BOUNDARY);
+	    save_area = gen_reg_rtx (*save_mode);
 	    emit_move_insn (save_area, stack_area);
 	  }
 
diff --git a/gcc/combine.c b/gcc/combine.c
index e8e0b3f..ed4f755 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7283,19 +7283,16 @@ expand_field_assignment (const_rtx x)
       /* Don't attempt bitwise arithmetic on non scalar integer modes.  */
       if (! SCALAR_INT_MODE_P (compute_mode))
 	{
-	  machine_mode imode;
-
 	  /* Don't do anything for vector or complex integral types.  */
 	  if (! FLOAT_MODE_P (compute_mode))
 	    break;
 
 	  /* Try to find an integral mode to pun with.  */
-	  imode = mode_for_size (GET_MODE_BITSIZE (compute_mode), MODE_INT, 0);
-	  if (imode == BLKmode)
+	  if (!int_mode_for_size (GET_MODE_BITSIZE (compute_mode), 0)
+	      .exists (&compute_mode))
 	    break;
 
-	  compute_mode = imode;
-	  inner = gen_lowpart (imode, inner);
+	  inner = gen_lowpart (compute_mode, inner);
 	}
 
       /* Compute a mask of LEN bits, if we can do this on the host machine.  */
@@ -7366,7 +7363,6 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   machine_mode wanted_inner_reg_mode = word_mode;
   machine_mode pos_mode = word_mode;
   machine_mode extraction_mode = word_mode;
-  machine_mode tmode = mode_for_size (len, MODE_INT, 1);
   rtx new_rtx = 0;
   rtx orig_pos_rtx = pos_rtx;
   HOST_WIDE_INT orig_pos;
@@ -7414,7 +7410,8 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
      For MEM, we can avoid an extract if the field starts on an appropriate
      boundary and we can change the mode of the memory reference.  */
 
-  if (tmode != BLKmode
+  scalar_int_mode tmode;
+  if (int_mode_for_size (len, 1).exists (&tmode)
       && ((pos_rtx == 0 && (pos % BITS_PER_WORD) == 0
 	   && !MEM_P (inner)
 	   && (pos == 0 || REG_P (inner))
@@ -10418,8 +10415,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	      && ! mode_dependent_address_p (XEXP (varop, 0),
 					     MEM_ADDR_SPACE (varop))
 	      && ! MEM_VOLATILE_P (varop)
-	      && (tmode = mode_for_size (GET_MODE_BITSIZE (mode) - count,
-					 MODE_INT, 1)) != BLKmode)
+	      && (int_mode_for_size (GET_MODE_BITSIZE (mode) - count, 1)
+		  .exists (&tmode)))
 	    {
 	      new_rtx = adjust_address_nv (varop, tmode,
 				       BYTES_BIG_ENDIAN ? 0
@@ -12334,7 +12331,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 				   & GET_MODE_MASK (mode))
 				  + 1)) >= 0
 	      && const_op >> i == 0
-	      && (tmode = mode_for_size (i, MODE_INT, 1)) != BLKmode)
+	      && int_mode_for_size (i, 1).exists (&tmode))
 	    {
 	      op0 = gen_lowpart_or_truncate (tmode, XEXP (op0, 0));
 	      continue;
@@ -12494,8 +12491,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	      && CONST_INT_P (XEXP (op0, 1))
 	      && GET_CODE (XEXP (op0, 0)) == ASHIFT
 	      && XEXP (op0, 1) == XEXP (XEXP (op0, 0), 1)
-	      && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
-					 MODE_INT, 1)) != BLKmode
+	      && (int_mode_for_size (mode_width - INTVAL (XEXP (op0, 1)), 1)
+		  .exists (&tmode))
 	      && (((unsigned HOST_WIDE_INT) const_op
 		   + (GET_MODE_MASK (tmode) >> 1) + 1)
 		  <= GET_MODE_MASK (tmode)))
@@ -12513,8 +12510,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	      && CONST_INT_P (XEXP (XEXP (op0, 0), 1))
 	      && GET_CODE (XEXP (XEXP (op0, 0), 0)) == ASHIFT
 	      && XEXP (op0, 1) == XEXP (XEXP (XEXP (op0, 0), 0), 1)
-	      && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
-					 MODE_INT, 1)) != BLKmode
+	      && (int_mode_for_size (mode_width - INTVAL (XEXP (op0, 1)), 1)
+		  .exists (&tmode))
 	      && (((unsigned HOST_WIDE_INT) const_op
 		   + (GET_MODE_MASK (tmode) >> 1) + 1)
 		  <= GET_MODE_MASK (tmode)))
diff --git a/gcc/dojump.c b/gcc/dojump.c
index e6ddf78..1195599 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -598,7 +598,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
           && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
           && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
           && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
-          && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
+	  && int_mode_for_size (i + 1, 0).exists (&mode)
           && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
           && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
           && have_insn_for (COMPARE, TYPE_MODE (type)))
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5130b64..568100d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15048,13 +15048,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	      || GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT))
 	{
 	  dw_die_ref type_die = base_type_for_mode (mode, 1);
-	  machine_mode amode;
+	  scalar_int_mode amode;
 	  if (type_die == NULL)
 	    return NULL;
-	  amode = mode_for_size (DWARF2_ADDR_SIZE * BITS_PER_UNIT,
-				 MODE_INT, 0);
 	  if (INTVAL (rtl) >= 0
-	      && amode != BLKmode
+	      && (int_mode_for_size (DWARF2_ADDR_SIZE * BITS_PER_UNIT, 0)
+		  .exists (&amode))
 	      && trunc_int_for_mode (INTVAL (rtl), amode) == INTVAL (rtl)
 	      /* const DW_OP_convert <XXX> vs.
 		 DW_OP_const_type <XXX, 1, const>.  */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index b9d87d3..569a478 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -5854,8 +5854,7 @@ init_derived_machine_modes (void)
 
   byte_mode = *opt_byte_mode;
   word_mode = *opt_word_mode;
-  ptr_mode = as_a <scalar_int_mode> (mode_for_size (POINTER_SIZE,
-						    MODE_INT, 0));
+  ptr_mode = *int_mode_for_size (POINTER_SIZE, 0);
 }
 
 /* Create some permanent unique rtl objects shared between all functions.  */
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 737588b..fea62e6 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -363,7 +363,7 @@ check_reverse_float_storage_order_support (void)
 rtx
 flip_storage_order (machine_mode mode, rtx x)
 {
-  machine_mode int_mode;
+  scalar_int_mode int_mode;
   rtx result;
 
   if (mode == QImode)
@@ -383,16 +383,13 @@ flip_storage_order (machine_mode mode, rtx x)
   if (__builtin_expect (reverse_storage_order_supported < 0, 0))
     check_reverse_storage_order_support ();
 
-  if (SCALAR_INT_MODE_P (mode))
-    int_mode = mode;
-  else
+  if (!is_a <scalar_int_mode> (mode, &int_mode))
     {
       if (FLOAT_MODE_P (mode)
 	  && __builtin_expect (reverse_float_storage_order_supported < 0, 0))
 	check_reverse_float_storage_order_support ();
 
-      int_mode = mode_for_size (GET_MODE_PRECISION (mode), MODE_INT, 0);
-      if (int_mode == BLKmode)
+      if (!int_mode_for_size (GET_MODE_PRECISION (mode), 0).exists (&int_mode))
 	{
 	  sorry ("reverse storage order for %smode", GET_MODE_NAME (mode));
 	  return x;
@@ -1422,11 +1419,10 @@ convert_extracted_bit_field (rtx x, machine_mode mode,
      value via a SUBREG.  */
   if (!SCALAR_INT_MODE_P (tmode))
     {
-      machine_mode smode;
-
-      smode = mode_for_size (GET_MODE_BITSIZE (tmode), MODE_INT, 0);
-      x = convert_to_mode (smode, x, unsignedp);
-      x = force_reg (smode, x);
+      scalar_int_mode int_mode
+	= *int_mode_for_size (GET_MODE_BITSIZE (tmode), 0);
+      x = convert_to_mode (int_mode, x, unsignedp);
+      x = force_reg (int_mode, x);
       return gen_lowpart (tmode, x);
     }
 
diff --git a/gcc/expr.c b/gcc/expr.c
index d277a88..19b982c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2664,9 +2664,9 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
   copy_mode = word_mode;
   if (MEM_P (target))
     {
-      machine_mode mem_mode = mode_for_size (bitsize, MODE_INT, 1);
-      if (mem_mode != BLKmode)
-	copy_mode = mem_mode;
+      opt_scalar_int_mode mem_mode = int_mode_for_size (bitsize, 1);
+      if (mem_mode.exists ())
+	copy_mode = *mem_mode;
     }
   else if (REG_P (target) && GET_MODE_BITSIZE (tmode) < BITS_PER_WORD)
     copy_mode = tmode;
diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c
index 209eada..0ceba85 100644
--- a/gcc/graphite-isl-ast-to-gimple.c
+++ b/gcc/graphite-isl-ast-to-gimple.c
@@ -61,7 +61,7 @@ along with GCC; see the file COPYING3.  If not see
    should use isl to derive the optimal type for each subexpression.  */
 
 static int max_mode_int_precision =
-  GET_MODE_PRECISION (mode_for_size (MAX_FIXED_MODE_SIZE, MODE_INT, 0));
+  GET_MODE_PRECISION (*int_mode_for_size (MAX_FIXED_MODE_SIZE, 0));
 static int graphite_expression_type_precision = 128 <= max_mode_int_precision ?
 						128 : max_mode_int_precision;
 
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 3dbd2a1..cdcbaa4 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -1467,7 +1467,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
     {
       struct separate_ops ops;
       int prec = GET_MODE_PRECISION (mode);
-      machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
+      scalar_int_mode hmode;
       machine_mode wmode;
       ops.op0 = make_tree (type, op0);
       ops.op1 = make_tree (type, op1);
@@ -1503,7 +1503,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
 				       PROB_VERY_LIKELY);
 	    }
 	}
-      else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
+      else if (int_mode_for_size (prec / 2, 1).exists (&hmode)
+	       && 2 * GET_MODE_PRECISION (hmode) == prec)
 	{
 	  rtx_code_label *large_op0 = gen_label_rtx ();
 	  rtx_code_label *small_op0_large_op1 = gen_label_rtx ();
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index d378542..520eed1 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -349,8 +349,7 @@ simple_move (rtx_insn *insn, bool speed_p)
      size.  */
   mode = GET_MODE (SET_DEST (set));
   if (!SCALAR_INT_MODE_P (mode)
-      && (mode_for_size (GET_MODE_SIZE (mode) * BITS_PER_UNIT, MODE_INT, 0)
-	  == BLKmode))
+      && !int_mode_for_size (GET_MODE_BITSIZE (mode), 0).exists ())
     return NULL_RTX;
 
   /* Reject PARTIAL_INT modes.  They are used for processor specific
diff --git a/gcc/machmode.h b/gcc/machmode.h
index bf568c9..db011d3 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -558,6 +558,16 @@ extern const unsigned char mode_complex[NUM_MACHINE_MODES];
 
 extern machine_mode mode_for_size (unsigned int, enum mode_class, int);
 
+/* Return the machine mode to use for a MODE_INT of SIZE bits, if one
+   exists.  If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
+   will not be used.  */
+
+inline opt_scalar_int_mode
+int_mode_for_size (unsigned int size, int limit)
+{
+  return dyn_cast <scalar_int_mode> (mode_for_size (size, MODE_INT, limit));
+}
+
 /* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one
    exists.  */
 
diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
index 75fd677..a26577e 100644
--- a/gcc/optabs-libfuncs.c
+++ b/gcc/optabs-libfuncs.c
@@ -858,8 +858,10 @@ init_optabs (void)
   /* The ffs function operates on `int'.  Fall back on it if we do not
      have a libgcc2 function for that width.  */
   if (INT_TYPE_SIZE < BITS_PER_WORD)
-    set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
-		       "ffs");
+    {
+      scalar_int_mode mode = *int_mode_for_size (INT_TYPE_SIZE, 0);
+      set_optab_libfunc (ffs_optab, mode, "ffs");
+    }
 
   /* Explicitly initialize the bswap libfuncs since we need them to be
      valid for things other than word_mode.  */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 907c1e7..a1387b1 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1482,12 +1482,11 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
 	  && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
 	{
-	  machine_mode tmode
-	    = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
-			     - INTVAL (XEXP (op, 1)), MODE_INT, 1);
+	  scalar_int_mode tmode;
 	  gcc_assert (GET_MODE_BITSIZE (mode)
 		      > GET_MODE_BITSIZE (GET_MODE (op)));
-	  if (tmode != BLKmode)
+	  if (int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
+				 - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
 	    {
 	      rtx inner =
 		rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
@@ -1599,10 +1598,9 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
 	  && GET_MODE_PRECISION (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
 	{
-	  machine_mode tmode
-	    = mode_for_size (GET_MODE_PRECISION (GET_MODE (op))
-			     - INTVAL (XEXP (op, 1)), MODE_INT, 1);
-	  if (tmode != BLKmode)
+	  scalar_int_mode tmode;
+	  if (int_mode_for_size (GET_MODE_PRECISION (GET_MODE (op))
+				 - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
 	    {
 	      rtx inner =
 		rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 2cde94e..49cce57 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2444,10 +2444,11 @@ vector_type_mode (const_tree t)
       /* For integers, try mapping it to a same-sized scalar mode.  */
       if (GET_MODE_CLASS (innermode) == MODE_INT)
 	{
-	  mode = mode_for_size (TYPE_VECTOR_SUBPARTS (t)
-				* GET_MODE_BITSIZE (innermode), MODE_INT, 0);
-
-	  if (mode != VOIDmode && have_regs_of_mode[mode])
+	  unsigned int size = (TYPE_VECTOR_SUBPARTS (t)
+			       * GET_MODE_BITSIZE (innermode));
+	  scalar_int_mode mode;
+	  if (int_mode_for_size (size, 0).exists (&mode)
+	      && have_regs_of_mode[mode])
 	    return mode;
 	}
 
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 339812e..a596005 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1989,8 +1989,8 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
       unsigned align1 = get_pointer_alignment (arg1);
       unsigned align2 = get_pointer_alignment (arg2);
       unsigned align = MIN (align1, align2);
-      machine_mode mode = mode_for_size (leni, MODE_INT, 1);
-      if (mode != BLKmode
+      scalar_int_mode mode;
+      if (int_mode_for_size (leni, 1).exists (&mode)
 	  && (align >= leni || !SLOW_UNALIGNED_ACCESS (mode, align)))
 	{
 	  location_t loc = gimple_location (stmt2);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 5a30314..2d94d2c 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -58,15 +58,14 @@ static bool
 vect_lanes_optab_supported_p (const char *name, convert_optab optab,
 			      tree vectype, unsigned HOST_WIDE_INT count)
 {
-  machine_mode mode, array_mode;
+  machine_mode mode;
+  scalar_int_mode array_mode;
   bool limit_p;
 
   mode = TYPE_MODE (vectype);
   limit_p = !targetm.array_mode_supported_p (mode, count);
-  array_mode = mode_for_size (count * GET_MODE_BITSIZE (mode),
-			      MODE_INT, limit_p);
-
-  if (array_mode == BLKmode)
+  if (!int_mode_for_size (count * GET_MODE_BITSIZE (mode),
+			  limit_p).exists (&array_mode))
     {
       if (dump_enabled_p ())
 	dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 91c5f93..4453e48 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -288,7 +288,6 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
 			enum tree_code code)
 {
   tree result, compute_type;
-  machine_mode mode;
   int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
   location_t loc = gimple_location (gsi_stmt (*gsi));
 
@@ -312,7 +311,8 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
   else
     {
       /* Use a single scalar operation with a mode no wider than word_mode.  */
-      mode = mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), MODE_INT, 0);
+      scalar_int_mode mode
+	= *int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0);
       compute_type = lang_hooks.types.type_for_mode (mode, 1);
       result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
       warning_at (loc, OPT_Wvector_operation_performance,
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 787ecea..1690cec 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6992,7 +6992,7 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
 		 to a larger load.  */
 	      unsigned lsize
 		= group_size * TYPE_PRECISION (TREE_TYPE (vectype));
-	      machine_mode elmode = mode_for_size (lsize, MODE_INT, 0);
+	      scalar_int_mode elmode = *int_mode_for_size (lsize, 0);
 	      machine_mode vmode = mode_for_vector (elmode,
 						    nunits / group_size);
 	      /* If we can't construct such a vector fall back to

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [18/67] Make int_mode_for_mode return an opt_scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (18 preceding siblings ...)
  2016-12-09 13:05 ` [19/67] Add a smallest_int_mode_for_size " Richard Sandiford
@ 2016-12-09 13:05 ` Richard Sandiford
  2016-12-09 13:06 ` [20/67] Replace MODE_INT checks with is_int_mode Richard Sandiford
                   ` (49 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:05 UTC (permalink / raw)
  To: gcc-patches

Also use int_mode_for_mode instead of (int_)mode_for_size
in cases where the requested size was the bitsize of an
existing mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

	* machmode.h (opt_mode::else_blk): New function.
	(int_mode_for_mode): Declare.
	* stor-layout.c (int_mode_for_mode): Return an opt_scalar_int_mode.
	* builtins.c (expand_builtin_signbit): Adjust for new int_mode_for_mode
	return type.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* combine.c (gen_lowpart_or_truncate): Likewise.
	(gen_lowpart_for_combine): Likewise.
	* config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Likewise.
	* config/avr/avr.c (avr_to_int_mode): Likewise.
	(avr_out_plus_1): Likewise.
	(avr_out_plus): Likewise.
	(avr_out_round): Likewise.
	* config/i386/i386.c (ix86_split_to_parts): Likewise.
	* config/spu/spu.c (spu_split_immediate): Likewise.
	(spu_expand_mov): Likewise.
	* dse.c (get_stored_val): Likewise.
	* expmed.c (store_bit_field_1): Likewise.
	(convert_extracted_bit_field): Use int_mode_for_mode instead of
	int_mode_for_size.
	(extract_bit_field_1): Adjust for new int_mode_for_mode return type.
	(extract_low_bits): Likewise.
	* expr.c (emit_group_load_1): Likewise.  Separate out the BLKmode
	handling rather than repeating the check.
	(emit_group_store): Likewise.
	(emit_move_via_integer): Adjust for new int_mode_for_mode return type.
	* optabs.c (expand_absneg_bit): Likewise.
	(expand_copysign_absneg): Likewise.
	(expand_copysign_bit): Likewise.
	* tree-if-conv.c (ifcvt_can_use_mask_load_store): Likewise.
	* tree-vect-slp.c (vect_transform_slp_perm_load): Likewise.
	* tree-vect-stmts.c (vect_gen_perm_mask_any): Likewise.
	* var-tracking.c (prepare_call_arguments):  Likewise.
	* config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Use
	int_mode_for_mode instead of mode_for_size.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 655ae27..00a0a73 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5258,8 +5258,7 @@ expand_builtin_signbit (tree exp, rtx target)
 
   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (fmode);
-      gcc_assert (imode != BLKmode);
+      imode = *int_mode_for_mode (fmode);
       temp = gen_lowpart (imode, temp);
     }
   else
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 97dc648..3915c97 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4827,10 +4827,11 @@ expand_debug_expr (tree exp)
 	    }
 	  else
 	    {
-	      machine_mode ifmode = int_mode_for_mode (mode);
-	      machine_mode ihmode = int_mode_for_mode (imode);
+	      scalar_int_mode ifmode;
+	      scalar_int_mode ihmode;
 	      rtx halfsize;
-	      if (ifmode == BLKmode || ihmode == BLKmode)
+	      if (!int_mode_for_mode (mode).exists (&ifmode)
+		  || !int_mode_for_mode (imode).exists (&ihmode))
 		return NULL;
 	      halfsize = GEN_INT (GET_MODE_BITSIZE (ihmode));
 	      re = op0;
diff --git a/gcc/combine.c b/gcc/combine.c
index ed4f755..573c558 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8416,8 +8416,8 @@ gen_lowpart_or_truncate (machine_mode mode, rtx x)
     {
       /* Bit-cast X into an integer mode.  */
       if (!SCALAR_INT_MODE_P (GET_MODE (x)))
-	x = gen_lowpart (int_mode_for_mode (GET_MODE (x)), x);
-      x = simplify_gen_unary (TRUNCATE, int_mode_for_mode (mode),
+	x = gen_lowpart (*int_mode_for_mode (GET_MODE (x)), x);
+      x = simplify_gen_unary (TRUNCATE, *int_mode_for_mode (mode),
 			      x, GET_MODE (x));
     }
 
@@ -11459,7 +11459,7 @@ gen_lowpart_for_combine (machine_mode omode, rtx x)
 
       if (imode == VOIDmode)
 	{
-	  imode = int_mode_for_mode (omode);
+	  imode = *int_mode_for_mode (omode);
 	  x = gen_lowpart_common (imode, x);
 	  if (x == NULL)
 	    goto fail;
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index f399514..fc2bcad 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -7867,7 +7867,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp)
     return false;
 
   machine_mode mmsk = mode_for_vector
-		        (int_mode_for_mode (GET_MODE_INNER (mode)),
+			(*int_mode_for_mode (GET_MODE_INNER (mode)),
 			 GET_MODE_NUNITS (mode));
   bool use_approx_sqrt_p = (!recp
 			    && (flag_mlow_precision_sqrt
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 732e030..e3a611f 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -279,7 +279,7 @@ avr_to_int_mode (rtx x)
 
   return VOIDmode == mode
     ? x
-    : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
+    : simplify_gen_subreg (*int_mode_for_mode (mode), x, mode, 0);
 }
 
 namespace {
@@ -7485,7 +7485,7 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
   machine_mode mode = GET_MODE (xop[0]);
 
   /* INT_MODE of the same size.  */
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
 
   /* Number of bytes to operate on.  */
   int n_bytes = GET_MODE_SIZE (mode);
@@ -7988,7 +7988,7 @@ avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
   rtx xdest = SET_DEST (xpattern);
   machine_mode mode = GET_MODE (xdest);
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
   int n_bytes = GET_MODE_SIZE (mode);
   enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
   enum rtx_code code
@@ -8923,7 +8923,7 @@ const char*
 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
 {
   machine_mode mode = GET_MODE (xop[0]);
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
   // The smallest fractional bit not cleared by the rounding is 2^(-RP).
   int fbit = (int) GET_MODE_FBIT (mode);
   double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0c58dae..0fbb3ed 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -25267,7 +25267,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
 
   if (GET_CODE (operand) == CONST_VECTOR)
     {
-      machine_mode imode = int_mode_for_mode (mode);
+      scalar_int_mode imode = *int_mode_for_mode (mode);
       /* Caution: if we looked through a constant pool memory above,
 	 the operand may actually have a different mode now.  That's
 	 ok, since we want to pun this all the way back to an integer.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 08a069d..06aae77 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -37185,10 +37185,8 @@ rs6000_do_expand_vec_perm (rtx target, rtx op0, rtx op1,
 
   imode = vmode;
   if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
-    {
-      imode = mode_for_size (GET_MODE_UNIT_BITSIZE (vmode), MODE_INT, 0);
-      imode = mode_for_vector (imode, nelt);
-    }
+    imode = mode_for_vector (*int_mode_for_mode (GET_MODE_INNER (vmode)),
+			     nelt);
 
   x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
   x = expand_vec_perm (vmode, op0, op1, x, target);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 4fb6daf..e8fd572 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -1492,10 +1492,9 @@ spu_split_immediate (rtx * ops)
 	unsigned char arrlo[16];
 	rtx to, temp, hi, lo;
 	int i;
-	machine_mode imode = mode;
 	/* We need to do reals as ints because the constant used in the
 	   IOR might not be a legitimate real constant. */
-	imode = int_mode_for_mode (mode);
+	scalar_int_mode imode = *int_mode_for_mode (mode);
 	constant_to_array (mode, ops[1], arrhi);
 	if (imode != mode)
 	  to = simplify_gen_subreg (imode, ops[0], mode, 0);
@@ -1521,10 +1520,9 @@ spu_split_immediate (rtx * ops)
 	unsigned char arr_andbi[16];
 	rtx to, reg_fsmbi, reg_and;
 	int i;
-	machine_mode imode = mode;
 	/* We need to do reals as ints because the constant used in the
 	 * AND might not be a legitimate real constant. */
-	imode = int_mode_for_mode (mode);
+	scalar_int_mode imode = *int_mode_for_mode (mode);
 	constant_to_array (mode, ops[1], arr_fsmbi);
 	if (imode != mode)
 	  to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
@@ -4429,7 +4427,7 @@ spu_expand_mov (rtx * ops, machine_mode mode)
   if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
     {
       rtx from = SUBREG_REG (ops[1]);
-      machine_mode imode = int_mode_for_mode (GET_MODE (from));
+      scalar_int_mode imode = *int_mode_for_mode (GET_MODE (from));
 
       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
 		  && GET_MODE_CLASS (imode) == MODE_INT
diff --git a/gcc/dse.c b/gcc/dse.c
index ef7a5c8..c8e22a7 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1734,12 +1734,12 @@ get_stored_val (store_info *store_info, machine_mode read_mode,
     {
       /* The store is a memset (addr, const_val, const_size).  */
       gcc_assert (CONST_INT_P (store_info->rhs));
-      store_mode = int_mode_for_mode (read_mode);
-      if (store_mode == BLKmode)
+      scalar_int_mode int_store_mode;
+      if (!int_mode_for_mode (read_mode).exists (&int_store_mode))
 	read_reg = NULL_RTX;
       else if (store_info->rhs == const0_rtx)
-	read_reg = extract_low_bits (read_mode, store_mode, const0_rtx);
-      else if (GET_MODE_BITSIZE (store_mode) > HOST_BITS_PER_WIDE_INT
+	read_reg = extract_low_bits (read_mode, int_store_mode, const0_rtx);
+      else if (GET_MODE_BITSIZE (int_store_mode) > HOST_BITS_PER_WIDE_INT
 	       || BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT)
 	read_reg = NULL_RTX;
       else
@@ -1753,8 +1753,8 @@ get_stored_val (store_info *store_info, machine_mode read_mode,
 	      c |= (c << shift);
 	      shift <<= 1;
 	    }
-	  read_reg = gen_int_mode (c, store_mode);
-	  read_reg = extract_low_bits (read_mode, store_mode, read_reg);
+	  read_reg = gen_int_mode (c, int_store_mode);
+	  read_reg = extract_low_bits (read_mode, int_store_mode, read_reg);
 	}
     }
   else if (store_info->const_rhs
diff --git a/gcc/expmed.c b/gcc/expmed.c
index fea62e6..bc5df87 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -828,19 +828,15 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
      if we aren't.  This must come after the entire register case above,
      since that case is valid for any mode.  The following cases are only
      valid for integral modes.  */
-  {
-    machine_mode imode = int_mode_for_mode (GET_MODE (op0));
-    if (imode != GET_MODE (op0))
-      {
-	if (MEM_P (op0))
-	  op0 = adjust_bitfield_address_size (op0, imode, 0, MEM_SIZE (op0));
-	else
-	  {
-	    gcc_assert (imode != BLKmode);
-	    op0 = gen_lowpart (imode, op0);
-	  }
-      }
-  }
+  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
+  if (!imode.exists () || *imode != GET_MODE (op0))
+    {
+      if (MEM_P (op0))
+	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+					    0, MEM_SIZE (op0));
+      else
+	op0 = gen_lowpart (*imode, op0);
+    }
 
   /* Storing an lsb-aligned field in a register
      can be done with a movstrict instruction.  */
@@ -955,7 +951,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       && GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
       && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
     {
-      value = gen_reg_rtx (int_mode_for_mode (GET_MODE (value)));
+      value = gen_reg_rtx (*int_mode_for_mode (GET_MODE (value)));
       emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value);
     }
 
@@ -1419,8 +1415,7 @@ convert_extracted_bit_field (rtx x, machine_mode mode,
      value via a SUBREG.  */
   if (!SCALAR_INT_MODE_P (tmode))
     {
-      scalar_int_mode int_mode
-	= *int_mode_for_size (GET_MODE_BITSIZE (tmode), 0);
+      scalar_int_mode int_mode = *int_mode_for_mode (tmode);
       x = convert_to_mode (int_mode, x, unsignedp);
       x = force_reg (int_mode, x);
       return gen_lowpart (tmode, x);
@@ -1525,7 +1520,6 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 		     bool reverse, bool fallback_p)
 {
   rtx op0 = str_rtx;
-  machine_mode int_mode;
   machine_mode mode1;
 
   if (tmode == VOIDmode)
@@ -1611,30 +1605,29 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Make sure we are playing with integral modes.  Pun with subregs
      if we aren't.  */
-  {
-    machine_mode imode = int_mode_for_mode (GET_MODE (op0));
-    if (imode != GET_MODE (op0))
-      {
-	if (MEM_P (op0))
-	  op0 = adjust_bitfield_address_size (op0, imode, 0, MEM_SIZE (op0));
-	else if (imode != BLKmode)
-	  {
-	    op0 = gen_lowpart (imode, op0);
+  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
+  if (!imode.exists () || *imode != GET_MODE (op0))
+    {
+      if (MEM_P (op0))
+	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+					    0, MEM_SIZE (op0));
+      else if (imode.exists ())
+	{
+	  op0 = gen_lowpart (*imode, op0);
 
-	    /* If we got a SUBREG, force it into a register since we
-	       aren't going to be able to do another SUBREG on it.  */
-	    if (GET_CODE (op0) == SUBREG)
-	      op0 = force_reg (imode, op0);
-	  }
-	else
-	  {
-	    HOST_WIDE_INT size = GET_MODE_SIZE (GET_MODE (op0));
-	    rtx mem = assign_stack_temp (GET_MODE (op0), size);
-	    emit_move_insn (mem, op0);
-	    op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size);
-	  }
-      }
-  }
+	  /* If we got a SUBREG, force it into a register since we
+	     aren't going to be able to do another SUBREG on it.  */
+	  if (GET_CODE (op0) == SUBREG)
+	    op0 = force_reg (*imode, op0);
+	}
+      else
+	{
+	  HOST_WIDE_INT size = GET_MODE_SIZE (GET_MODE (op0));
+	  rtx mem = assign_stack_temp (GET_MODE (op0), size);
+	  emit_move_insn (mem, op0);
+	  op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size);
+	}
+    }
 
   /* ??? We currently assume TARGET is at least as big as BITSIZE.
      If that's wrong, the solution is to test for it and set TARGET to 0
@@ -1838,11 +1831,11 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Find a correspondingly-sized integer field, so we can apply
      shifts and masks to it.  */
-  int_mode = int_mode_for_mode (tmode);
-  if (int_mode == BLKmode)
-    int_mode = int_mode_for_mode (mode);
-  /* Should probably push op0 out to memory and then do a load.  */
-  gcc_assert (int_mode != BLKmode);
+  scalar_int_mode int_mode;
+  if (!int_mode_for_mode (tmode).exists (&int_mode))
+    /* If this fails, we should probably push op0 out to memory and then
+       do a load.  */
+    int_mode = *int_mode_for_mode (mode);
 
   target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
 				    unsignedp, reverse);
@@ -2196,9 +2189,8 @@ extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src)
         return x;
     }
 
-  src_int_mode = int_mode_for_mode (src_mode);
-  int_mode = int_mode_for_mode (mode);
-  if (src_int_mode == BLKmode || int_mode == BLKmode)
+  if (!int_mode_for_mode (src_mode).exists (&src_int_mode)
+      || !int_mode_for_mode (mode).exists (&int_mode))
     return NULL_RTX;
 
   if (!MODES_TIEABLE_P (src_int_mode, src_mode))
diff --git a/gcc/expr.c b/gcc/expr.c
index 19b982c..8141016 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2089,17 +2089,17 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
       && !MEM_P (orig_src)
       && GET_CODE (orig_src) != CONCAT)
     {
-      machine_mode imode = int_mode_for_mode (GET_MODE (orig_src));
-      if (imode == BLKmode)
-	src = assign_stack_temp (GET_MODE (orig_src), ssize);
+      scalar_int_mode imode;
+      if (int_mode_for_mode (GET_MODE (orig_src)).exists (&imode))
+	{
+	  src = gen_reg_rtx (imode);
+	  emit_move_insn (gen_lowpart (GET_MODE (orig_src), src), orig_src);
+	}
       else
-	src = gen_reg_rtx (imode);
-      if (imode != BLKmode)
-	src = gen_lowpart (GET_MODE (orig_src), src);
-      emit_move_insn (src, orig_src);
-      /* ...and back again.  */
-      if (imode != BLKmode)
-	src = gen_lowpart (imode, src);
+	{
+	  src = assign_stack_temp (GET_MODE (orig_src), ssize);
+	  emit_move_insn (src, orig_src);
+	}
       emit_group_load_1 (tmps, dst, src, type, ssize);
       return;
     }
@@ -2361,14 +2361,18 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
   if (!SCALAR_INT_MODE_P (m)
       && !MEM_P (orig_dst) && GET_CODE (orig_dst) != CONCAT)
     {
-      machine_mode imode = int_mode_for_mode (GET_MODE (orig_dst));
-      if (imode == BLKmode)
-        dst = assign_stack_temp (GET_MODE (orig_dst), ssize);
+      scalar_int_mode imode;
+      if (int_mode_for_mode (GET_MODE (orig_dst)).exists (&imode))
+	{
+	  dst = gen_reg_rtx (imode);
+	  emit_group_store (dst, src, type, ssize);
+	  dst = gen_lowpart (GET_MODE (orig_dst), dst);
+	}
       else
-        dst = gen_reg_rtx (imode);
-      emit_group_store (dst, src, type, ssize);
-      if (imode != BLKmode)
-        dst = gen_lowpart (GET_MODE (orig_dst), dst);
+	{
+	  dst = assign_stack_temp (GET_MODE (orig_dst), ssize);
+	  emit_group_store (dst, src, type, ssize);
+	}
       emit_move_insn (orig_dst, dst);
       return;
     }
@@ -3276,12 +3280,11 @@ emit_move_change_mode (machine_mode new_mode,
 static rtx_insn *
 emit_move_via_integer (machine_mode mode, rtx x, rtx y, bool force)
 {
-  machine_mode imode;
+  scalar_int_mode imode;
   enum insn_code code;
 
   /* There must exist a mode of the exact size we require.  */
-  imode = int_mode_for_mode (mode);
-  if (imode == BLKmode)
+  if (!int_mode_for_mode (mode).exists (&imode))
     return NULL;
 
   /* The target must support moves in this mode.  */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index db011d3..f1519a8 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -202,6 +202,7 @@ public:
   ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
   ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
   machine_mode_enum else_void () const;
+  machine_mode_enum else_blk () const;
   T operator * () const;
 
   /* Return true if the object contains a T rather than nothing.  */
@@ -222,6 +223,15 @@ opt_mode<T>::else_void () const
   return m_mode;
 }
 
+/* If the T exists, return its enum value, otherwise return E_BLKmode.  */
+
+template<typename T>
+inline machine_mode_enum
+opt_mode<T>::else_blk () const
+{
+  return m_mode == E_VOIDmode ? E_BLKmode : m_mode;
+}
+
 /* Assert that the object contains a T and return it.  */
 
 template<typename T>
@@ -583,10 +593,9 @@ extern machine_mode smallest_mode_for_size (unsigned int,
 						 enum mode_class);
 
 
-/* Return an integer mode of the exact same size as the input mode,
-   or BLKmode on failure.  */
+/* Return an integer mode of exactly the same size as the input mode.  */
 
-extern machine_mode int_mode_for_mode (machine_mode);
+extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
 
 extern machine_mode bitwise_mode_for_mode (machine_mode);
 
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 58c26e4..b2c8006 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2574,8 +2574,7 @@ expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
 
   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (mode);
-      if (imode == BLKmode)
+      if (!int_mode_for_mode (mode).exists (&imode))
 	return NULL_RTX;
       word = 0;
       nwords = 1;
@@ -3267,8 +3266,7 @@ expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
     {
       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
 	{
-	  imode = int_mode_for_mode (mode);
-	  if (imode == BLKmode)
+	  if (!int_mode_for_mode (mode).exists (&imode))
 	    return NULL_RTX;
 	  op1 = gen_lowpart (imode, op1);
 	}
@@ -3330,15 +3328,14 @@ static rtx
 expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
 		     int bitpos, bool op0_is_abs)
 {
-  machine_mode imode;
+  scalar_int_mode imode;
   int word, nwords, i;
   rtx temp;
   rtx_insn *insns;
 
   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (mode);
-      if (imode == BLKmode)
+      if (!int_mode_for_mode (mode).exists (&imode))
 	return NULL_RTX;
       word = 0;
       nwords = 1;
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 49cce57..6337764 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -364,16 +364,16 @@ smallest_mode_for_size (unsigned int size, enum mode_class mclass)
   return mode;
 }
 
-/* Find an integer mode of the exact same size, or BLKmode on failure.  */
+/* Return an integer mode of exactly the same size as MODE, if one exists.  */
 
-machine_mode
+opt_scalar_int_mode
 int_mode_for_mode (machine_mode mode)
 {
   switch (GET_MODE_CLASS (mode))
     {
     case MODE_INT:
     case MODE_PARTIAL_INT:
-      break;
+      return as_a <scalar_int_mode> (mode);
 
     case MODE_COMPLEX_INT:
     case MODE_COMPLEX_FLOAT:
@@ -390,12 +390,11 @@ int_mode_for_mode (machine_mode mode)
     case MODE_VECTOR_UFRACT:
     case MODE_VECTOR_UACCUM:
     case MODE_POINTER_BOUNDS:
-      mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
-      break;
+      return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
 
     case MODE_RANDOM:
       if (mode == BLKmode)
-	break;
+	return opt_scalar_int_mode ();
 
       /* fall through */
 
@@ -403,8 +402,6 @@ int_mode_for_mode (machine_mode mode)
     default:
       gcc_unreachable ();
     }
-
-  return mode;
 }
 
 /* Find a mode that can be used for efficient bitwise operations on MODE.
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 5716deb..ed6a8b7 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -933,8 +933,7 @@ ifcvt_can_use_mask_load_store (gimple *stmt)
   /* Mask should be integer mode of the same size as the load/store
      mode.  */
   mode = TYPE_MODE (TREE_TYPE (lhs));
-  if (int_mode_for_mode (mode) == BLKmode
-      || VECTOR_MODE_P (mode))
+  if (!int_mode_for_mode (mode).exists () || VECTOR_MODE_P (mode))
     return false;
 
   if (can_vec_mask_load_store_p (mode, VOIDmode, is_load))
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 8d54768..de5c2c0 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3471,7 +3471,7 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
   /* The generic VEC_PERM_EXPR code always uses an integral type of the
      same size as the vector element being permuted.  */
   mask_element_type = lang_hooks.types.type_for_mode
-		(int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
+		(*int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
   mask_type = get_vectype_for_scalar_type (mask_element_type);
   nunits = TYPE_VECTOR_SUBPARTS (vectype);
   mask = XALLOCAVEC (unsigned char, nunits);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 1690cec..d6b281d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6417,7 +6417,7 @@ vect_gen_perm_mask_any (tree vectype, const unsigned char *sel)
   nunits = TYPE_VECTOR_SUBPARTS (vectype);
 
   mask_elt_type = lang_hooks.types.type_for_mode
-		    (int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
+		    (*int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
   mask_type = get_vectype_for_scalar_type (mask_elt_type);
 
   mask_elts = XALLOCAVEC (tree, nunits);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index cd29dc6..a187794 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -6347,8 +6347,9 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
 	      {
 		/* For non-integer stack argument see also if they weren't
 		   initialized by integers.  */
-		machine_mode imode = int_mode_for_mode (GET_MODE (mem));
-		if (imode != GET_MODE (mem) && imode != BLKmode)
+		scalar_int_mode imode;
+		if (int_mode_for_mode (GET_MODE (mem)).exists (&imode)
+		    && imode != GET_MODE (mem))
 		  {
 		    val = cselib_lookup (adjust_address_nv (mem, imode, 0),
 					 imode, 0, VOIDmode);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [19/67] Add a smallest_int_mode_for_size helper function
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (17 preceding siblings ...)
  2016-12-09 13:04 ` [17/67] Add an int_mode_for_size helper function Richard Sandiford
@ 2016-12-09 13:05 ` Richard Sandiford
  2016-12-09 13:05 ` [18/67] Make int_mode_for_mode return an opt_scalar_int_mode Richard Sandiford
                   ` (50 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:05 UTC (permalink / raw)
  To: gcc-patches

This patch adds a wrapper around smallest_mode_for_size
for cases in which the mode class is MODE_INT.  Unlike
(int_)mode_for_size, smallest_mode_for_size always returns
a mode of the specified class, asserting if no such mode exists.
smallest_int_mode_for_size therefore returns a scalar_int_mode
rather than an opt_scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (smallest_mode_for_size): Fix formatting.
	(smallest_int_mode_for_size): New function.
	* cfgexpand.c (expand_debug_expr): Use smallest_int_mode_for_size
	instead of smallest_mopde_for_size.
	* combine.c (make_extraction): Likewise.
	* config/arc/arc.c (arc_expand_movmem): Likewise.
	* config/i386/i386.c (ix86_get_mask_mode): Likewise.
	* config/i386/i386.md (define_split): Likewise.
	* config/s390/s390.c (s390_expand_insv): Likewise.
	* config/sparc/sparc.c (assign_int_registers): Likewise.
	* config/spu/spu.c (spu_function_value): Likewise.
	(spu_function_arg): Likewise.
	* coverage.c (get_gcov_type): Likewise.
	(get_gcov_unsigned_t): Likewise.
	* dse.c (find_shift_sequence): Likewise.
	* expr.c (convert_move): Likewise.
	(store_field): Likewise.
	* internal-fn.c (expand_arith_overflow): Likewise.
	* optabs-query.c (get_best_extraction_insn): Likewise.
	* optabs.c (expand_twoval_binop_libfunc): Likewise.
	* stor-layout.c (layout_type): Likewise.
	(initialize_sizetypes): Likewise.
	* targhooks.c (default_get_mask_mode): Likewise.
	* tree-ssa-loop-manip.c (canonicalize_loop_ivs): Likewise.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 3915c97..b531996 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4486,7 +4486,7 @@ expand_debug_expr (tree exp)
 	  {
 	    if (mode1 == VOIDmode)
 	      /* Bitfield.  */
-	      mode1 = smallest_mode_for_size (bitsize, MODE_INT);
+	      mode1 = smallest_int_mode_for_size (bitsize);
 	    if (bitpos >= BITS_PER_UNIT)
 	      {
 		op0 = adjust_address_nv (op0, mode1, bitpos / BITS_PER_UNIT);
diff --git a/gcc/combine.c b/gcc/combine.c
index 573c558..29b849a 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7586,7 +7586,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
     {
       /* Be careful not to go beyond the extracted object and maintain the
 	 natural alignment of the memory.  */
-      wanted_inner_mode = smallest_mode_for_size (len, MODE_INT);
+      wanted_inner_mode = smallest_int_mode_for_size (len);
       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);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 2b25a37..bc5c031 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -7621,7 +7621,7 @@ arc_expand_movmem (rtx *operands)
 
       while (piece > size)
 	piece >>= 1;
-      mode = smallest_mode_for_size (piece * BITS_PER_UNIT, MODE_INT);
+      mode = smallest_int_mode_for_size (piece * BITS_PER_UNIT);
       /* If we don't re-use temporaries, the scheduler gets carried away,
 	 and the register pressure gets unnecessarily high.  */
       if (0 && tmpx[i] && GET_MODE (tmpx[i]) == mode)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0fbb3ed..4d74bc4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -50331,11 +50331,11 @@ ix86_get_mask_mode (unsigned nunits, unsigned vector_size)
       || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
     {
       if (elem_size == 4 || elem_size == 8 || TARGET_AVX512BW)
-	return smallest_mode_for_size (nunits, MODE_INT);
+	return smallest_int_mode_for_size (nunits);
     }
 
-  machine_mode elem_mode
-    = smallest_mode_for_size (elem_size * BITS_PER_UNIT, MODE_INT);
+  scalar_int_mode elem_mode
+    = smallest_int_mode_for_size (elem_size * BITS_PER_UNIT);
 
   gcc_assert (elem_size * nunits == vector_size);
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index f2248a5..1433cbf 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -7936,7 +7936,7 @@
 	 no matter the size of the test.  So find a mode that works.  */
       if (! MEM_VOLATILE_P (val))
 	{
-	  mode = smallest_mode_for_size (pos + len, MODE_INT);
+	  mode = smallest_int_mode_for_size (pos + len);
 	  val = adjust_address (val, mode, 0);
 	}
     }
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index a3bb952..510c24c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6093,7 +6093,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
       return true;
     }
 
-  smode = smallest_mode_for_size (bitsize, MODE_INT);
+  smode = smallest_int_mode_for_size (bitsize);
   smode_bsize = GET_MODE_BITSIZE (smode);
   mode_bsize = GET_MODE_BITSIZE (mode);
 
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 995b0af..28bb0c5 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -6626,8 +6626,8 @@ assign_int_registers (HOST_WIDE_INT bitpos, assign_data_t *data)
      the latter case we may pick up unwanted bits.  It's not a problem
      at the moment but may wish to revisit.  */
   if (intoffset % BITS_PER_WORD != 0)
-    mode = smallest_mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
-			  	   MODE_INT);
+    mode = smallest_int_mode_for_size (BITS_PER_WORD
+				       - intoffset % BITS_PER_WORD);
   else
     mode = word_mode;
 
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index e8fd572..ea449e0 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -3808,8 +3808,7 @@ spu_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
 	{
 	  if (byte_size < 4)
 	    byte_size = 4;
-	  smode =
-	    smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
+	  smode = smallest_int_mode_for_size (byte_size * BITS_PER_UNIT);
 	  RTVEC_ELT (v, n) =
 	    gen_rtx_EXPR_LIST (VOIDmode,
 			       gen_rtx_REG (smode, FIRST_RETURN_REGNUM + n),
@@ -3847,7 +3846,7 @@ spu_function_arg (cumulative_args_t cum_v,
       rtx gr_reg;
       if (byte_size < 4)
 	byte_size = 4;
-      smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
+      smode = smallest_int_mode_for_size (byte_size * BITS_PER_UNIT);
       gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
 				  gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum),
 				  const0_rtx);
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 4167e26..bd351e5 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -143,8 +143,8 @@ static void coverage_obj_finish (vec<constructor_elt, va_gc> *);
 tree
 get_gcov_type (void)
 {
-  machine_mode mode
-    = smallest_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32, MODE_INT);
+  scalar_int_mode mode
+    = smallest_int_mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64 : 32);
   return lang_hooks.types.type_for_mode (mode, false);
 }
 
@@ -153,7 +153,7 @@ get_gcov_type (void)
 static tree
 get_gcov_unsigned_t (void)
 {
-  machine_mode mode = smallest_mode_for_size (32, MODE_INT);
+  scalar_int_mode mode = smallest_int_mode_for_size (32);
   return lang_hooks.types.type_for_mode (mode, true);
 }
 \f
diff --git a/gcc/dse.c b/gcc/dse.c
index c8e22a7..93ff9a7 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1573,7 +1573,7 @@ find_shift_sequence (int access_size,
 		     int shift, bool speed, bool require_cst)
 {
   machine_mode store_mode = GET_MODE (store_info->mem);
-  machine_mode new_mode;
+  scalar_int_mode new_mode;
   rtx read_reg = NULL;
 
   /* Some machines like the x86 have shift insns for each size of
@@ -1583,14 +1583,15 @@ find_shift_sequence (int access_size,
      justify the value we want to read but is available in one insn on
      the machine.  */
 
-  FOR_EACH_MODE_FROM (new_mode,
-		      smallest_mode_for_size (access_size * BITS_PER_UNIT,
-					      MODE_INT))
+  opt_scalar_int_mode new_mode_iter;
+  FOR_EACH_MODE_FROM (new_mode_iter,
+		      smallest_int_mode_for_size (access_size * BITS_PER_UNIT))
     {
       rtx target, new_reg, new_lhs;
       rtx_insn *shift_seq, *insn;
       int cost;
 
+      new_mode = *new_mode_iter;
       if (GET_MODE_BITSIZE (new_mode) > BITS_PER_WORD)
 	break;
 
diff --git a/gcc/expr.c b/gcc/expr.c
index 8141016..2e59bfd 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -344,8 +344,8 @@ convert_move (rtx to, rtx from, int unsignedp)
      xImode for all MODE_PARTIAL_INT modes they use, but no others.  */
   if (GET_MODE_CLASS (to_mode) == MODE_PARTIAL_INT)
     {
-      machine_mode full_mode
-	= smallest_mode_for_size (GET_MODE_BITSIZE (to_mode), MODE_INT);
+      scalar_int_mode full_mode
+	= smallest_int_mode_for_size (GET_MODE_BITSIZE (to_mode));
 
       gcc_assert (convert_optab_handler (trunc_optab, to_mode, full_mode)
 		  != CODE_FOR_nothing);
@@ -359,8 +359,8 @@ convert_move (rtx to, rtx from, int unsignedp)
   if (GET_MODE_CLASS (from_mode) == MODE_PARTIAL_INT)
     {
       rtx new_from;
-      machine_mode full_mode
-	= smallest_mode_for_size (GET_MODE_BITSIZE (from_mode), MODE_INT);
+      scalar_int_mode full_mode
+	= smallest_int_mode_for_size (GET_MODE_BITSIZE (from_mode));
       convert_optab ctab = unsignedp ? zext_optab : sext_optab;
       enum insn_code icode;
 
@@ -6898,7 +6898,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
 	  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
 	  rtx temp_target;
 	  if (mode == BLKmode || mode == VOIDmode)
-	    mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+	    mode = smallest_int_mode_for_size (size * BITS_PER_UNIT);
 	  temp_target = gen_reg_rtx (mode);
 	  emit_group_store (temp_target, temp, TREE_TYPE (exp), size);
 	  temp = temp_target;
@@ -6916,7 +6916,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
 	    {
 	      HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
 	      rtx temp_target;
-	      mode = smallest_mode_for_size (size * BITS_PER_UNIT, MODE_INT);
+	      mode = smallest_int_mode_for_size (size * BITS_PER_UNIT);
 	      temp_target = gen_reg_rtx (mode);
 	      temp_target
 	        = extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index cdcbaa4..49075c2 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2171,7 +2171,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
       if (orig_precres == precres && precop <= BITS_PER_WORD)
 	{
 	  int p = MAX (min_precision, precop);
-	  machine_mode m = smallest_mode_for_size (p, MODE_INT);
+	  scalar_int_mode m = smallest_int_mode_for_size (p);
 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
 							uns0_p && uns1_p
 							&& unsr_p);
@@ -2213,7 +2213,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
       if (orig_precres == precres)
 	{
 	  int p = MAX (prec0, prec1);
-	  machine_mode m = smallest_mode_for_size (p, MODE_INT);
+	  scalar_int_mode m = smallest_int_mode_for_size (p);
 	  tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
 							uns0_p && uns1_p
 							&& unsr_p);
diff --git a/gcc/machmode.h b/gcc/machmode.h
index f1519a8..b3d2d76 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -589,9 +589,16 @@ float_mode_for_size (unsigned int size)
 
 /* Similar to mode_for_size, but find the smallest mode for a given width.  */
 
-extern machine_mode smallest_mode_for_size (unsigned int,
-						 enum mode_class);
+extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
 
+/* Find the narrowest integer mode that contains at least SIZE bits.
+   Such a mode must exist.  */
+
+inline scalar_int_mode
+smallest_int_mode_for_size (unsigned int size)
+{
+  return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
+}
 
 /* Return an integer mode of exactly the same size as the input mode.  */
 
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index fdde578..e664587 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -193,13 +193,15 @@ get_best_extraction_insn (extraction_insn *insn,
 			  unsigned HOST_WIDE_INT struct_bits,
 			  machine_mode field_mode)
 {
-  machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
-  FOR_EACH_MODE_FROM (mode, mode)
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
     {
+      scalar_int_mode mode = *mode_iter;
       if (get_extraction_insn (insn, pattern, type, mode))
 	{
-	  FOR_EACH_MODE_FROM (mode, mode)
+	  FOR_EACH_MODE_FROM (mode_iter, mode)
 	    {
+	      mode = *mode_iter;
 	      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (field_mode)
 		  || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
 						    field_mode))
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b2c8006..edafe4a 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2082,8 +2082,7 @@ expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
 
   /* The value returned by the library function will have twice as
      many bits as the nominal MODE.  */
-  libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
-					MODE_INT);
+  libval_mode = smallest_int_mode_for_size (2 * GET_MODE_BITSIZE (mode));
   start_sequence ();
   libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
 				    libval_mode, 2,
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 6337764..91e79ad 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2121,12 +2121,15 @@ layout_type (tree type)
     case BOOLEAN_TYPE:
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
-      SET_TYPE_MODE (type,
-		     smallest_mode_for_size (TYPE_PRECISION (type), MODE_INT));
-      TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      /* Don't set TYPE_PRECISION here, as it may be set by a bitfield.  */
-      TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-      break;
+      {
+	scalar_int_mode mode
+	  = smallest_int_mode_for_size (TYPE_PRECISION (type));
+	SET_TYPE_MODE (type, mode);
+	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+	/* Don't set TYPE_PRECISION here, as it may be set by a bitfield.  */
+	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+	break;
+      }
 
     case REAL_TYPE:
       {
@@ -2571,8 +2574,7 @@ initialize_sizetypes (void)
 
   bprecision
     = MIN (precision + LOG2_BITS_PER_UNIT + 1, MAX_FIXED_MODE_SIZE);
-  bprecision
-    = GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
+  bprecision = GET_MODE_PRECISION (smallest_int_mode_for_size (bprecision));
   if (bprecision > HOST_BITS_PER_DOUBLE_INT)
     bprecision = HOST_BITS_PER_DOUBLE_INT;
 
@@ -2587,17 +2589,18 @@ initialize_sizetypes (void)
   TYPE_UNSIGNED (bitsizetype) = 1;
 
   /* Now layout both types manually.  */
-  SET_TYPE_MODE (sizetype, smallest_mode_for_size (precision, MODE_INT));
+  scalar_int_mode mode = smallest_int_mode_for_size (precision);
+  SET_TYPE_MODE (sizetype, mode);
   SET_TYPE_ALIGN (sizetype, GET_MODE_ALIGNMENT (TYPE_MODE (sizetype)));
   TYPE_SIZE (sizetype) = bitsize_int (precision);
-  TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
+  TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (mode));
   set_min_and_max_values_for_integral_type (sizetype, precision, UNSIGNED);
 
-  SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
+  mode = smallest_int_mode_for_size (bprecision);
+  SET_TYPE_MODE (bitsizetype, mode);
   SET_TYPE_ALIGN (bitsizetype, GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype)));
   TYPE_SIZE (bitsizetype) = bitsize_int (bprecision);
-  TYPE_SIZE_UNIT (bitsizetype)
-    = size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
+  TYPE_SIZE_UNIT (bitsizetype) = size_int (GET_MODE_SIZE (mode));
   set_min_and_max_values_for_integral_type (bitsizetype, bprecision, UNSIGNED);
 
   /* Create the signed variants of *sizetype.  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 90892fa..4f7744f 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1184,8 +1184,8 @@ machine_mode
 default_get_mask_mode (unsigned nunits, unsigned vector_size)
 {
   unsigned elem_size = vector_size / nunits;
-  machine_mode elem_mode
-    = smallest_mode_for_size (elem_size * BITS_PER_UNIT, MODE_INT);
+  scalar_int_mode elem_mode
+    = smallest_int_mode_for_size (elem_size * BITS_PER_UNIT);
   machine_mode vector_mode;
 
   gcc_assert (elem_size * nunits == vector_size);
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index f2d3492..e624a46 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -1462,7 +1462,6 @@ canonicalize_loop_ivs (struct loop *loop, tree *nit, bool bump_in_latch)
   gcond *stmt;
   edge exit = single_dom_exit (loop);
   gimple_seq stmts;
-  machine_mode mode;
   bool unsigned_p = false;
 
   for (psi = gsi_start_phis (loop->header);
@@ -1489,7 +1488,7 @@ canonicalize_loop_ivs (struct loop *loop, tree *nit, bool bump_in_latch)
       precision = TYPE_PRECISION (type);
     }
 
-  mode = smallest_mode_for_size (precision, MODE_INT);
+  scalar_int_mode mode = smallest_int_mode_for_size (precision);
   precision = GET_MODE_PRECISION (mode);
   type = build_nonstandard_integer_type (precision, unsigned_p);
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [20/67] Replace MODE_INT checks with is_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (19 preceding siblings ...)
  2016-12-09 13:05 ` [18/67] Make int_mode_for_mode return an opt_scalar_int_mode Richard Sandiford
@ 2016-12-09 13:06 ` Richard Sandiford
  2016-12-09 13:07 ` [22/67] Replace !VECTOR_MODE_P with is_a <scalar_int_mode> Richard Sandiford
                   ` (48 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:06 UTC (permalink / raw)
  To: gcc-patches

Replace checks of "GET_MODE_CLASS (...) == MODE_INT" with
"is_int_mode (..., &var)", in cases where it becomes useful
to refer to the mode as a scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (is_int_mode): New fuction.
	* combine.c (find_split_point): Use it.
	(combine_simplify_rtx): Likewise.
	(simplify_if_then_else): Likewise.
	(simplify_set): Likewise.
	(simplify_shift_const_1): Likewise.
	(simplify_comparison): Likewise.
	* config/aarch64/aarch64.c (aarch64_rtx_costs): Likewise.
	* cse.c (notreg_cost): Likewise.
	(cse_insn): Likewise.
	* cselib.c (cselib_lookup_1): Likewise.
	* dojump.c (do_jump_1): Likewise.
	(do_compare_rtx_and_jump): Likewise.
	* dse.c (get_call_args): Likewise.
	* dwarf2out.c (rtl_for_decl_init): Likewise.
	(native_encode_initializer): Likewise.
	* expmed.c (emit_store_flag_1): Likewise.
	(emit_store_flag): Likewise.
	* expr.c (convert_modes): Likewise.
	(store_field): Likewise.
	(expand_expr_real_1): Likewise.
	* fold-const.c (fold_read_from_constant_string): Likewise.
	* optabs-libfuncs.c (gen_int_libfunc): Likewise.
	* optabs.c (expand_binop): Likewise.
	(expand_unop): Likewise.
	(expand_abs_nojump): Likewise.
	(expand_one_cmpl_abs_nojump): Likewise.
	* simplify-rtx.c (mode_signbit_p): Likewise.
	(val_signbit_p): Likewise.
	(val_signbit_known_set_p): Likewise.
	(val_signbit_known_clear_p): Likewise.
	(simplify_relational_operation_1): Likewise.
	* stor-layout.c (vector_type_mode): Likewise.

diff --git a/gcc/combine.c b/gcc/combine.c
index 29b849a..5168488 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4766,6 +4766,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
   HOST_WIDE_INT pos = 0;
   int unsignedp = 0;
   rtx inner = NULL_RTX;
+  scalar_int_mode inner_mode;
 
   /* First special-case some codes.  */
   switch (code)
@@ -5007,12 +5008,12 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
 	  /* We can't optimize if either mode is a partial integer
 	     mode as we don't know how many bits are significant
 	     in those modes.  */
-	  if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_PARTIAL_INT
+	  if (!is_int_mode (GET_MODE (inner), &inner_mode)
 	      || GET_MODE_CLASS (GET_MODE (SET_SRC (x))) == MODE_PARTIAL_INT)
 	    break;
 
 	  pos = 0;
-	  len = GET_MODE_PRECISION (GET_MODE (inner));
+	  len = GET_MODE_PRECISION (inner_mode);
 	  unsignedp = 0;
 	  break;
 
@@ -5535,6 +5536,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 {
   enum rtx_code code = GET_CODE (x);
   machine_mode mode = GET_MODE (x);
+  scalar_int_mode int_mode;
   rtx temp;
   int i;
 
@@ -6045,47 +6047,51 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	    ;
 
 	  else if (STORE_FLAG_VALUE == 1
-	      && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
-	      && op1 == const0_rtx
-	      && mode == GET_MODE (op0)
-	      && nonzero_bits (op0, mode) == 1)
-	    return gen_lowpart (mode,
+		   && new_code == NE
+		   && is_int_mode (mode, &int_mode)
+		   && op1 == const0_rtx
+		   && int_mode == GET_MODE (op0)
+		   && nonzero_bits (op0, int_mode) == 1)
+	    return gen_lowpart (int_mode,
 				expand_compound_operation (op0));
 
 	  else if (STORE_FLAG_VALUE == 1
-		   && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == NE
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && (num_sign_bit_copies (op0, mode)
-		       == GET_MODE_PRECISION (mode)))
+		   && int_mode == GET_MODE (op0)
+		   && (num_sign_bit_copies (op0, int_mode)
+		       == GET_MODE_PRECISION (int_mode)))
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return simplify_gen_unary (NEG, mode,
-					 gen_lowpart (mode, op0),
-					 mode);
+	      return simplify_gen_unary (NEG, int_mode,
+					 gen_lowpart (int_mode, op0),
+					 int_mode);
 	    }
 
 	  else if (STORE_FLAG_VALUE == 1
-		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == EQ
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && nonzero_bits (op0, mode) == 1)
+		   && int_mode == GET_MODE (op0)
+		   && nonzero_bits (op0, int_mode) == 1)
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return simplify_gen_binary (XOR, mode,
-					  gen_lowpart (mode, op0),
+	      return simplify_gen_binary (XOR, int_mode,
+					  gen_lowpart (int_mode, op0),
 					  const1_rtx);
 	    }
 
 	  else if (STORE_FLAG_VALUE == 1
-		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == EQ
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && (num_sign_bit_copies (op0, mode)
-		       == GET_MODE_PRECISION (mode)))
+		   && int_mode == GET_MODE (op0)
+		   && (num_sign_bit_copies (op0, int_mode)
+		       == GET_MODE_PRECISION (int_mode)))
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return plus_constant (mode, gen_lowpart (mode, op0), 1);
+	      return plus_constant (int_mode, gen_lowpart (int_mode, op0), 1);
 	    }
 
 	  /* If STORE_FLAG_VALUE is -1, we have cases similar to
@@ -6094,48 +6100,51 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	    ;
 
 	  else if (STORE_FLAG_VALUE == -1
-		   && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == NE
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && (num_sign_bit_copies (op0, mode)
-		       == GET_MODE_PRECISION (mode)))
-	    return gen_lowpart (mode,
-				expand_compound_operation (op0));
+		   && int_mode == GET_MODE (op0)
+		   && (num_sign_bit_copies (op0, int_mode)
+		       == GET_MODE_PRECISION (int_mode)))
+	    return gen_lowpart (int_mode, expand_compound_operation (op0));
 
 	  else if (STORE_FLAG_VALUE == -1
-		   && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == NE
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && nonzero_bits (op0, mode) == 1)
+		   && int_mode == GET_MODE (op0)
+		   && nonzero_bits (op0, int_mode) == 1)
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return simplify_gen_unary (NEG, mode,
-					 gen_lowpart (mode, op0),
-					 mode);
+	      return simplify_gen_unary (NEG, int_mode,
+					 gen_lowpart (int_mode, op0),
+					 int_mode);
 	    }
 
 	  else if (STORE_FLAG_VALUE == -1
-		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == EQ
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && (num_sign_bit_copies (op0, mode)
-		       == GET_MODE_PRECISION (mode)))
+		   && int_mode == GET_MODE (op0)
+		   && (num_sign_bit_copies (op0, int_mode)
+		       == GET_MODE_PRECISION (int_mode)))
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return simplify_gen_unary (NOT, mode,
-					 gen_lowpart (mode, op0),
-					 mode);
+	      return simplify_gen_unary (NOT, int_mode,
+					 gen_lowpart (int_mode, op0),
+					 int_mode);
 	    }
 
 	  /* If X is 0/1, (eq X 0) is X-1.  */
 	  else if (STORE_FLAG_VALUE == -1
-		   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
+		   && new_code == EQ
+		   && is_int_mode (mode, &int_mode)
 		   && op1 == const0_rtx
-		   && mode == GET_MODE (op0)
-		   && nonzero_bits (op0, mode) == 1)
+		   && int_mode == GET_MODE (op0)
+		   && nonzero_bits (op0, int_mode) == 1)
 	    {
 	      op0 = expand_compound_operation (op0);
-	      return plus_constant (mode, gen_lowpart (mode, op0), -1);
+	      return plus_constant (int_mode, gen_lowpart (int_mode, op0), -1);
 	    }
 
 	  /* If STORE_FLAG_VALUE says to just test the sign bit and X has just
@@ -6143,16 +6152,17 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	     (ashift x c) where C puts the bit in the sign bit.  Remove any
 	     AND with STORE_FLAG_VALUE when we are done, since we are only
 	     going to test the sign bit.  */
-	  if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
-	      && HWI_COMPUTABLE_MODE_P (mode)
-	      && val_signbit_p (mode, STORE_FLAG_VALUE)
+	  if (new_code == NE
+	      && is_int_mode (mode, &int_mode)
+	      && HWI_COMPUTABLE_MODE_P (int_mode)
+	      && val_signbit_p (int_mode, STORE_FLAG_VALUE)
 	      && op1 == const0_rtx
-	      && mode == GET_MODE (op0)
-	      && (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
+	      && int_mode == GET_MODE (op0)
+	      && (i = exact_log2 (nonzero_bits (op0, int_mode))) >= 0)
 	    {
-	      x = simplify_shift_const (NULL_RTX, ASHIFT, mode,
+	      x = simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
 					expand_compound_operation (op0),
-					GET_MODE_PRECISION (mode) - 1 - i);
+					GET_MODE_PRECISION (int_mode) - 1 - i);
 	      if (GET_CODE (x) == AND && XEXP (x, 1) == const_true_rtx)
 		return XEXP (x, 0);
 	      else
@@ -6238,6 +6248,7 @@ simplify_if_then_else (rtx x)
   int i;
   enum rtx_code false_code;
   rtx reversed;
+  scalar_int_mode int_mode;
 
   /* Simplify storing of the truth value.  */
   if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
@@ -6418,7 +6429,7 @@ simplify_if_then_else (rtx x)
 
   if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
       && comparison_p
-      && GET_MODE_CLASS (mode) == MODE_INT
+      && is_int_mode (mode, &int_mode)
       && ! side_effects_p (x))
     {
       rtx t = make_compound_operation (true_rtx, SET);
@@ -6426,7 +6437,7 @@ simplify_if_then_else (rtx x)
       rtx cond_op0 = XEXP (cond, 0);
       rtx cond_op1 = XEXP (cond, 1);
       enum rtx_code op = UNKNOWN, extend_op = UNKNOWN;
-      machine_mode m = mode;
+      machine_mode m = int_mode;
       rtx z = 0, c1 = NULL_RTX;
 
       if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
@@ -6455,7 +6466,7 @@ simplify_if_then_else (rtx x)
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
 	       && (num_sign_bit_copies (f, GET_MODE (f))
 		   > (unsigned int)
-		     (GET_MODE_PRECISION (mode)
+		     (GET_MODE_PRECISION (int_mode)
 		      - GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (t, 0), 0))))))
 	{
 	  c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
@@ -6471,7 +6482,7 @@ simplify_if_then_else (rtx x)
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
 	       && (num_sign_bit_copies (f, GET_MODE (f))
 		   > (unsigned int)
-		     (GET_MODE_PRECISION (mode)
+		     (GET_MODE_PRECISION (int_mode)
 		      - GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (t, 0), 1))))))
 	{
 	  c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
@@ -6487,7 +6498,7 @@ simplify_if_then_else (rtx x)
 		   || GET_CODE (XEXP (t, 0)) == LSHIFTRT
 		   || GET_CODE (XEXP (t, 0)) == ASHIFTRT)
 	       && GET_CODE (XEXP (XEXP (t, 0), 0)) == SUBREG
-	       && HWI_COMPUTABLE_MODE_P (mode)
+	       && HWI_COMPUTABLE_MODE_P (int_mode)
 	       && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
 	       && ((nonzero_bits (f, GET_MODE (f))
@@ -6503,7 +6514,7 @@ simplify_if_then_else (rtx x)
 		   || GET_CODE (XEXP (t, 0)) == IOR
 		   || GET_CODE (XEXP (t, 0)) == XOR)
 	       && GET_CODE (XEXP (XEXP (t, 0), 1)) == SUBREG
-	       && HWI_COMPUTABLE_MODE_P (mode)
+	       && HWI_COMPUTABLE_MODE_P (int_mode)
 	       && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
 	       && ((nonzero_bits (f, GET_MODE (f))
@@ -6527,7 +6538,7 @@ simplify_if_then_else (rtx x)
 	  temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
 
 	  if (extend_op != UNKNOWN)
-	    temp = simplify_gen_unary (extend_op, mode, temp, m);
+	    temp = simplify_gen_unary (extend_op, int_mode, temp, m);
 
 	  return temp;
 	}
@@ -6580,6 +6591,7 @@ simplify_set (rtx x)
     = GET_MODE (src) != VOIDmode ? GET_MODE (src) : GET_MODE (dest);
   rtx_insn *other_insn;
   rtx *cc_use;
+  scalar_int_mode int_mode;
 
   /* (set (pc) (return)) gets written as (return).  */
   if (GET_CODE (dest) == PC && ANY_RETURN_P (src))
@@ -6848,15 +6860,14 @@ simplify_set (rtx x)
 
   if (GET_CODE (dest) != PC
       && GET_CODE (src) == IF_THEN_ELSE
-      && GET_MODE_CLASS (GET_MODE (src)) == MODE_INT
+      && is_int_mode (GET_MODE (src), &int_mode)
       && (GET_CODE (XEXP (src, 0)) == EQ || GET_CODE (XEXP (src, 0)) == NE)
       && XEXP (XEXP (src, 0), 1) == const0_rtx
-      && GET_MODE (src) == GET_MODE (XEXP (XEXP (src, 0), 0))
+      && int_mode == GET_MODE (XEXP (XEXP (src, 0), 0))
       && (!HAVE_conditional_move
-	  || ! can_conditionally_move_p (GET_MODE (src)))
-      && (num_sign_bit_copies (XEXP (XEXP (src, 0), 0),
-			       GET_MODE (XEXP (XEXP (src, 0), 0)))
-	  == GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (src, 0), 0))))
+	  || ! can_conditionally_move_p (int_mode))
+      && (num_sign_bit_copies (XEXP (XEXP (src, 0), 0), int_mode)
+	  == GET_MODE_PRECISION (int_mode))
       && ! side_effects_p (src))
     {
       rtx true_rtx = (GET_CODE (XEXP (src, 0)) == NE
@@ -6878,17 +6889,17 @@ simplify_set (rtx x)
 	       && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
 	term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx;
 
-      term2 = simplify_gen_binary (AND, GET_MODE (src),
+      term2 = simplify_gen_binary (AND, int_mode,
 				   XEXP (XEXP (src, 0), 0), true_rtx);
-      term3 = simplify_gen_binary (AND, GET_MODE (src),
-				   simplify_gen_unary (NOT, GET_MODE (src),
+      term3 = simplify_gen_binary (AND, int_mode,
+				   simplify_gen_unary (NOT, int_mode,
 						       XEXP (XEXP (src, 0), 0),
-						       GET_MODE (src)),
+						       int_mode),
 				   false_rtx);
 
       SUBST (SET_SRC (x),
-	     simplify_gen_binary (IOR, GET_MODE (src),
-				  simplify_gen_binary (IOR, GET_MODE (src),
+	     simplify_gen_binary (IOR, int_mode,
+				  simplify_gen_binary (IOR, int_mode,
 						       term1, term2),
 				  term3));
 
@@ -10270,7 +10281,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
   rtx orig_varop = varop;
   int count;
   machine_mode mode = result_mode;
-  machine_mode shift_mode, tmode;
+  machine_mode shift_mode;
+  scalar_int_mode tmode, inner_mode;
   unsigned int mode_words
     = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
   /* We form (outer_op (code varop count) (outer_const)).  */
@@ -10438,17 +10450,16 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	     the same number of words as what we've seen so far.  Then store
 	     the widest mode in MODE.  */
 	  if (subreg_lowpart_p (varop)
-	      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
-		  > GET_MODE_SIZE (GET_MODE (varop)))
-	      && (unsigned int) ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
+	      && is_int_mode (GET_MODE (SUBREG_REG (varop)), &inner_mode)
+	      && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (GET_MODE (varop))
+	      && (unsigned int) ((GET_MODE_SIZE (inner_mode)
 				  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
 		 == mode_words
-	      && GET_MODE_CLASS (GET_MODE (varop)) == MODE_INT
-	      && GET_MODE_CLASS (GET_MODE (SUBREG_REG (varop))) == MODE_INT)
+	      && GET_MODE_CLASS (GET_MODE (varop)) == MODE_INT)
 	    {
 	      varop = SUBREG_REG (varop);
-	      if (GET_MODE_SIZE (GET_MODE (varop)) > GET_MODE_SIZE (mode))
-		mode = GET_MODE (varop);
+	      if (GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (mode))
+		mode = inner_mode;
 	      continue;
 	    }
 	  break;
@@ -11679,7 +11690,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
   rtx op1 = *pop1;
   rtx tem, tem1;
   int i;
-  machine_mode mode, tmode;
+  scalar_int_mode mode, inner_mode;
+  machine_mode tmode;
 
   /* Try a few ways of applying the same transformation to both operands.  */
   while (1)
@@ -12621,8 +12633,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
   op1 = make_compound_operation (op1, SET);
 
   if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
-      && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-      && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
+      && is_int_mode (GET_MODE (op0), &mode)
+      && is_int_mode (GET_MODE (SUBREG_REG (op0)), &inner_mode)
       && (code == NE || code == EQ))
     {
       if (paradoxical_subreg_p (op0))
@@ -12632,19 +12644,16 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	  if (REG_P (SUBREG_REG (op0)))
 	    {
 	      op0 = SUBREG_REG (op0);
-	      op1 = gen_lowpart (GET_MODE (op0), op1);
+	      op1 = gen_lowpart (inner_mode, op1);
 	    }
 	}
-      else if ((GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0)))
-		<= HOST_BITS_PER_WIDE_INT)
-	       && (nonzero_bits (SUBREG_REG (op0),
-				 GET_MODE (SUBREG_REG (op0)))
-		   & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+      else if (GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
+	       && (nonzero_bits (SUBREG_REG (op0), inner_mode)
+		   & ~GET_MODE_MASK (mode)) == 0)
 	{
-	  tem = gen_lowpart (GET_MODE (SUBREG_REG (op0)), op1);
+	  tem = gen_lowpart (inner_mode, op1);
 
-	  if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
-	       & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+	  if ((nonzero_bits (tem, inner_mode) & ~GET_MODE_MASK (mode)) == 0)
 	    op0 = SUBREG_REG (op0), op1 = tem;
 	}
     }
@@ -12655,8 +12664,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
      mode for which we can do the compare.  There are a number of cases in
      which we can use the wider mode.  */
 
-  mode = GET_MODE (op0);
-  if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
+  if (is_int_mode (GET_MODE (op0), &mode)
       && GET_MODE_SIZE (mode) < UNITS_PER_WORD
       && ! have_insn_for (COMPARE, mode))
     FOR_EACH_WIDER_MODE (tmode, mode)
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index fc2bcad..ed2e44b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -6486,6 +6486,7 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
   const struct cpu_cost_table *extra_cost
     = aarch64_tune_params.insn_extra_cost;
   int code = GET_CODE (x);
+  scalar_int_mode int_mode;
 
   /* By default, assume that everything has equivalent cost to the
      cheapest instruction.  Any additional costs are applied as a delta
@@ -7048,28 +7049,29 @@ cost_plus:
           return true;
         }
 
-      if (GET_MODE_CLASS (mode) == MODE_INT)
+      if (is_int_mode (mode, &int_mode))
 	{
 	  if (CONST_INT_P (op1))
 	    {
 	      /* We have a mask + shift version of a UBFIZ
 		 i.e. the *andim_ashift<mode>_bfiz pattern.  */
 	      if (GET_CODE (op0) == ASHIFT
-		  && aarch64_mask_and_shift_for_ubfiz_p (mode, op1,
-							  XEXP (op0, 1)))
+		  && aarch64_mask_and_shift_for_ubfiz_p (int_mode, op1,
+							 XEXP (op0, 1)))
 		{
-		  *cost += rtx_cost (XEXP (op0, 0), mode,
+		  *cost += rtx_cost (XEXP (op0, 0), int_mode,
 				     (enum rtx_code) code, 0, speed);
 		  if (speed)
 		    *cost += extra_cost->alu.bfx;
 
 		  return true;
 		}
-	      else if (aarch64_bitmask_imm (INTVAL (op1), mode))
+	      else if (aarch64_bitmask_imm (INTVAL (op1), int_mode))
 		{
 		/* We possibly get the immediate for free, this is not
 		   modelled.  */
-		  *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed);
+		  *cost += rtx_cost (op0, int_mode,
+				     (enum rtx_code) code, 0, speed);
 		  if (speed)
 		    *cost += extra_cost->alu.logical;
 
@@ -7104,8 +7106,10 @@ cost_plus:
 		}
 
 	      /* In both cases we want to cost both operands.  */
-	      *cost += rtx_cost (new_op0, mode, (enum rtx_code) code, 0, speed);
-	      *cost += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
+	      *cost += rtx_cost (new_op0, int_mode, (enum rtx_code) code,
+				 0, speed);
+	      *cost += rtx_cost (op1, int_mode, (enum rtx_code) code,
+				 1, speed);
 
 	      return true;
 	    }
diff --git a/gcc/cse.c b/gcc/cse.c
index eda6177..cc29d4a 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -720,13 +720,14 @@ preferable (int cost_a, int regcost_a, int cost_b, int regcost_b)
 static int
 notreg_cost (rtx x, machine_mode mode, enum rtx_code outer, int opno)
 {
+  scalar_int_mode int_mode, inner_mode;
   return ((GET_CODE (x) == SUBREG
 	   && REG_P (SUBREG_REG (x))
-	   && GET_MODE_CLASS (mode) == MODE_INT
-	   && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
-	   && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+	   && is_int_mode (mode, &int_mode)
+	   && is_int_mode (GET_MODE (SUBREG_REG (x)), &inner_mode)
+	   && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode)
 	   && subreg_lowpart_p (x)
-	   && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (SUBREG_REG (x))))
+	   && TRULY_NOOP_TRUNCATION_MODES_P (int_mode, inner_mode))
 	  ? 0
 	  : rtx_cost (x, mode, outer, opno, optimize_this_for_speed_p) * 2);
 }
@@ -4603,6 +4604,7 @@ cse_insn (rtx_insn *insn)
       /* Set nonzero if we need to call force_const_mem on with the
 	 contents of src_folded before using it.  */
       int src_folded_force_flag = 0;
+      scalar_int_mode int_mode;
 
       dest = SET_DEST (sets[i].rtl);
       src = SET_SRC (sets[i].rtl);
@@ -4840,13 +4842,13 @@ cse_insn (rtx_insn *insn)
 	 wider mode.  */
 
       if (src_const && src_related == 0 && CONST_INT_P (src_const)
-	  && GET_MODE_CLASS (mode) == MODE_INT
-	  && GET_MODE_PRECISION (mode) < BITS_PER_WORD)
+	  && is_int_mode (mode, &int_mode)
+	  && GET_MODE_PRECISION (int_mode) < BITS_PER_WORD)
 	{
-	  machine_mode wider_mode;
-
-	  FOR_EACH_WIDER_MODE (wider_mode, mode)
+	  opt_scalar_int_mode wider_mode_iter;
+	  FOR_EACH_WIDER_MODE (wider_mode_iter, int_mode)
 	    {
+	      scalar_int_mode wider_mode = *wider_mode_iter;
 	      if (GET_MODE_PRECISION (wider_mode) > BITS_PER_WORD)
 		break;
 
@@ -4860,7 +4862,7 @@ cse_insn (rtx_insn *insn)
 		   const_elt; const_elt = const_elt->next_same_value)
 		if (REG_P (const_elt->exp))
 		  {
-		    src_related = gen_lowpart (mode, const_elt->exp);
+		    src_related = gen_lowpart (int_mode, const_elt->exp);
 		    break;
 		  }
 
diff --git a/gcc/cselib.c b/gcc/cselib.c
index a35dca8..032461a 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -1999,6 +1999,8 @@ cselib_lookup_1 (rtx x, machine_mode mode,
 
       e = new_cselib_val (next_uid, GET_MODE (x), x);
       new_elt_loc_list (e, x);
+
+      scalar_int_mode int_mode;
       if (REG_VALUES (i) == 0)
 	{
 	  /* Maintain the invariant that the first entry of
@@ -2008,27 +2010,27 @@ cselib_lookup_1 (rtx x, machine_mode mode,
 	  REG_VALUES (i) = new_elt_list (REG_VALUES (i), NULL);
 	}
       else if (cselib_preserve_constants
-	       && GET_MODE_CLASS (mode) == MODE_INT)
+	       && is_int_mode (mode, &int_mode))
 	{
 	  /* During var-tracking, try harder to find equivalences
 	     for SUBREGs.  If a setter sets say a DImode register
 	     and user uses that register only in SImode, add a lowpart
 	     subreg location.  */
 	  struct elt_list *lwider = NULL;
+	  scalar_int_mode lmode;
 	  l = REG_VALUES (i);
 	  if (l && l->elt == NULL)
 	    l = l->next;
 	  for (; l; l = l->next)
-	    if (GET_MODE_CLASS (GET_MODE (l->elt->val_rtx)) == MODE_INT
-		&& GET_MODE_SIZE (GET_MODE (l->elt->val_rtx))
-		   > GET_MODE_SIZE (mode)
+	    if (is_int_mode (GET_MODE (l->elt->val_rtx), &lmode)
+		&& GET_MODE_SIZE (lmode) > GET_MODE_SIZE (int_mode)
 		&& (lwider == NULL
-		    || GET_MODE_SIZE (GET_MODE (l->elt->val_rtx))
+		    || GET_MODE_SIZE (lmode)
 		       < GET_MODE_SIZE (GET_MODE (lwider->elt->val_rtx))))
 	      {
 		struct elt_loc_list *el;
 		if (i < FIRST_PSEUDO_REGISTER
-		    && hard_regno_nregs[i][GET_MODE (l->elt->val_rtx)] != 1)
+		    && hard_regno_nregs[i][lmode] != 1)
 		  continue;
 		for (el = l->elt->locs; el; el = el->next)
 		  if (!REG_P (el->loc))
@@ -2038,7 +2040,7 @@ cselib_lookup_1 (rtx x, machine_mode mode,
 	      }
 	  if (lwider)
 	    {
-	      rtx sub = lowpart_subreg (mode, lwider->elt->val_rtx,
+	      rtx sub = lowpart_subreg (int_mode, lwider->elt->val_rtx,
 					GET_MODE (lwider->elt->val_rtx));
 	      if (sub)
 		new_elt_loc_list (e, sub);
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 1195599..dbc76dc 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -209,6 +209,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 {
   machine_mode mode;
   rtx_code_label *drop_through_label = 0;
+  scalar_int_mode int_mode;
 
   switch (code)
     {
@@ -223,10 +224,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
         if (integer_zerop (op1))
 	  do_jump (op0, if_true_label, if_false_label, inv (prob));
-        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-                 && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
-	  do_jump_by_parts_equality (op0, op1, if_false_label, if_true_label,
-				     prob);
+	else if (is_int_mode (TYPE_MODE (inner_type), &int_mode)
+		 && !can_compare_p (EQ, int_mode, ccp_jump))
+	  do_jump_by_parts_equality (op0, op1, if_false_label,
+				     if_true_label, prob);
         else
 	  do_compare_and_jump (op0, op1, EQ, EQ, if_false_label, if_true_label,
 			       prob);
@@ -244,10 +245,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
         if (integer_zerop (op1))
 	  do_jump (op0, if_false_label, if_true_label, prob);
-        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-           && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
-	  do_jump_by_parts_equality (op0, op1, if_true_label, if_false_label,
-				     inv (prob));
+	else if (is_int_mode (TYPE_MODE (inner_type), &int_mode)
+		 && !can_compare_p (NE, int_mode, ccp_jump))
+	  do_jump_by_parts_equality (op0, op1, if_true_label,
+				     if_false_label, inv (prob));
         else
 	  do_compare_and_jump (op0, op1, NE, NE, if_false_label, if_true_label,
 			       prob);
@@ -256,10 +257,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
     case LT_EXPR:
       mode = TYPE_MODE (TREE_TYPE (op0));
-      if (GET_MODE_CLASS (mode) == MODE_INT
-          && ! can_compare_p (LT, mode, ccp_jump))
-	do_jump_by_parts_greater (op0, op1, 1, if_false_label, if_true_label,
-				  prob);
+      if (is_int_mode (mode, &int_mode)
+	  && ! can_compare_p (LT, int_mode, ccp_jump))
+	do_jump_by_parts_greater (op0, op1, 1, if_false_label,
+				  if_true_label, prob);
       else
 	do_compare_and_jump (op0, op1, LT, LTU, if_false_label, if_true_label,
 			     prob);
@@ -267,10 +268,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
     case LE_EXPR:
       mode = TYPE_MODE (TREE_TYPE (op0));
-      if (GET_MODE_CLASS (mode) == MODE_INT
-          && ! can_compare_p (LE, mode, ccp_jump))
-	do_jump_by_parts_greater (op0, op1, 0, if_true_label, if_false_label,
-				  inv (prob));
+      if (is_int_mode (mode, &int_mode)
+	  && ! can_compare_p (LE, int_mode, ccp_jump))
+	do_jump_by_parts_greater (op0, op1, 0, if_true_label,
+				  if_false_label, inv (prob));
       else
 	do_compare_and_jump (op0, op1, LE, LEU, if_false_label, if_true_label,
 			     prob);
@@ -278,10 +279,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
     case GT_EXPR:
       mode = TYPE_MODE (TREE_TYPE (op0));
-      if (GET_MODE_CLASS (mode) == MODE_INT
-          && ! can_compare_p (GT, mode, ccp_jump))
-	do_jump_by_parts_greater (op0, op1, 0, if_false_label, if_true_label,
-				  prob);
+      if (is_int_mode (mode, &int_mode)
+	  && ! can_compare_p (GT, int_mode, ccp_jump))
+	do_jump_by_parts_greater (op0, op1, 0, if_false_label,
+				  if_true_label, prob);
       else
 	do_compare_and_jump (op0, op1, GT, GTU, if_false_label, if_true_label,
 			     prob);
@@ -289,10 +290,10 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 
     case GE_EXPR:
       mode = TYPE_MODE (TREE_TYPE (op0));
-      if (GET_MODE_CLASS (mode) == MODE_INT
-          && ! can_compare_p (GE, mode, ccp_jump))
-	do_jump_by_parts_greater (op0, op1, 1, if_true_label, if_false_label,
-				  inv (prob));
+      if (is_int_mode (mode, &int_mode)
+	  && ! can_compare_p (GE, int_mode, ccp_jump))
+	do_jump_by_parts_greater (op0, op1, 1, if_true_label,
+				  if_false_label, inv (prob));
       else
 	do_compare_and_jump (op0, op1, GE, GEU, if_false_label, if_true_label,
 			     prob);
@@ -1022,62 +1023,63 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
   if (! if_true_label)
     dummy_label = if_true_label = gen_label_rtx ();
 
-  if (GET_MODE_CLASS (mode) == MODE_INT
-      && ! can_compare_p (code, mode, ccp_jump))
+  scalar_int_mode int_mode;
+  if (is_int_mode (mode, &int_mode)
+      && ! can_compare_p (code, int_mode, ccp_jump))
     {
       switch (code)
 	{
 	case LTU:
-	  do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
+	  do_jump_by_parts_greater_rtx (int_mode, 1, op1, op0,
 					if_false_label, if_true_label, prob);
 	  break;
 
 	case LEU:
-	  do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
+	  do_jump_by_parts_greater_rtx (int_mode, 1, op0, op1,
 					if_true_label, if_false_label,
 					inv (prob));
 	  break;
 
 	case GTU:
-	  do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
+	  do_jump_by_parts_greater_rtx (int_mode, 1, op0, op1,
 					if_false_label, if_true_label, prob);
 	  break;
 
 	case GEU:
-	  do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
+	  do_jump_by_parts_greater_rtx (int_mode, 1, op1, op0,
 					if_true_label, if_false_label,
 					inv (prob));
 	  break;
 
 	case LT:
-	  do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
+	  do_jump_by_parts_greater_rtx (int_mode, 0, op1, op0,
 					if_false_label, if_true_label, prob);
 	  break;
 
 	case LE:
-	  do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
+	  do_jump_by_parts_greater_rtx (int_mode, 0, op0, op1,
 					if_true_label, if_false_label,
 					inv (prob));
 	  break;
 
 	case GT:
-	  do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
+	  do_jump_by_parts_greater_rtx (int_mode, 0, op0, op1,
 					if_false_label, if_true_label, prob);
 	  break;
 
 	case GE:
-	  do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
+	  do_jump_by_parts_greater_rtx (int_mode, 0, op1, op0,
 					if_true_label, if_false_label,
 					inv (prob));
 	  break;
 
 	case EQ:
-	  do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
+	  do_jump_by_parts_equality_rtx (int_mode, op0, op1, if_false_label,
 					 if_true_label, prob);
 	  break;
 
 	case NE:
-	  do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
+	  do_jump_by_parts_equality_rtx (int_mode, op0, op1, if_true_label,
 					 if_false_label, inv (prob));
 	  break;
 
diff --git a/gcc/dse.c b/gcc/dse.c
index 93ff9a7..713f52b 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -2185,11 +2185,14 @@ get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
        arg != void_list_node && idx < nargs;
        arg = TREE_CHAIN (arg), idx++)
     {
-      machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
+      scalar_int_mode mode;
       rtx reg, link, tmp;
+
+      if (!is_int_mode (TYPE_MODE (TREE_VALUE (arg)), &mode))
+	return false;
+
       reg = targetm.calls.function_arg (args_so_far, mode, NULL_TREE, true);
-      if (!reg || !REG_P (reg) || GET_MODE (reg) != mode
-	  || GET_MODE_CLASS (mode) != MODE_INT)
+      if (!reg || !REG_P (reg) || GET_MODE (reg) != mode)
 	return false;
 
       for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
@@ -2197,15 +2200,14 @@ get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
 	   link = XEXP (link, 1))
 	if (GET_CODE (XEXP (link, 0)) == USE)
 	  {
+	    scalar_int_mode arg_mode;
 	    args[idx] = XEXP (XEXP (link, 0), 0);
 	    if (REG_P (args[idx])
 		&& REGNO (args[idx]) == REGNO (reg)
 		&& (GET_MODE (args[idx]) == mode
-		    || (GET_MODE_CLASS (GET_MODE (args[idx])) == MODE_INT
-			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
-			    <= UNITS_PER_WORD)
-			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
-			    > GET_MODE_SIZE (mode)))))
+		    || (is_int_mode (GET_MODE (args[idx]), &arg_mode)
+			&& (GET_MODE_SIZE (arg_mode) <= UNITS_PER_WORD)
+			&& (GET_MODE_SIZE (arg_mode) > GET_MODE_SIZE (mode)))))
 	      break;
 	  }
       if (!link)
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 568100d..2af401c 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -18562,9 +18562,10 @@ rtl_for_decl_init (tree init, tree type)
     {
       tree enttype = TREE_TYPE (type);
       tree domain = TYPE_DOMAIN (type);
-      machine_mode mode = TYPE_MODE (enttype);
+      scalar_int_mode mode;
 
-      if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+      if (is_int_mode (TYPE_MODE (enttype), &mode)
+	  && GET_MODE_SIZE (mode) == 1
 	  && domain
 	  && integer_zerop (TYPE_MIN_VALUE (domain))
 	  && compare_tree_int (TYPE_MAX_VALUE (domain),
@@ -19045,9 +19046,10 @@ native_encode_initializer (tree init, unsigned char *array, int size)
       if (TREE_CODE (type) == ARRAY_TYPE)
 	{
 	  tree enttype = TREE_TYPE (type);
-	  machine_mode mode = TYPE_MODE (enttype);
+	  scalar_int_mode mode;
 
-	  if (GET_MODE_CLASS (mode) != MODE_INT || GET_MODE_SIZE (mode) != 1)
+	  if (!is_int_mode (TYPE_MODE (enttype), &mode)
+	      || GET_MODE_SIZE (mode) != 1)
 	    return false;
 	  if (int_size_in_bytes (type) != size)
 	    return false;
diff --git a/gcc/expmed.c b/gcc/expmed.c
index bc5df87..bf85b7f 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -5381,8 +5381,9 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
   /* If we are comparing a double-word integer with zero or -1, we can
      convert the comparison into one involving a single word.  */
-  if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD * 2
-      && GET_MODE_CLASS (mode) == MODE_INT
+  scalar_int_mode int_mode;
+  if (is_int_mode (mode, &int_mode)
+      && GET_MODE_BITSIZE (int_mode) == BITS_PER_WORD * 2
       && (!MEM_P (op0) || ! MEM_VOLATILE_P (op0)))
     {
       rtx tem;
@@ -5393,8 +5394,8 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
 	  /* Do a logical OR or AND of the two words and compare the
 	     result.  */
-	  op00 = simplify_gen_subreg (word_mode, op0, mode, 0);
-	  op01 = simplify_gen_subreg (word_mode, op0, mode, UNITS_PER_WORD);
+	  op00 = simplify_gen_subreg (word_mode, op0, int_mode, 0);
+	  op01 = simplify_gen_subreg (word_mode, op0, int_mode, UNITS_PER_WORD);
 	  tem = expand_binop (word_mode,
 			      op1 == const0_rtx ? ior_optab : and_optab,
 			      op00, op01, NULL_RTX, unsignedp,
@@ -5409,9 +5410,9 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 	  rtx op0h;
 
 	  /* If testing the sign bit, can just test on high word.  */
-	  op0h = simplify_gen_subreg (word_mode, op0, mode,
+	  op0h = simplify_gen_subreg (word_mode, op0, int_mode,
 				      subreg_highpart_offset (word_mode,
-							      mode));
+							      int_mode));
 	  tem = emit_store_flag (NULL_RTX, code, op0h, op1, word_mode,
 				 unsignedp, normalizep);
 	}
@@ -5436,21 +5437,21 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
   /* If this is A < 0 or A >= 0, we can do this by taking the ones
      complement of A (for GE) and shifting the sign bit to the low bit.  */
   if (op1 == const0_rtx && (code == LT || code == GE)
-      && GET_MODE_CLASS (mode) == MODE_INT
+      && is_int_mode (mode, &int_mode)
       && (normalizep || STORE_FLAG_VALUE == 1
-	  || val_signbit_p (mode, STORE_FLAG_VALUE)))
+	  || val_signbit_p (int_mode, STORE_FLAG_VALUE)))
     {
       subtarget = target;
 
       if (!target)
-	target_mode = mode;
+	target_mode = int_mode;
 
       /* If the result is to be wider than OP0, it is best to convert it
 	 first.  If it is to be narrower, it is *incorrect* to convert it
 	 first.  */
-      else if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode))
+      else if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (int_mode))
 	{
-	  op0 = convert_modes (target_mode, mode, op0, 0);
+	  op0 = convert_modes (target_mode, int_mode, op0, 0);
 	  mode = target_mode;
 	}
 
@@ -5650,7 +5651,8 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
   /* The remaining tricks only apply to integer comparisons.  */
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  scalar_int_mode int_mode;
+  if (!is_int_mode (mode, &int_mode))
     return 0;
 
   /* If this is an equality comparison of integers, we can try to exclusive-or
@@ -5660,15 +5662,15 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
   if ((code == EQ || code == NE) && op1 != const0_rtx)
     {
-      tem = expand_binop (mode, xor_optab, op0, op1, subtarget, 1,
+      tem = expand_binop (int_mode, xor_optab, op0, op1, subtarget, 1,
 			  OPTAB_WIDEN);
 
       if (tem == 0)
-	tem = expand_binop (mode, sub_optab, op0, op1, subtarget, 1,
+	tem = expand_binop (int_mode, sub_optab, op0, op1, subtarget, 1,
 			    OPTAB_WIDEN);
       if (tem != 0)
 	tem = emit_store_flag (target, code, tem, const0_rtx,
-			       mode, unsignedp, normalizep);
+			       int_mode, unsignedp, normalizep);
       if (tem != 0)
 	return tem;
 
@@ -5679,10 +5681,10 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
      small X and if we'd have anyway to extend, implementing "X != 0"
      as "-(int)X >> 31" is still cheaper than inverting "(int)X == 0".  */
   rcode = reverse_condition (code);
-  if (can_compare_p (rcode, mode, ccp_store_flag)
-      && ! (optab_handler (cstore_optab, mode) == CODE_FOR_nothing
+  if (can_compare_p (rcode, int_mode, ccp_store_flag)
+      && ! (optab_handler (cstore_optab, int_mode) == CODE_FOR_nothing
 	    && code == NE
-	    && GET_MODE_SIZE (mode) < UNITS_PER_WORD
+	    && GET_MODE_SIZE (int_mode) < UNITS_PER_WORD
 	    && op1 == const0_rtx))
     {
       int want_add = ((STORE_FLAG_VALUE == 1 && normalizep == -1)
@@ -5690,10 +5692,10 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 
       /* Again, for the reverse comparison, use either an addition or a XOR.  */
       if (want_add
-	  && rtx_cost (GEN_INT (normalizep), mode, PLUS, 1,
+	  && rtx_cost (GEN_INT (normalizep), int_mode, PLUS, 1,
 		       optimize_insn_for_speed_p ()) == 0)
 	{
-	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
+	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, int_mode, 0,
 				   STORE_FLAG_VALUE, target_mode);
 	  if (tem != 0)
             tem = expand_binop (target_mode, add_optab, tem,
@@ -5701,10 +5703,10 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 				target, 0, OPTAB_WIDEN);
 	}
       else if (!want_add
-	       && rtx_cost (trueval, mode, XOR, 1,
+	       && rtx_cost (trueval, int_mode, XOR, 1,
 			    optimize_insn_for_speed_p ()) == 0)
 	{
-	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, mode, 0,
+	  tem = emit_store_flag_1 (subtarget, rcode, op0, op1, int_mode, 0,
 				   normalizep, target_mode);
 	  if (tem != 0)
             tem = expand_binop (target_mode, xor_optab, tem, trueval, target,
@@ -5741,10 +5743,10 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
       if (rtx_equal_p (subtarget, op0))
 	subtarget = 0;
 
-      tem = expand_binop (mode, sub_optab, op0, const1_rtx, subtarget, 0,
+      tem = expand_binop (int_mode, sub_optab, op0, const1_rtx, subtarget, 0,
 			  OPTAB_WIDEN);
       if (tem)
-	tem = expand_binop (mode, ior_optab, op0, tem, subtarget, 0,
+	tem = expand_binop (int_mode, ior_optab, op0, tem, subtarget, 0,
 			    OPTAB_WIDEN);
     }
 
@@ -5756,11 +5758,11 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
       if (rtx_equal_p (subtarget, op0))
 	subtarget = 0;
 
-      tem = maybe_expand_shift (RSHIFT_EXPR, mode, op0,
-				GET_MODE_BITSIZE (mode) - 1,
+      tem = maybe_expand_shift (RSHIFT_EXPR, int_mode, op0,
+				GET_MODE_BITSIZE (int_mode) - 1,
 				subtarget, 0);
       if (tem)
-	tem = expand_binop (mode, sub_optab, tem, op0, subtarget, 0,
+	tem = expand_binop (int_mode, sub_optab, tem, op0, subtarget, 0,
 			    OPTAB_WIDEN);
     }
 
@@ -5781,23 +5783,23 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 	 that is compensated by the subsequent overflow when subtracting
 	 one / negating.  */
 
-      if (optab_handler (abs_optab, mode) != CODE_FOR_nothing)
-	tem = expand_unop (mode, abs_optab, op0, subtarget, 1);
-      else if (optab_handler (ffs_optab, mode) != CODE_FOR_nothing)
-	tem = expand_unop (mode, ffs_optab, op0, subtarget, 1);
-      else if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+      if (optab_handler (abs_optab, int_mode) != CODE_FOR_nothing)
+	tem = expand_unop (int_mode, abs_optab, op0, subtarget, 1);
+      else if (optab_handler (ffs_optab, int_mode) != CODE_FOR_nothing)
+	tem = expand_unop (int_mode, ffs_optab, op0, subtarget, 1);
+      else if (GET_MODE_SIZE (int_mode) < UNITS_PER_WORD)
 	{
-	  tem = convert_modes (word_mode, mode, op0, 1);
-	  mode = word_mode;
+	  tem = convert_modes (word_mode, int_mode, op0, 1);
+	  int_mode = word_mode;
 	}
 
       if (tem != 0)
 	{
 	  if (code == EQ)
-	    tem = expand_binop (mode, sub_optab, tem, const1_rtx, subtarget,
-				0, OPTAB_WIDEN);
+	    tem = expand_binop (int_mode, sub_optab, tem, const1_rtx,
+				subtarget, 0, OPTAB_WIDEN);
 	  else
-	    tem = expand_unop (mode, neg_optab, tem, subtarget, 0);
+	    tem = expand_unop (int_mode, neg_optab, tem, subtarget, 0);
 	}
 
       /* If we couldn't do it that way, for NE we can "or" the two's complement
@@ -5813,18 +5815,18 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
 	  if (rtx_equal_p (subtarget, op0))
 	    subtarget = 0;
 
-	  tem = expand_unop (mode, neg_optab, op0, subtarget, 0);
-	  tem = expand_binop (mode, ior_optab, tem, op0, subtarget, 0,
+	  tem = expand_unop (int_mode, neg_optab, op0, subtarget, 0);
+	  tem = expand_binop (int_mode, ior_optab, tem, op0, subtarget, 0,
 			      OPTAB_WIDEN);
 
 	  if (tem && code == EQ)
-	    tem = expand_unop (mode, one_cmpl_optab, tem, subtarget, 0);
+	    tem = expand_unop (int_mode, one_cmpl_optab, tem, subtarget, 0);
 	}
     }
 
   if (tem && normalizep)
-    tem = maybe_expand_shift (RSHIFT_EXPR, mode, tem,
-			      GET_MODE_BITSIZE (mode) - 1,
+    tem = maybe_expand_shift (RSHIFT_EXPR, int_mode, tem,
+			      GET_MODE_BITSIZE (int_mode) - 1,
 			      subtarget, normalizep == 1);
 
   if (tem)
diff --git a/gcc/expr.c b/gcc/expr.c
index 2e59bfd..467c873 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -628,6 +628,7 @@ rtx
 convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
 {
   rtx temp;
+  scalar_int_mode int_mode;
 
   /* If FROM is a SUBREG that indicates that we have already done at least
      the required extension, strip it.  */
@@ -643,7 +644,8 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
   if (mode == oldmode)
     return x;
 
-  if (CONST_SCALAR_INT_P (x) && GET_MODE_CLASS (mode) == MODE_INT)
+  if (CONST_SCALAR_INT_P (x)
+      && is_int_mode (mode, &int_mode))
     {
       /* If the caller did not tell us the old mode, then there is not
 	 much to do with respect to canonicalization.  We have to
@@ -651,24 +653,24 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
       if (GET_MODE_CLASS (oldmode) != MODE_INT)
 	oldmode = MAX_MODE_INT;
       wide_int w = wide_int::from (rtx_mode_t (x, oldmode),
-				   GET_MODE_PRECISION (mode),
+				   GET_MODE_PRECISION (int_mode),
 				   unsignedp ? UNSIGNED : SIGNED);
-      return immed_wide_int_const (w, mode);
+      return immed_wide_int_const (w, int_mode);
     }
 
   /* We can do this with a gen_lowpart if both desired and current modes
      are integer, and this is either a constant integer, a register, or a
      non-volatile MEM. */
-  if (GET_MODE_CLASS (mode) == MODE_INT
-      && GET_MODE_CLASS (oldmode) == MODE_INT
-      && GET_MODE_PRECISION (mode) <= GET_MODE_PRECISION (oldmode)
-      && ((MEM_P (x) && !MEM_VOLATILE_P (x) && direct_load[(int) mode])
+  scalar_int_mode int_oldmode;
+  if (is_int_mode (mode, &int_mode)
+      && is_int_mode (oldmode, &int_oldmode)
+      && GET_MODE_PRECISION (int_mode) <= GET_MODE_PRECISION (int_oldmode)
+      && ((MEM_P (x) && !MEM_VOLATILE_P (x) && direct_load[(int) int_mode])
           || (REG_P (x)
               && (!HARD_REGISTER_P (x)
-                  || HARD_REGNO_MODE_OK (REGNO (x), mode))
-              && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x)))))
-
-   return gen_lowpart (mode, x);
+		  || HARD_REGNO_MODE_OK (REGNO (x), int_mode))
+	      && TRULY_NOOP_TRUNCATION_MODES_P (int_mode, GET_MODE (x)))))
+   return gen_lowpart (int_mode, x);
 
   /* Converting from integer constant into mode is always equivalent to an
      subreg operation.  */
@@ -6846,19 +6848,20 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
 	 be not aligned on a byte boundary; in this case, if it has reverse
 	 storage order, it needs to be accessed as a scalar field with reverse
 	 storage order and we must first put the value into target order.  */
+      scalar_int_mode temp_mode;
       if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
-	  && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT)
+	  && is_int_mode (GET_MODE (temp), &temp_mode))
 	{
-	  HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp));
+	  HOST_WIDE_INT size = GET_MODE_BITSIZE (temp_mode);
 
 	  reverse = TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (exp));
 
 	  if (reverse)
-	    temp = flip_storage_order (GET_MODE (temp), temp);
+	    temp = flip_storage_order (temp_mode, temp);
 
 	  if (bitsize < size
 	      && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
-	    temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
+	    temp = expand_shift (RSHIFT_EXPR, temp_mode, temp,
 				 size - bitsize, NULL_RTX, 1);
 	}
 
@@ -9884,13 +9887,15 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	    || GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
 	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
 	  return const_vector_from_tree (exp);
-	if (GET_MODE_CLASS (mode) == MODE_INT)
+	scalar_int_mode int_mode;
+	if (is_int_mode (mode, &int_mode))
 	  {
 	    if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
 	      return const_scalar_mask_from_tree (exp);
 	    else
 	      {
-		tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
+		tree type_for_mode
+		  = lang_hooks.types.type_for_mode (int_mode, 1);
 		if (type_for_mode)
 		  tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR,
 					type_for_mode, exp);
@@ -10285,9 +10290,9 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 		    && compare_tree_int (index1, TREE_STRING_LENGTH (init)) < 0)
 		  {
 		    tree type = TREE_TYPE (TREE_TYPE (init));
-		    machine_mode mode = TYPE_MODE (type);
+		    scalar_int_mode mode;
 
-		    if (GET_MODE_CLASS (mode) == MODE_INT
+		    if (is_int_mode (TYPE_MODE (type), &mode)
 			&& GET_MODE_SIZE (mode) == 1)
 		      return gen_int_mode (TREE_STRING_POINTER (init)
 					   [TREE_INT_CST_LOW (index1)],
@@ -10305,6 +10310,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	{
 	  unsigned HOST_WIDE_INT idx;
 	  tree field, value;
+	  scalar_int_mode field_mode;
 
 	  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (treeop0),
 				    idx, field, value)
@@ -10317,8 +10323,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 		   the bitfield does not meet either of those conditions,
 		   we can't do this optimization.  */
 		&& (! DECL_BIT_FIELD (field)
-		    || ((GET_MODE_CLASS (DECL_MODE (field)) == MODE_INT)
-			&& (GET_MODE_PRECISION (DECL_MODE (field))
+		    || (is_int_mode (DECL_MODE (field), &field_mode)
+			&& (GET_MODE_PRECISION (field_mode)
 			    <= HOST_BITS_PER_WIDE_INT))))
 	      {
 		if (DECL_BIT_FIELD (field)
@@ -10652,18 +10658,19 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	       and this is for big-endian data, we must put the field
 	       into the high-order bits.  And we must also put it back
 	       into memory order if it has been previously reversed.  */
+	    scalar_int_mode op0_mode;
 	    if (TREE_CODE (type) == RECORD_TYPE
-		&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
+		&& is_int_mode (GET_MODE (op0), &op0_mode))
 	      {
-		HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (op0));
+		HOST_WIDE_INT size = GET_MODE_BITSIZE (op0_mode);
 
 		if (bitsize < size
 		    && reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
-		  op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
+		  op0 = expand_shift (LSHIFT_EXPR, op0_mode, op0,
 				      size - bitsize, op0, 1);
 
 		if (reversep)
-		  op0 = flip_storage_order (GET_MODE (op0), op0);
+		  op0 = flip_storage_order (op0_mode, op0);
 	      }
 
 	    /* If the result type is BLKmode, store the data into a temporary
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6d7b839..c4a2ae3 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -13587,14 +13587,15 @@ fold_read_from_constant_string (tree exp)
 	  string = exp1;
 	}
 
+      scalar_int_mode char_mode;
       if (string
 	  && TYPE_MODE (TREE_TYPE (exp)) == TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))
 	  && TREE_CODE (string) == STRING_CST
 	  && TREE_CODE (index) == INTEGER_CST
 	  && compare_tree_int (index, TREE_STRING_LENGTH (string)) < 0
-	  && (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_TYPE (string))))
-	      == MODE_INT)
-	  && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (string)))) == 1))
+	  && is_int_mode (TYPE_MODE (TREE_TYPE (TREE_TYPE (string))),
+			  &char_mode)
+	  && GET_MODE_SIZE (char_mode) == 1)
 	return build_int_cst_type (TREE_TYPE (exp),
 				   (TREE_STRING_POINTER (string)
 				    [TREE_INT_CST_LOW (index)]));
diff --git a/gcc/machmode.h b/gcc/machmode.h
index b3d2d76..fdbf174 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -695,6 +695,21 @@ 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];
 
+/* Return true if MODE has class MODE_INT, storing it as a scalar_int_mode
+   in *INT_MODE if so.  */
+
+template<typename T>
+inline bool
+is_int_mode (machine_mode mode, T *int_mode)
+{
+  if (GET_MODE_CLASS (mode) == MODE_INT)
+    {
+      *int_mode = scalar_int_mode::from_int (mode);
+      return true;
+    }
+  return false;
+}
+
 namespace mode_iterator
 {
   /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */
diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c
index a26577e..3d932b4 100644
--- a/gcc/optabs-libfuncs.c
+++ b/gcc/optabs-libfuncs.c
@@ -189,8 +189,9 @@ gen_int_libfunc (optab optable, const char *opname, char suffix,
 {
   int maxsize = 2 * BITS_PER_WORD;
   int minsize = BITS_PER_WORD;
+  scalar_int_mode int_mode;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  if (!is_int_mode (mode, &int_mode))
     return;
   if (maxsize < LONG_LONG_TYPE_SIZE)
     maxsize = LONG_LONG_TYPE_SIZE;
@@ -198,10 +199,10 @@ gen_int_libfunc (optab optable, const char *opname, char suffix,
       && (trapv_binoptab_p (optable)
 	  || trapv_unoptab_p (optable)))
     minsize = INT_TYPE_SIZE;
-  if (GET_MODE_BITSIZE (mode) < minsize
-      || GET_MODE_BITSIZE (mode) > maxsize)
+  if (GET_MODE_BITSIZE (int_mode) < minsize
+      || GET_MODE_BITSIZE (int_mode) > maxsize)
     return;
-  gen_libfunc (optable, opname, suffix, mode);
+  gen_libfunc (optable, opname, suffix, int_mode);
 }
 
 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index edafe4a..c8b70c7 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1111,6 +1111,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
        ? OPTAB_WIDEN : methods);
   enum mode_class mclass;
   machine_mode wider_mode;
+  scalar_int_mode int_mode;
   rtx libfunc;
   rtx temp;
   rtx_insn *entry_last = get_last_insn ();
@@ -1159,22 +1160,22 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	&& optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
        || (binoptab == rotr_optab
 	   && optab_handler (rotl_optab, mode) != CODE_FOR_nothing))
-      && mclass == MODE_INT)
+      && is_int_mode (mode, &int_mode))
     {
       optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
       rtx newop1;
-      unsigned int bits = GET_MODE_PRECISION (mode);
+      unsigned int bits = GET_MODE_PRECISION (int_mode);
 
       if (CONST_INT_P (op1))
         newop1 = GEN_INT (bits - INTVAL (op1));
-      else if (targetm.shift_truncation_mask (mode) == bits - 1)
+      else if (targetm.shift_truncation_mask (int_mode) == bits - 1)
         newop1 = negate_rtx (GET_MODE (op1), op1);
       else
         newop1 = expand_binop (GET_MODE (op1), sub_optab,
 			       gen_int_mode (bits, GET_MODE (op1)), op1,
 			       NULL_RTX, unsignedp, OPTAB_DIRECT);
 
-      temp = expand_binop_directly (mode, otheroptab, op0, newop1,
+      temp = expand_binop_directly (int_mode, otheroptab, op0, newop1,
 				    target, unsignedp, methods, last);
       if (temp)
 	return temp;
@@ -1318,8 +1319,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   /* These can be done a word at a time.  */
   if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
-      && mclass == MODE_INT
-      && GET_MODE_SIZE (mode) > UNITS_PER_WORD
+      && is_int_mode (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
       && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
     {
       int i;
@@ -1331,17 +1332,17 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	  || target == op0
 	  || target == op1
 	  || !valid_multiword_target_p (target))
-	target = gen_reg_rtx (mode);
+	target = gen_reg_rtx (int_mode);
 
       start_sequence ();
 
       /* Do the actual arithmetic.  */
-      for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
+      for (i = 0; i < GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD; i++)
 	{
-	  rtx target_piece = operand_subword (target, i, 1, mode);
+	  rtx target_piece = operand_subword (target, i, 1, int_mode);
 	  rtx x = expand_binop (word_mode, binoptab,
-				operand_subword_force (op0, i, mode),
-				operand_subword_force (op1, i, mode),
+				operand_subword_force (op0, i, int_mode),
+				operand_subword_force (op1, i, int_mode),
 				target_piece, unsignedp, next_methods);
 
 	  if (x == 0)
@@ -1354,7 +1355,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       insns = get_insns ();
       end_sequence ();
 
-      if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
+      if (i == GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD)
 	{
 	  emit_insn (insns);
 	  return target;
@@ -1364,10 +1365,10 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
   /* Synthesize double word shifts from single word shifts.  */
   if ((binoptab == lshr_optab || binoptab == ashl_optab
        || binoptab == ashr_optab)
-      && mclass == MODE_INT
+      && is_int_mode (mode, &int_mode)
       && (CONST_INT_P (op1) || optimize_insn_for_speed_p ())
-      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-      && GET_MODE_PRECISION (mode) == GET_MODE_BITSIZE (mode)
+      && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+      && GET_MODE_PRECISION (int_mode) == GET_MODE_BITSIZE (int_mode)
       && optab_handler (binoptab, word_mode) != CODE_FOR_nothing
       && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
       && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
@@ -1375,7 +1376,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
       machine_mode op1_mode;
 
-      double_shift_mask = targetm.shift_truncation_mask (mode);
+      double_shift_mask = targetm.shift_truncation_mask (int_mode);
       shift_mask = targetm.shift_truncation_mask (word_mode);
       op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
 
@@ -1403,7 +1404,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	      || target == op0
 	      || target == op1
 	      || !valid_multiword_target_p (target))
-	    target = gen_reg_rtx (mode);
+	    target = gen_reg_rtx (int_mode);
 
 	  start_sequence ();
 
@@ -1415,11 +1416,11 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	  left_shift = binoptab == ashl_optab;
 	  outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
 
-	  outof_target = operand_subword (target, outof_word, 1, mode);
-	  into_target = operand_subword (target, 1 - outof_word, 1, mode);
+	  outof_target = operand_subword (target, outof_word, 1, int_mode);
+	  into_target = operand_subword (target, 1 - outof_word, 1, int_mode);
 
-	  outof_input = operand_subword_force (op0, outof_word, mode);
-	  into_input = operand_subword_force (op0, 1 - outof_word, mode);
+	  outof_input = operand_subword_force (op0, outof_word, int_mode);
+	  into_input = operand_subword_force (op0, 1 - outof_word, int_mode);
 
 	  if (expand_doubleword_shift (op1_mode, binoptab,
 				       outof_input, into_input, op1,
@@ -1438,9 +1439,9 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   /* Synthesize double word rotates from single word shifts.  */
   if ((binoptab == rotl_optab || binoptab == rotr_optab)
-      && mclass == MODE_INT
+      && is_int_mode (mode, &int_mode)
       && CONST_INT_P (op1)
-      && GET_MODE_PRECISION (mode) == 2 * BITS_PER_WORD
+      && GET_MODE_PRECISION (int_mode) == 2 * BITS_PER_WORD
       && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing
       && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
     {
@@ -1461,7 +1462,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	  || target == op1
 	  || !REG_P (target)
 	  || !valid_multiword_target_p (target))
-	target = gen_reg_rtx (mode);
+	target = gen_reg_rtx (int_mode);
 
       start_sequence ();
 
@@ -1475,11 +1476,11 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       left_shift = (binoptab == rotl_optab);
       outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;
 
-      outof_target = operand_subword (target, outof_word, 1, mode);
-      into_target = operand_subword (target, 1 - outof_word, 1, mode);
+      outof_target = operand_subword (target, outof_word, 1, int_mode);
+      into_target = operand_subword (target, 1 - outof_word, 1, int_mode);
 
-      outof_input = operand_subword_force (op0, outof_word, mode);
-      into_input = operand_subword_force (op0, 1 - outof_word, mode);
+      outof_input = operand_subword_force (op0, outof_word, int_mode);
+      into_input = operand_subword_force (op0, 1 - outof_word, int_mode);
 
       if (shift_count == BITS_PER_WORD)
 	{
@@ -1555,13 +1556,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
   /* These can be done a word at a time by propagating carries.  */
   if ((binoptab == add_optab || binoptab == sub_optab)
-      && mclass == MODE_INT
-      && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
+      && is_int_mode (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) >= 2 * UNITS_PER_WORD
       && optab_handler (binoptab, word_mode) != CODE_FOR_nothing)
     {
       unsigned int i;
       optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
-      const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
+      const unsigned int nwords = GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD;
       rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
       rtx xop0, xop1, xtarget;
 
@@ -1575,10 +1576,10 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 #endif
 
       /* Prepare the operands.  */
-      xop0 = force_reg (mode, op0);
-      xop1 = force_reg (mode, op1);
+      xop0 = force_reg (int_mode, op0);
+      xop1 = force_reg (int_mode, op1);
 
-      xtarget = gen_reg_rtx (mode);
+      xtarget = gen_reg_rtx (int_mode);
 
       if (target == 0 || !REG_P (target) || !valid_multiword_target_p (target))
 	target = xtarget;
@@ -1591,9 +1592,9 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       for (i = 0; i < nwords; i++)
 	{
 	  int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
-	  rtx target_piece = operand_subword (xtarget, index, 1, mode);
-	  rtx op0_piece = operand_subword_force (xop0, index, mode);
-	  rtx op1_piece = operand_subword_force (xop1, index, mode);
+	  rtx target_piece = operand_subword (xtarget, index, 1, int_mode);
+	  rtx op0_piece = operand_subword_force (xop0, index, int_mode);
+	  rtx op1_piece = operand_subword_force (xop1, index, int_mode);
 	  rtx x;
 
 	  /* Main add/subtract of the input operands.  */
@@ -1652,16 +1653,16 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	  carry_in = carry_out;
 	}
 
-      if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
+      if (i == GET_MODE_BITSIZE (int_mode) / (unsigned) BITS_PER_WORD)
 	{
-	  if (optab_handler (mov_optab, mode) != CODE_FOR_nothing
+	  if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing
 	      || ! rtx_equal_p (target, xtarget))
 	    {
 	      rtx_insn *temp = emit_move_insn (target, xtarget);
 
 	      set_dst_reg_note (temp, REG_EQUAL,
 				gen_rtx_fmt_ee (optab_to_code (binoptab),
-						mode, copy_rtx (xop0),
+						int_mode, copy_rtx (xop0),
 						copy_rtx (xop1)),
 				target);
 	    }
@@ -1681,26 +1682,26 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
      try using a signed widening multiply.  */
 
   if (binoptab == smul_optab
-      && mclass == MODE_INT
-      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
+      && is_int_mode (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
       && optab_handler (smul_optab, word_mode) != CODE_FOR_nothing
       && optab_handler (add_optab, word_mode) != CODE_FOR_nothing)
     {
       rtx product = NULL_RTX;
-      if (widening_optab_handler (umul_widen_optab, mode, word_mode)
-	    != CODE_FOR_nothing)
+      if (widening_optab_handler (umul_widen_optab, int_mode, word_mode)
+	  != CODE_FOR_nothing)
 	{
-	  product = expand_doubleword_mult (mode, op0, op1, target,
+	  product = expand_doubleword_mult (int_mode, op0, op1, target,
 					    true, methods);
 	  if (!product)
 	    delete_insns_since (last);
 	}
 
       if (product == NULL_RTX
-	  && widening_optab_handler (smul_widen_optab, mode, word_mode)
-		!= CODE_FOR_nothing)
+	  && (widening_optab_handler (smul_widen_optab, int_mode, word_mode)
+	      != CODE_FOR_nothing))
 	{
-	  product = expand_doubleword_mult (mode, op0, op1, target,
+	  product = expand_doubleword_mult (int_mode, op0, op1, target,
 					    false, methods);
 	  if (!product)
 	    delete_insns_since (last);
@@ -1708,13 +1709,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       if (product != NULL_RTX)
 	{
-	  if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
+	  if (optab_handler (mov_optab, int_mode) != CODE_FOR_nothing)
 	    {
 	      rtx_insn *move = emit_move_insn (target ? target : product,
 					       product);
 	      set_dst_reg_note (move,
 				REG_EQUAL,
-				gen_rtx_fmt_ee (MULT, mode,
+				gen_rtx_fmt_ee (MULT, int_mode,
 						copy_rtx (op0),
 						copy_rtx (op1)),
 				target ? target : product);
@@ -2694,6 +2695,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
   machine_mode wider_mode;
+  scalar_int_mode int_mode;
   scalar_float_mode float_mode;
   rtx temp;
   rtx libfunc;
@@ -2851,24 +2853,24 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 
   /* These can be done a word at a time.  */
   if (unoptab == one_cmpl_optab
-      && mclass == MODE_INT
-      && GET_MODE_SIZE (mode) > UNITS_PER_WORD
+      && is_int_mode (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
       && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
     {
       int i;
       rtx_insn *insns;
 
       if (target == 0 || target == op0 || !valid_multiword_target_p (target))
-	target = gen_reg_rtx (mode);
+	target = gen_reg_rtx (int_mode);
 
       start_sequence ();
 
       /* Do the actual arithmetic.  */
-      for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
+      for (i = 0; i < GET_MODE_BITSIZE (int_mode) / BITS_PER_WORD; i++)
 	{
-	  rtx target_piece = operand_subword (target, i, 1, mode);
+	  rtx target_piece = operand_subword (target, i, 1, int_mode);
 	  rtx x = expand_unop (word_mode, unoptab,
-			       operand_subword_force (op0, i, mode),
+			       operand_subword_force (op0, i, int_mode),
 			       target_piece, unsignedp);
 
 	  if (target_piece != x)
@@ -3114,18 +3116,20 @@ expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
      value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
      where W is the width of MODE.  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT
+  scalar_int_mode int_mode;
+  if (is_int_mode (mode, &int_mode)
       && BRANCH_COST (optimize_insn_for_speed_p (),
 	      	      false) >= 2)
     {
-      rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
-				   GET_MODE_PRECISION (mode) - 1,
+      rtx extended = expand_shift (RSHIFT_EXPR, int_mode, op0,
+				   GET_MODE_PRECISION (int_mode) - 1,
 				   NULL_RTX, 0);
 
-      temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
+      temp = expand_binop (int_mode, xor_optab, extended, op0, target, 0,
 			   OPTAB_LIB_WIDEN);
       if (temp != 0)
-	temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
+	temp = expand_binop (int_mode,
+			     result_unsignedp ? sub_optab : subv_optab,
                              temp, extended, target, 0, OPTAB_LIB_WIDEN);
 
       if (temp != 0)
@@ -3217,15 +3221,16 @@ expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
   /* If this machine has expensive jumps, we can do one's complement
      absolute value of X as (((signed) x >> (W-1)) ^ x).  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT
+  scalar_int_mode int_mode;
+  if (is_int_mode (mode, &int_mode)
       && BRANCH_COST (optimize_insn_for_speed_p (),
 	             false) >= 2)
     {
-      rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
-				   GET_MODE_PRECISION (mode) - 1,
+      rtx extended = expand_shift (RSHIFT_EXPR, int_mode, op0,
+				   GET_MODE_PRECISION (int_mode) - 1,
 				   NULL_RTX, 0);
 
-      temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
+      temp = expand_binop (int_mode, xor_optab, extended, op0, target, 0,
 			   OPTAB_LIB_WIDEN);
 
       if (temp != 0)
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a1387b1..637ed4f 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -77,11 +77,12 @@ mode_signbit_p (machine_mode mode, const_rtx x)
 {
   unsigned HOST_WIDE_INT val;
   unsigned int width;
+  scalar_int_mode int_mode;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  if (!is_int_mode (mode, &int_mode))
     return false;
 
-  width = GET_MODE_PRECISION (mode);
+  width = GET_MODE_PRECISION (int_mode);
   if (width == 0)
     return false;
 
@@ -129,15 +130,16 @@ bool
 val_signbit_p (machine_mode mode, unsigned HOST_WIDE_INT val)
 {
   unsigned int width;
+  scalar_int_mode int_mode;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  if (!is_int_mode (mode, &int_mode))
     return false;
 
-  width = GET_MODE_PRECISION (mode);
+  width = GET_MODE_PRECISION (int_mode);
   if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
     return false;
 
-  val &= GET_MODE_MASK (mode);
+  val &= GET_MODE_MASK (int_mode);
   return val == (HOST_WIDE_INT_1U << (width - 1));
 }
 
@@ -148,10 +150,11 @@ val_signbit_known_set_p (machine_mode mode, unsigned HOST_WIDE_INT val)
 {
   unsigned int width;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  scalar_int_mode int_mode;
+  if (!is_int_mode (mode, &int_mode))
     return false;
 
-  width = GET_MODE_PRECISION (mode);
+  width = GET_MODE_PRECISION (int_mode);
   if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
     return false;
 
@@ -166,10 +169,11 @@ val_signbit_known_clear_p (machine_mode mode, unsigned HOST_WIDE_INT val)
 {
   unsigned int width;
 
-  if (GET_MODE_CLASS (mode) != MODE_INT)
+  scalar_int_mode int_mode;
+  if (!is_int_mode (mode, &int_mode))
     return false;
 
-  width = GET_MODE_PRECISION (mode);
+  width = GET_MODE_PRECISION (int_mode);
   if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
     return false;
 
@@ -4811,18 +4815,19 @@ simplify_relational_operation_1 (enum rtx_code code, machine_mode mode,
 
   /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is
      the same as (zero_extract:SI FOO (const_int 1) BAR).  */
+  scalar_int_mode int_mode;
   if (code == NE
       && op1 == const0_rtx
-      && GET_MODE_CLASS (mode) == MODE_INT
+      && is_int_mode (mode, &int_mode)
       && cmp_mode != VOIDmode
       /* ??? Work-around BImode bugs in the ia64 backend.  */
-      && mode != BImode
+      && int_mode != BImode
       && cmp_mode != BImode
       && nonzero_bits (op0, cmp_mode) == 1
       && STORE_FLAG_VALUE == 1)
-    return GET_MODE_SIZE (mode) > GET_MODE_SIZE (cmp_mode)
-	   ? simplify_gen_unary (ZERO_EXTEND, mode, op0, cmp_mode)
-	   : lowpart_subreg (mode, op0, cmp_mode);
+    return GET_MODE_SIZE (int_mode) > GET_MODE_SIZE (cmp_mode)
+	   ? simplify_gen_unary (ZERO_EXTEND, int_mode, op0, cmp_mode)
+	   : lowpart_subreg (int_mode, op0, cmp_mode);
 
   /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y).  */
   if ((code == EQ || code == NE)
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 91e79ad..1cbef06 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2439,10 +2439,10 @@ vector_type_mode (const_tree t)
       && (!targetm.vector_mode_supported_p (mode)
 	  || !have_regs_of_mode[mode]))
     {
-      machine_mode innermode = TREE_TYPE (t)->type_common.mode;
+      scalar_int_mode innermode;
 
       /* For integers, try mapping it to a same-sized scalar mode.  */
-      if (GET_MODE_CLASS (innermode) == MODE_INT)
+      if (is_int_mode (TREE_TYPE (t)->type_common.mode, &innermode))
 	{
 	  unsigned int size = (TYPE_VECTOR_SUBPARTS (t)
 			       * GET_MODE_BITSIZE (innermode));

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [21/67] Replace SCALAR_INT_MODE_P checks with is_a <scalar_int_mode>
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (21 preceding siblings ...)
  2016-12-09 13:07 ` [22/67] Replace !VECTOR_MODE_P with is_a <scalar_int_mode> Richard Sandiford
@ 2016-12-09 13:07 ` Richard Sandiford
  2016-12-09 13:08 ` [24/67] Replace a != BLKmode check " Richard Sandiford
                   ` (46 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:07 UTC (permalink / raw)
  To: gcc-patches

Replace checks of "SCALAR_INT_MODE_P (...)" with
"is_a <scalar_int_mode> (..., &var)" in cases where it
becomes useful to refer to the mode as a scalar_int_mode.
Also:

- Replace some lingering checks for the two constituent
  classes (MODE_INT and MODE_PARTIAL_INT)

- Introduce is_a <scalar_int_mode> checks for some uses of
  HWI_COMPUTABLE_MODE_P, which is a subcondition of
  SCALAR_INT_MODE_P.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* wide-int.h (int_traits<unsigned char>) New class.
	(int_traits<unsigned short>) Likewise.
	* cfgexpand.c (expand_debug_expr): Use is_a <scalar_int_mode>.
	Use GET_MODE_UNIT_PRECISION and remove redundant test for
	SCALAR_INT_MODE_P.
	* combine.c (set_nonzero_bits_and_sign_copies): Use
	is_a <scalar_int_mode>.
	(find_split_point): Likewise.
	(combine_simplify_rtx): Likewise.
	(simplify_logical): Likewise.
	(expand_compound_operation): Likewise.
	(expand_field_assignment): Likewise.
	(make_compound_operation): Likewise.
	(extended_count): Likewise.
	(change_zero_ext): Likewise.
	(simplify_comparison): Likewise.
	* dwarf2out.c (scompare_loc_descriptor): Likewise.
	(ucompare_loc_descriptor): Likewise.
	(minmax_loc_descriptor): Likewise.
	(mem_loc_descriptor): Likewise.
	(loc_descriptor): Likewise.
	* expmed.c (init_expmed_one_mode): Likewise.
	* lra-constraints.c (lra_constraint_offset): Likewise.
	* optabs.c (prepare_libcall_arg): Likewise.
	* postreload.c (move2add_note_store): Likewise.
	* reload.c (operands_match_p): Likewise.
	* rtl.h (load_extend_op): Likewise.
	* rtlhooks.c (gen_lowpart_general): Likewise.
	* simplify-rtx.c (simplify_truncation): Likewise.
	(simplify_unary_operation_1): Likewise.
	(simplify_binary_operation_1): Likewise.
	(simplify_const_binary_operation): Likewise.
	(simplify_const_relational_operation): Likewise.
	(simplify_subreg): Likewise.
	* stor-layout.c (bitwise_mode_for_mode): Likewise.
	* var-tracking.c (adjust_mems): Likewise.
	(prepare_call_arguments): Likewise.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/decl.c (check_ok_for_atomic_type): Use
	is_a <scalar_int_mode>.
	* gcc-interface/trans.c (Pragma_to_gnu): Likewise.
	* gcc-interface/utils.c (gnat_type_for_mode): Likewise.

gcc/fortran/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* trans-types.c (gfc_type_for_mode): Use is_a <scalar_int_mode>.

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 843024e..e300892 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -8753,9 +8753,10 @@ check_ok_for_atomic_type (tree type, Entity_Id gnat_entity, bool component_p)
 
   /* Consider all aligned floating-point types atomic and any aligned types
      that are represented by integers no wider than a machine word.  */
+  scalar_int_mode int_mode;
   if ((mclass == MODE_FLOAT
-       || ((mclass == MODE_INT || mclass == MODE_PARTIAL_INT)
-	   && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD))
+       || (is_a <scalar_int_mode> (mode, &int_mode)
+	   && GET_MODE_BITSIZE (int_mode) <= BITS_PER_WORD))
       && align >= GET_MODE_ALIGNMENT (mode))
     return;
 
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index e5047f0..da4408e 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -1268,6 +1268,7 @@ Pragma_to_gnu (Node_Id gnat_node)
 	  tree gnu_expr = gnat_to_gnu (gnat_expr);
 	  int use_address;
 	  machine_mode mode;
+	  scalar_int_mode int_mode;
 	  tree asm_constraint = NULL_TREE;
 #ifdef ASM_COMMENT_START
 	  char *comment;
@@ -1279,9 +1280,8 @@ Pragma_to_gnu (Node_Id gnat_node)
 	  /* Use the value only if it fits into a normal register,
 	     otherwise use the address.  */
 	  mode = TYPE_MODE (TREE_TYPE (gnu_expr));
-	  use_address = ((GET_MODE_CLASS (mode) != MODE_INT
-			  && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
-			 || GET_MODE_SIZE (mode) > UNITS_PER_WORD);
+	  use_address = (!is_a <scalar_int_mode> (mode, &int_mode)
+			 || GET_MODE_SIZE (int_mode) > UNITS_PER_WORD);
 
 	  if (use_address)
 	    gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_expr);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 937691c..4e0b7fe5 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -3417,8 +3417,9 @@ gnat_type_for_mode (machine_mode mode, int unsignedp)
     return float_type_for_precision (GET_MODE_PRECISION (float_mode),
 				     float_mode);
 
-  if (SCALAR_INT_MODE_P (mode))
-    return gnat_type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode, &int_mode))
+    return gnat_type_for_size (GET_MODE_BITSIZE (int_mode), unsignedp);
 
   if (VECTOR_MODE_P (mode))
     {
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index b531996..f94be27 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4128,6 +4128,7 @@ expand_debug_expr (tree exp)
   machine_mode inner_mode = VOIDmode;
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
   addr_space_t as;
+  scalar_int_mode op1_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -4177,16 +4178,10 @@ expand_debug_expr (tree exp)
 	case WIDEN_LSHIFT_EXPR:
 	  /* Ensure second operand isn't wider than the first one.  */
 	  inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
-	  if (SCALAR_INT_MODE_P (inner_mode))
-	    {
-	      machine_mode opmode = mode;
-	      if (VECTOR_MODE_P (mode))
-		opmode = GET_MODE_INNER (mode);
-	      if (SCALAR_INT_MODE_P (opmode)
-		  && (GET_MODE_PRECISION (opmode)
-		      < GET_MODE_PRECISION (inner_mode)))
-		op1 = lowpart_subreg (opmode, op1, inner_mode);
-	    }
+	  if (is_a <scalar_int_mode> (inner_mode, &op1_mode)
+	      && (GET_MODE_UNIT_PRECISION (mode)
+		  < GET_MODE_PRECISION (op1_mode)))
+	    op1 = lowpart_subreg (GET_MODE_INNER (mode), op1, op1_mode);
 	  break;
 	default:
 	  break;
diff --git a/gcc/combine.c b/gcc/combine.c
index 5168488..2e2acea 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1701,6 +1701,7 @@ static void
 set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 {
   rtx_insn *insn = (rtx_insn *) data;
+  scalar_int_mode mode;
 
   if (REG_P (x)
       && REGNO (x) >= FIRST_PSEUDO_REGISTER
@@ -1708,13 +1709,14 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 	 say what its contents were.  */
       && ! REGNO_REG_SET_P
 	   (DF_LR_IN (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb), REGNO (x))
-      && HWI_COMPUTABLE_MODE_P (GET_MODE (x)))
+      && is_a <scalar_int_mode> (GET_MODE (x), &mode)
+      && HWI_COMPUTABLE_MODE_P (mode))
     {
       reg_stat_type *rsp = &reg_stat[REGNO (x)];
 
       if (set == 0 || GET_CODE (set) == CLOBBER)
 	{
-	  rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+	  rsp->nonzero_bits = GET_MODE_MASK (mode);
 	  rsp->sign_bit_copies = 1;
 	  return;
 	}
@@ -1744,7 +1746,7 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 	      break;
 	  if (!link)
 	    {
-	      rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+	      rsp->nonzero_bits = GET_MODE_MASK (mode);
 	      rsp->sign_bit_copies = 1;
 	      return;
 	    }
@@ -1763,7 +1765,7 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
 	update_rsp_from_reg_equal (rsp, insn, set, x);
       else
 	{
-	  rsp->nonzero_bits = GET_MODE_MASK (GET_MODE (x));
+	  rsp->nonzero_bits = GET_MODE_MASK (mode);
 	  rsp->sign_bit_copies = 1;
 	}
     }
@@ -4901,37 +4903,38 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
       /* See if this is a bitfield assignment with everything constant.  If
 	 so, this is an IOR of an AND, so split it into that.  */
       if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
-	  && HWI_COMPUTABLE_MODE_P (GET_MODE (XEXP (SET_DEST (x), 0)))
+	  && is_a <scalar_int_mode> (GET_MODE (XEXP (SET_DEST (x), 0)),
+				     &inner_mode)
+	  && HWI_COMPUTABLE_MODE_P (inner_mode)
 	  && CONST_INT_P (XEXP (SET_DEST (x), 1))
 	  && CONST_INT_P (XEXP (SET_DEST (x), 2))
 	  && CONST_INT_P (SET_SRC (x))
 	  && ((INTVAL (XEXP (SET_DEST (x), 1))
 	       + INTVAL (XEXP (SET_DEST (x), 2)))
-	      <= GET_MODE_PRECISION (GET_MODE (XEXP (SET_DEST (x), 0))))
+	      <= GET_MODE_PRECISION (inner_mode))
 	  && ! side_effects_p (XEXP (SET_DEST (x), 0)))
 	{
 	  HOST_WIDE_INT pos = INTVAL (XEXP (SET_DEST (x), 2));
 	  unsigned HOST_WIDE_INT len = INTVAL (XEXP (SET_DEST (x), 1));
 	  unsigned HOST_WIDE_INT src = INTVAL (SET_SRC (x));
 	  rtx dest = XEXP (SET_DEST (x), 0);
-	  machine_mode mode = GET_MODE (dest);
 	  unsigned HOST_WIDE_INT mask
 	    = (HOST_WIDE_INT_1U << len) - 1;
 	  rtx or_mask;
 
 	  if (BITS_BIG_ENDIAN)
-	    pos = GET_MODE_PRECISION (mode) - len - pos;
+	    pos = GET_MODE_PRECISION (inner_mode) - len - pos;
 
-	  or_mask = gen_int_mode (src << pos, mode);
+	  or_mask = gen_int_mode (src << pos, inner_mode);
 	  if (src == mask)
 	    SUBST (SET_SRC (x),
-		   simplify_gen_binary (IOR, mode, dest, or_mask));
+		   simplify_gen_binary (IOR, inner_mode, dest, or_mask));
 	  else
 	    {
-	      rtx negmask = gen_int_mode (~(mask << pos), mode);
+	      rtx negmask = gen_int_mode (~(mask << pos), inner_mode);
 	      SUBST (SET_SRC (x),
-		     simplify_gen_binary (IOR, mode,
-					  simplify_gen_binary (AND, mode,
+		     simplify_gen_binary (IOR, inner_mode,
+					  simplify_gen_binary (AND, inner_mode,
 							       dest, negmask),
 					  or_mask));
 	    }
@@ -5771,15 +5774,18 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	  return temp;
 
 	/* If op is known to have all lower bits zero, the result is zero.  */
+	scalar_int_mode int_mode, int_op0_mode;
 	if (!in_dest
-	    && SCALAR_INT_MODE_P (mode)
-	    && SCALAR_INT_MODE_P (op0_mode)
-	    && GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (op0_mode)
-	    && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
-	    && HWI_COMPUTABLE_MODE_P (op0_mode)
-	    && (nonzero_bits (SUBREG_REG (x), op0_mode)
-		& GET_MODE_MASK (mode)) == 0)
-	  return CONST0_RTX (mode);
+	    && is_a <scalar_int_mode> (mode, &int_mode)
+	    && is_a <scalar_int_mode> (op0_mode, &int_op0_mode)
+	    && (GET_MODE_PRECISION (int_mode)
+		< GET_MODE_PRECISION (int_op0_mode))
+	    && (subreg_lowpart_offset (int_mode, int_op0_mode)
+		== SUBREG_BYTE (x))
+	    && HWI_COMPUTABLE_MODE_P (int_op0_mode)
+	    && (nonzero_bits (SUBREG_REG (x), int_op0_mode)
+		& GET_MODE_MASK (int_mode)) == 0)
+	  return CONST0_RTX (int_mode);
       }
 
       /* Don't change the mode of the MEM if that would change the meaning
@@ -5887,12 +5893,13 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	 sign_extract.  The `and' may be a zero_extend and the two
 	 <c>, -<c> constants may be reversed.  */
       if (GET_CODE (XEXP (x, 0)) == XOR
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && CONST_INT_P (XEXP (x, 1))
 	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
 	  && INTVAL (XEXP (x, 1)) == -INTVAL (XEXP (XEXP (x, 0), 1))
 	  && ((i = exact_log2 (UINTVAL (XEXP (XEXP (x, 0), 1)))) >= 0
 	      || (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0)
-	  && HWI_COMPUTABLE_MODE_P (mode)
+	  && HWI_COMPUTABLE_MODE_P (int_mode)
 	  && ((GET_CODE (XEXP (XEXP (x, 0), 0)) == AND
 	       && CONST_INT_P (XEXP (XEXP (XEXP (x, 0), 0), 1))
 	       && (UINTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))
@@ -5901,11 +5908,11 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 		  && (GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)))
 		      == (unsigned int) i + 1))))
 	return simplify_shift_const
-	  (NULL_RTX, ASHIFTRT, mode,
-	   simplify_shift_const (NULL_RTX, ASHIFT, mode,
+	  (NULL_RTX, ASHIFTRT, int_mode,
+	   simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
 				 XEXP (XEXP (XEXP (x, 0), 0), 0),
-				 GET_MODE_PRECISION (mode) - (i + 1)),
-	   GET_MODE_PRECISION (mode) - (i + 1));
+				 GET_MODE_PRECISION (int_mode) - (i + 1)),
+	   GET_MODE_PRECISION (int_mode) - (i + 1));
 
       /* If only the low-order bit of X is possibly nonzero, (plus x -1)
 	 can become (ashiftrt (ashift (xor x 1) C) C) where C is
@@ -6926,6 +6933,7 @@ simplify_logical (rtx x)
   machine_mode mode = GET_MODE (x);
   rtx op0 = XEXP (x, 0);
   rtx op1 = XEXP (x, 1);
+  scalar_int_mode int_mode;
 
   switch (GET_CODE (x))
     {
@@ -6933,11 +6941,12 @@ simplify_logical (rtx x)
       /* We can call simplify_and_const_int only if we don't lose
 	 any (sign) bits when converting INTVAL (op1) to
 	 "unsigned HOST_WIDE_INT".  */
-      if (CONST_INT_P (op1)
-	  && (HWI_COMPUTABLE_MODE_P (mode)
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && CONST_INT_P (op1)
+	  && (HWI_COMPUTABLE_MODE_P (int_mode)
 	      || INTVAL (op1) > 0))
 	{
-	  x = simplify_and_const_int (x, mode, op0, INTVAL (op1));
+	  x = simplify_and_const_int (x, int_mode, op0, INTVAL (op1));
 	  if (GET_CODE (x) != AND)
 	    return x;
 
@@ -7008,6 +7017,7 @@ expand_compound_operation (rtx x)
   int unsignedp = 0;
   unsigned int modewidth;
   rtx tem;
+  scalar_int_mode inner_mode;
 
   switch (GET_CODE (x))
     {
@@ -7026,25 +7036,24 @@ expand_compound_operation (rtx x)
       if (CONST_INT_P (XEXP (x, 0)))
 	return x;
 
+      /* Reject modes that aren't scalar integers because turning vector
+	 or complex modes into shifts causes problems.  */
+      if (!is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &inner_mode))
+	return x;
+
       /* Return if (subreg:MODE FROM 0) is not a safe replacement for
 	 (zero_extend:MODE FROM) or (sign_extend:MODE FROM).  It is for any MEM
 	 because (SUBREG (MEM...)) is guaranteed to cause the MEM to be
 	 reloaded. If not for that, MEM's would very rarely be safe.
 
-	 Reject MODEs bigger than a word, because we might not be able
+	 Reject modes bigger than a word, because we might not be able
 	 to reference a two-register group starting with an arbitrary register
 	 (and currently gen_lowpart might crash for a SUBREG).  */
 
-      if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) > UNITS_PER_WORD)
+      if (GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
 	return x;
 
-      /* Reject MODEs that aren't scalar integers because turning vector
-	 or complex modes into shifts causes problems.  */
-
-      if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
-	return x;
-
-      len = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
+      len = GET_MODE_PRECISION (inner_mode);
       /* If the inner object has VOIDmode (the only way this can happen
 	 is if it is an ASM_OPERANDS), we can't do anything since we don't
 	 know how much masking to do.  */
@@ -7064,25 +7073,23 @@ expand_compound_operation (rtx x)
 	return XEXP (x, 0);
 
       if (!CONST_INT_P (XEXP (x, 1))
-	  || !CONST_INT_P (XEXP (x, 2))
-	  || GET_MODE (XEXP (x, 0)) == VOIDmode)
+	  || !CONST_INT_P (XEXP (x, 2)))
 	return x;
 
-      /* Reject MODEs that aren't scalar integers because turning vector
+      /* Reject modes that aren't scalar integers because turning vector
 	 or complex modes into shifts causes problems.  */
-
-      if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
+      if (!is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &inner_mode))
 	return x;
 
       len = INTVAL (XEXP (x, 1));
       pos = INTVAL (XEXP (x, 2));
 
       /* This should stay within the object being extracted, fail otherwise.  */
-      if (len + pos > GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))))
+      if (len + pos > GET_MODE_PRECISION (inner_mode))
 	return x;
 
       if (BITS_BIG_ENDIAN)
-	pos = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))) - len - pos;
+	pos = GET_MODE_PRECISION (inner_mode) - len - pos;
 
       break;
 
@@ -7093,12 +7100,10 @@ expand_compound_operation (rtx x)
      bit is not set, as this is easier to optimize.  It will be converted
      back to cheaper alternative in make_extraction.  */
   if (GET_CODE (x) == SIGN_EXTEND
-      && (HWI_COMPUTABLE_MODE_P (GET_MODE (x))
-	  && ((nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
-		& ~(((unsigned HOST_WIDE_INT)
-		      GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
-		     >> 1))
-	       == 0)))
+      && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
+      && ((nonzero_bits (XEXP (x, 0), inner_mode)
+	   & ~(((unsigned HOST_WIDE_INT) GET_MODE_MASK (inner_mode)) >> 1))
+	  == 0))
     {
       machine_mode mode = GET_MODE (x);
       rtx temp = gen_rtx_ZERO_EXTEND (mode, XEXP (x, 0));
@@ -7125,7 +7130,7 @@ expand_compound_operation (rtx x)
 	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
 	  && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
 	  && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
-	      & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+	      & ~GET_MODE_MASK (inner_mode)) == 0)
 	return XEXP (XEXP (x, 0), 0);
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
@@ -7134,7 +7139,7 @@ expand_compound_operation (rtx x)
 	  && subreg_lowpart_p (XEXP (x, 0))
 	  && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
 	  && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
-	      & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+	      & ~GET_MODE_MASK (inner_mode)) == 0)
 	return SUBREG_REG (XEXP (x, 0));
 
       /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo
@@ -7144,9 +7149,8 @@ expand_compound_operation (rtx x)
       if (GET_CODE (XEXP (x, 0)) == TRUNCATE
 	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
 	  && COMPARISON_P (XEXP (XEXP (x, 0), 0))
-	  && (GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
-	      <= HOST_BITS_PER_WIDE_INT)
-	  && (STORE_FLAG_VALUE & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+	  && GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
+	  && (STORE_FLAG_VALUE & ~GET_MODE_MASK (inner_mode)) == 0)
 	return XEXP (XEXP (x, 0), 0);
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
@@ -7154,9 +7158,8 @@ expand_compound_operation (rtx x)
 	  && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
 	  && subreg_lowpart_p (XEXP (x, 0))
 	  && COMPARISON_P (SUBREG_REG (XEXP (x, 0)))
-	  && (GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
-	      <= HOST_BITS_PER_WIDE_INT)
-	  && (STORE_FLAG_VALUE & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+	  && GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
+	  && (STORE_FLAG_VALUE & ~GET_MODE_MASK (inner_mode)) == 0)
 	return SUBREG_REG (XEXP (x, 0));
 
     }
@@ -7221,7 +7224,7 @@ expand_field_assignment (const_rtx x)
   rtx pos;			/* Always counts from low bit.  */
   int len;
   rtx mask, cleared, masked;
-  machine_mode compute_mode;
+  scalar_int_mode compute_mode;
 
   /* Loop until we find something we can't simplify.  */
   while (1)
@@ -7289,17 +7292,15 @@ expand_field_assignment (const_rtx x)
       while (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner))
 	inner = SUBREG_REG (inner);
 
-      compute_mode = GET_MODE (inner);
-
       /* Don't attempt bitwise arithmetic on non scalar integer modes.  */
-      if (! SCALAR_INT_MODE_P (compute_mode))
+      if (!is_a <scalar_int_mode> (GET_MODE (inner), &compute_mode))
 	{
 	  /* Don't do anything for vector or complex integral types.  */
-	  if (! FLOAT_MODE_P (compute_mode))
+	  if (! FLOAT_MODE_P (GET_MODE (inner)))
 	    break;
 
 	  /* Try to find an integral mode to pun with.  */
-	  if (!int_mode_for_size (GET_MODE_BITSIZE (compute_mode), 0)
+	  if (!int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (inner)), 0)
 	      .exists (&compute_mode))
 	    break;
 
@@ -8246,10 +8247,11 @@ make_compound_operation (rtx x, enum rtx_code in_code)
 		  && XEXP (x, 1) == const0_rtx) ? COMPARE
 	       : in_code == COMPARE || in_code == EQ ? SET : in_code);
 
-  if (SCALAR_INT_MODE_P (GET_MODE (x)))
+  scalar_int_mode mode;
+  if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
     {
-      rtx new_rtx = make_compound_operation_int (GET_MODE (x), &x,
-						 in_code, &next_code);
+      rtx new_rtx = make_compound_operation_int (mode, &x, in_code,
+						 &next_code);
       if (new_rtx)
 	return new_rtx;
       code = GET_CODE (x);
@@ -10069,10 +10071,12 @@ extended_count (const_rtx x, machine_mode mode, int unsignedp)
   if (nonzero_sign_valid == 0)
     return 0;
 
+  scalar_int_mode int_mode;
   return (unsignedp
-	  ? (HWI_COMPUTABLE_MODE_P (mode)
-	     ? (unsigned int) (GET_MODE_PRECISION (mode) - 1
-			       - floor_log2 (nonzero_bits (x, mode)))
+	  ? (is_a <scalar_int_mode> (mode, &int_mode)
+	     && HWI_COMPUTABLE_MODE_P (int_mode)
+	     ? (unsigned int) (GET_MODE_PRECISION (int_mode) - 1
+			       - floor_log2 (nonzero_bits (x, int_mode)))
 	     : 0)
 	  : num_sign_bit_copies (x, mode) - 1);
 }
@@ -11241,7 +11245,9 @@ change_zero_ext (rtx pat)
   FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST)
     {
       rtx x = **iter;
-      machine_mode mode = GET_MODE (x);
+      scalar_int_mode mode;
+      if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
+	continue;
       int size;
 
       if (GET_CODE (x) == ZERO_EXTRACT
@@ -11261,7 +11267,6 @@ change_zero_ext (rtx pat)
 	    x = XEXP (x, 0);
 	}
       else if (GET_CODE (x) == ZERO_EXTEND
-	       && SCALAR_INT_MODE_P (mode)
 	       && GET_CODE (XEXP (x, 0)) == SUBREG
 	       && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (XEXP (x, 0))))
 	       && !paradoxical_subreg_p (XEXP (x, 0))
@@ -11273,7 +11278,6 @@ change_zero_ext (rtx pat)
 	    x = gen_lowpart_SUBREG (mode, x);
 	}
       else if (GET_CODE (x) == ZERO_EXTEND
-	       && SCALAR_INT_MODE_P (mode)
 	       && REG_P (XEXP (x, 0))
 	       && HARD_REGISTER_P (XEXP (x, 0))
 	       && can_change_dest_mode (XEXP (x, 0), 0, mode))
@@ -12356,11 +12360,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	  if (GET_CODE (XEXP (op0, 0)) == SUBREG
 	      && CONST_INT_P (XEXP (op0, 1)))
 	    {
-	      tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
 	      unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
 	      /* Require an integral mode, to avoid creating something like
 		 (AND:SF ...).  */
-	      if (SCALAR_INT_MODE_P (tmode)
+	      if ((is_a <scalar_int_mode>
+		   (GET_MODE (SUBREG_REG (XEXP (op0, 0))), &tmode))
 		  /* It is unsafe to commute the AND into the SUBREG if the
 		     SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
 		     not defined.  As originally written the upper bits
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 2af401c..19e6d24 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -13766,10 +13766,11 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
   if (op_mode == VOIDmode)
     return NULL;
 
+  scalar_int_mode int_op_mode;
   if (dwarf_strict
       && dwarf_version < 5
-      && (!SCALAR_INT_MODE_P (op_mode)
-	  || GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE))
+      && (!is_a <scalar_int_mode> (op_mode, &int_op_mode)
+	  || GET_MODE_SIZE (int_op_mode) > DWARF2_ADDR_SIZE))
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
@@ -13780,13 +13781,13 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
   if (op0 == NULL || op1 == NULL)
     return NULL;
 
-  if (!SCALAR_INT_MODE_P (op_mode)
-      || GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE)
+  if (!is_a <scalar_int_mode> (op_mode, &int_op_mode)
+      || GET_MODE_SIZE (int_op_mode) == DWARF2_ADDR_SIZE)
     return compare_loc_descriptor (op, op0, op1);
 
-  if (GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
+  if (GET_MODE_SIZE (int_op_mode) > DWARF2_ADDR_SIZE)
     {
-      dw_die_ref type_die = base_type_for_mode (op_mode, 0);
+      dw_die_ref type_die = base_type_for_mode (int_op_mode, 0);
       dw_loc_descr_ref cvt;
 
       if (type_die == NULL)
@@ -13804,7 +13805,7 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
       return compare_loc_descriptor (op, op0, op1);
     }
 
-  shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode)) * BITS_PER_UNIT;
+  shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (int_op_mode)) * BITS_PER_UNIT;
   /* For eq/ne, if the operands are known to be zero-extended,
      there is no need to do the fancy shifting up.  */
   if (op == DW_OP_eq || op == DW_OP_ne)
@@ -13817,15 +13818,17 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
       /* deref_size zero extends, and for constants we can check
 	 whether they are zero extended or not.  */
       if (((last0->dw_loc_opc == DW_OP_deref_size
-	    && last0->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode))
+	    && last0->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (int_op_mode))
 	   || (CONST_INT_P (XEXP (rtl, 0))
 	       && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0))
-		  == (INTVAL (XEXP (rtl, 0)) & GET_MODE_MASK (op_mode))))
+		  == (INTVAL (XEXP (rtl, 0)) & GET_MODE_MASK (int_op_mode))))
 	  && ((last1->dw_loc_opc == DW_OP_deref_size
-	       && last1->dw_loc_oprnd1.v.val_int <= GET_MODE_SIZE (op_mode))
+	       && (last1->dw_loc_oprnd1.v.val_int
+		   <= GET_MODE_SIZE (int_op_mode)))
 	      || (CONST_INT_P (XEXP (rtl, 1))
 		  && (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 1))
-		     == (INTVAL (XEXP (rtl, 1)) & GET_MODE_MASK (op_mode)))))
+		     == (INTVAL (XEXP (rtl, 1))
+			 & GET_MODE_MASK (int_op_mode)))))
 	return compare_loc_descriptor (op, op0, op1);
 
       /* EQ/NE comparison against constant in narrower type than
@@ -13836,17 +13839,18 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
 	 DW_OP_const*u <mode_mask> DW_OP_and DW_OP_const* <cst & mode_mask>
 	 DW_OP_{eq,ne}.  Pick whatever is shorter.  */
       if (CONST_INT_P (XEXP (rtl, 1))
-	  && GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
+	  && GET_MODE_BITSIZE (int_op_mode) < HOST_BITS_PER_WIDE_INT
 	  && (size_of_int_loc_descriptor (shift) + 1
 	      + size_of_int_loc_descriptor (UINTVAL (XEXP (rtl, 1)) << shift)
-	      >= size_of_int_loc_descriptor (GET_MODE_MASK (op_mode)) + 1
+	      >= size_of_int_loc_descriptor (GET_MODE_MASK (int_op_mode)) + 1
 		 + size_of_int_loc_descriptor (INTVAL (XEXP (rtl, 1))
-					       & GET_MODE_MASK (op_mode))))
+					       & GET_MODE_MASK (int_op_mode))))
 	{
-	  add_loc_descr (&op0, int_loc_descriptor (GET_MODE_MASK (op_mode)));
+	  add_loc_descr (&op0,
+			 int_loc_descriptor (GET_MODE_MASK (int_op_mode)));
 	  add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
 	  op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1))
-				    & GET_MODE_MASK (op_mode));
+				    & GET_MODE_MASK (int_op_mode));
 	  return compare_loc_descriptor (op, op0, op1);
 	}
     }
@@ -13875,25 +13879,27 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
     op_mode = GET_MODE (XEXP (rtl, 1));
   if (op_mode == VOIDmode)
     return NULL;
-  if (!SCALAR_INT_MODE_P (op_mode))
+
+  scalar_int_mode int_op_mode;
+  if (!is_a <scalar_int_mode> (op_mode, &int_op_mode))
     return NULL;
 
   if (dwarf_strict
       && dwarf_version < 5
-      && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
+      && GET_MODE_SIZE (int_op_mode) > DWARF2_ADDR_SIZE)
     return NULL;
 
-  op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
+  op0 = mem_loc_descriptor (XEXP (rtl, 0), int_op_mode, mem_mode,
 			    VAR_INIT_STATUS_INITIALIZED);
-  op1 = mem_loc_descriptor (XEXP (rtl, 1), op_mode, mem_mode,
+  op1 = mem_loc_descriptor (XEXP (rtl, 1), int_op_mode, mem_mode,
 			    VAR_INIT_STATUS_INITIALIZED);
 
   if (op0 == NULL || op1 == NULL)
     return NULL;
 
-  if (GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
+  if (GET_MODE_SIZE (int_op_mode) < DWARF2_ADDR_SIZE)
     {
-      HOST_WIDE_INT mask = GET_MODE_MASK (op_mode);
+      HOST_WIDE_INT mask = GET_MODE_MASK (int_op_mode);
       dw_loc_descr_ref last0, last1;
       for (last0 = op0; last0->dw_loc_next != NULL; last0 = last0->dw_loc_next)
 	;
@@ -13903,7 +13909,7 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
 	op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask);
       /* deref_size zero extends, so no need to mask it again.  */
       else if (last0->dw_loc_opc != DW_OP_deref_size
-	       || last0->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode))
+	       || last0->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (int_op_mode))
 	{
 	  add_loc_descr (&op0, int_loc_descriptor (mask));
 	  add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
@@ -13912,13 +13918,13 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
 	op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask);
       /* deref_size zero extends, so no need to mask it again.  */
       else if (last1->dw_loc_opc != DW_OP_deref_size
-	       || last1->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (op_mode))
+	       || last1->dw_loc_oprnd1.v.val_int > GET_MODE_SIZE (int_op_mode))
 	{
 	  add_loc_descr (&op1, int_loc_descriptor (mask));
 	  add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
 	}
     }
-  else if (GET_MODE_SIZE (op_mode) == DWARF2_ADDR_SIZE)
+  else if (GET_MODE_SIZE (int_op_mode) == DWARF2_ADDR_SIZE)
     {
       HOST_WIDE_INT bias = 1;
       bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
@@ -13943,10 +13949,11 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref op0, op1, ret;
   dw_loc_descr_ref bra_node, drop_node;
 
+  scalar_int_mode int_mode;
   if (dwarf_strict
       && dwarf_version < 5
-      && (!SCALAR_INT_MODE_P (mode)
-	  || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE))
+      && (!is_a <scalar_int_mode> (mode, &int_mode)
+	  || GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE))
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -13978,19 +13985,19 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
 	  add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0));
 	}
     }
-  else if (!SCALAR_INT_MODE_P (mode)
-	   && GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
+  else if (is_a <scalar_int_mode> (mode, &int_mode)
+	   && GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE)
     {
-      int shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (mode)) * BITS_PER_UNIT;
+      int shift = (DWARF2_ADDR_SIZE - GET_MODE_SIZE (int_mode)) * BITS_PER_UNIT;
       add_loc_descr (&op0, int_loc_descriptor (shift));
       add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
       add_loc_descr (&op1, int_loc_descriptor (shift));
       add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
     }
-  else if (SCALAR_INT_MODE_P (mode)
-	   && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
+  else if (is_a <scalar_int_mode> (mode, &int_mode)
+	   && GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
     {
-      dw_die_ref type_die = base_type_for_mode (mode, 0);
+      dw_die_ref type_die = base_type_for_mode (int_mode, 0);
       dw_loc_descr_ref cvt;
       if (type_die == NULL)
 	return NULL;
@@ -14021,9 +14028,9 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
   bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
   bra_node->dw_loc_oprnd1.v.val_loc = drop_node;
   if ((GET_CODE (rtl) == SMIN || GET_CODE (rtl) == SMAX)
-      && SCALAR_INT_MODE_P (mode)
-      && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
-    ret = convert_descriptor_to_mode (mode, ret);
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
+    ret = convert_descriptor_to_mode (int_mode, ret);
   return ret;
 }
 
@@ -14484,6 +14491,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
   if (mode != GET_MODE (rtl) && GET_MODE (rtl) != VOIDmode)
     return NULL;
 
+  scalar_int_mode int_mode, inner_mode;
   switch (GET_CODE (rtl))
     {
     case POST_INC:
@@ -14504,29 +14512,26 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case TRUNCATE:
       if (inner == NULL_RTX)
         inner = XEXP (rtl, 0);
-      if (SCALAR_INT_MODE_P (mode)
-	  && SCALAR_INT_MODE_P (GET_MODE (inner))
-	  && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (inner), &inner_mode)
+	  && (GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
-	      || (mode == Pmode && mem_mode != VOIDmode)
+	      || (int_mode == Pmode && mem_mode != VOIDmode)
 #endif
 	     )
-	  && GET_MODE_SIZE (GET_MODE (inner)) <= DWARF2_ADDR_SIZE)
+	  && GET_MODE_SIZE (inner_mode) <= DWARF2_ADDR_SIZE)
 	{
 	  mem_loc_result = mem_loc_descriptor (inner,
-					       GET_MODE (inner),
+					       inner_mode,
 					       mem_mode, initialized);
 	  break;
 	}
       if (dwarf_strict && dwarf_version < 5)
 	break;
-      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (inner)))
-	break;
-      if (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (inner))
-	  && (!SCALAR_INT_MODE_P (mode)
-	      || !SCALAR_INT_MODE_P (GET_MODE (inner))))
-	break;
-      else
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (inner), &inner_mode)
+	  ? GET_MODE_SIZE (int_mode) <= GET_MODE_SIZE (inner_mode)
+	  : GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (inner)))
 	{
 	  dw_die_ref type_die;
 	  dw_loc_descr_ref cvt;
@@ -14551,8 +14556,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
 	  cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
 	  add_loc_descr (&mem_loc_result, cvt);
-	  if (SCALAR_INT_MODE_P (mode)
-	      && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
+	  if (is_a <scalar_int_mode> (mode, &int_mode)
+	      && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE)
 	    {
 	      /* Convert it to untyped afterwards.  */
 	      cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
@@ -14562,12 +14567,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       break;
 
     case REG:
-      if (! SCALAR_INT_MODE_P (mode)
-	  || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
+      if (!is_a <scalar_int_mode> (mode, &int_mode)
+	  || (GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE
 	      && rtl != arg_pointer_rtx
 	      && rtl != frame_pointer_rtx
 #ifdef POINTERS_EXTEND_UNSIGNED
-	      && (mode != Pmode || mem_mode == VOIDmode)
+	      && (int_mode != Pmode || mem_mode == VOIDmode)
 #endif
 	      ))
 	{
@@ -14621,14 +14626,14 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case SIGN_EXTEND:
     case ZERO_EXTEND:
-      if (!SCALAR_INT_MODE_P (mode))
+      if (!is_a <scalar_int_mode> (mode, &int_mode))
 	break;
       op0 = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (XEXP (rtl, 0)),
 				mem_mode, VAR_INIT_STATUS_INITIALIZED);
       if (op0 == 0)
 	break;
       else if (GET_CODE (rtl) == ZERO_EXTEND
-	       && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+	       && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 	       && GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0)))
 		  < HOST_BITS_PER_WIDE_INT
 	       /* If DW_OP_const{1,2,4}u won't be used, it is shorter
@@ -14642,7 +14647,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 			 int_loc_descriptor (GET_MODE_MASK (imode)));
 	  add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_and, 0, 0));
 	}
-      else if (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
+      else if (GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE)
 	{
 	  int shift = DWARF2_ADDR_SIZE
 		      - GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)));
@@ -14666,7 +14671,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 					  GET_CODE (rtl) == ZERO_EXTEND);
 	  if (type_die1 == NULL)
 	    break;
-	  type_die2 = base_type_for_mode (mode, 1);
+	  type_die2 = base_type_for_mode (int_mode, 1);
 	  if (type_die2 == NULL)
 	    break;
 	  mem_loc_result = op0;
@@ -14701,8 +14706,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	mem_loc_result = tls_mem_loc_descriptor (rtl);
       if (mem_loc_result != NULL)
 	{
-	  if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
-	      || !SCALAR_INT_MODE_P(mode))
+	  if (!is_a <scalar_int_mode> (mode, &int_mode)
+	      || GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
 	    {
 	      dw_die_ref type_die;
 	      dw_loc_descr_ref deref;
@@ -14720,12 +14725,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	      deref->dw_loc_oprnd2.v.val_die_ref.external = 0;
 	      add_loc_descr (&mem_loc_result, deref);
 	    }
-	  else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
+	  else if (GET_MODE_SIZE (int_mode) == DWARF2_ADDR_SIZE)
 	    add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
 	  else
 	    add_loc_descr (&mem_loc_result,
 			   new_loc_descr (DW_OP_deref_size,
-					  GET_MODE_SIZE (mode), 0));
+					  GET_MODE_SIZE (int_mode), 0));
 	}
       break;
 
@@ -14738,10 +14743,10 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	 pool.  */
     case CONST:
     case SYMBOL_REF:
-      if (!SCALAR_INT_MODE_P (mode)
-	  || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
+      if (!is_a <scalar_int_mode> (mode, &int_mode)
+	  || (GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
-	      && (mode != Pmode || mem_mode == VOIDmode)
+	      && (int_mode != Pmode || mem_mode == VOIDmode)
 #endif
 	      ))
 	break;
@@ -14770,8 +14775,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       if (!const_ok_for_output (rtl))
 	{
 	  if (GET_CODE (rtl) == CONST)
-	    mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
-						 initialized);
+	    mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), int_mode,
+						 mem_mode, initialized);
 	  break;
 	}
 
@@ -14793,8 +14798,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	return NULL;
       if (REG_P (ENTRY_VALUE_EXP (rtl)))
 	{
-	  if (!SCALAR_INT_MODE_P (mode)
-	      || GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
+	  if (!is_a <scalar_int_mode> (mode, &int_mode)
+	      || GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
 	    op0 = mem_loc_descriptor (ENTRY_VALUE_EXP (rtl), mode,
 				      VOIDmode, VAR_INIT_STATUS_INITIALIZED);
 	  else
@@ -14848,10 +14853,10 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case PLUS:
     plus:
       if (is_based_loc (rtl)
-	  && (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && (GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 	      || XEXP (rtl, 0) == arg_pointer_rtx
-	      || XEXP (rtl, 0) == frame_pointer_rtx)
-	  && SCALAR_INT_MODE_P (mode))
+	      || XEXP (rtl, 0) == frame_pointer_rtx))
 	mem_loc_result = based_loc_descr (XEXP (rtl, 0),
 					  INTVAL (XEXP (rtl, 1)),
 					  VAR_INIT_STATUS_INITIALIZED);
@@ -14890,12 +14895,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case DIV:
       if ((!dwarf_strict || dwarf_version >= 5)
-	  && SCALAR_INT_MODE_P (mode)
-	  && GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
 	{
 	  mem_loc_result = typed_binop (DW_OP_div, rtl,
 					base_type_for_mode (mode, 0),
-					mode, mem_mode);
+					int_mode, mem_mode);
 	  break;
 	}
       op = DW_OP_div;
@@ -14918,17 +14923,17 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       goto do_shift;
 
     do_shift:
-      if (!SCALAR_INT_MODE_P (mode))
+      if (!is_a <scalar_int_mode> (mode, &int_mode))
 	break;
-      op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+      op0 = mem_loc_descriptor (XEXP (rtl, 0), int_mode, mem_mode,
 				VAR_INIT_STATUS_INITIALIZED);
       {
 	rtx rtlop1 = XEXP (rtl, 1);
 	if (GET_MODE (rtlop1) != VOIDmode
 	    && GET_MODE_BITSIZE (GET_MODE (rtlop1))
-	       < GET_MODE_BITSIZE (mode))
-	  rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1);
-	op1 = mem_loc_descriptor (rtlop1, mode, mem_mode,
+	       < GET_MODE_BITSIZE (int_mode))
+	  rtlop1 = gen_rtx_ZERO_EXTEND (int_mode, rtlop1);
+	op1 = mem_loc_descriptor (rtlop1, int_mode, mem_mode,
 				  VAR_INIT_STATUS_INITIALIZED);
       }
 
@@ -14995,16 +15000,16 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case UDIV:
       if ((!dwarf_strict || dwarf_version >= 5)
-	  && SCALAR_INT_MODE_P (mode))
+	  && is_a <scalar_int_mode> (mode, &int_mode))
 	{
-	  if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
+	  if (GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
 	    {
 	      op = DW_OP_div;
 	      goto do_binop;
 	    }
 	  mem_loc_result = typed_binop (DW_OP_div, rtl,
-					base_type_for_mode (mode, 1),
-					mode, mem_mode);
+					base_type_for_mode (int_mode, 1),
+					int_mode, mem_mode);
 	}
       break;
 
@@ -15032,9 +15037,10 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       break;
 
     case CONST_INT:
-      if (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+      if (!is_a <scalar_int_mode> (mode, &int_mode)
+	  || GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
-	  || (mode == Pmode
+	  || (int_mode == Pmode
 	      && mem_mode != VOIDmode
 	      && trunc_int_for_mode (INTVAL (rtl), ptr_mode) == INTVAL (rtl))
 #endif
@@ -15044,10 +15050,10 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  break;
 	}
       if ((!dwarf_strict || dwarf_version >= 5)
-	  && (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT
-	      || GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT))
+	  && (GET_MODE_BITSIZE (int_mode) == HOST_BITS_PER_WIDE_INT
+	      || GET_MODE_BITSIZE (int_mode) == HOST_BITS_PER_DOUBLE_INT))
 	{
-	  dw_die_ref type_die = base_type_for_mode (mode, 1);
+	  dw_die_ref type_die = base_type_for_mode (int_mode, 1);
 	  scalar_int_mode amode;
 	  if (type_die == NULL)
 	    return NULL;
@@ -15058,7 +15064,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	      /* const DW_OP_convert <XXX> vs.
 		 DW_OP_const_type <XXX, 1, const>.  */
 	      && size_of_int_loc_descriptor (INTVAL (rtl)) + 1 + 1
-		 < (unsigned long) 1 + 1 + 1 + GET_MODE_SIZE (mode))
+		 < (unsigned long) 1 + 1 + 1 + GET_MODE_SIZE (int_mode))
 	    {
 	      mem_loc_result = int_loc_descriptor (INTVAL (rtl));
 	      op0 = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
@@ -15073,7 +15079,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
 	  mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
 	  mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
-	  if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
+	  if (GET_MODE_BITSIZE (int_mode) == HOST_BITS_PER_WIDE_INT)
 	    mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
 	  else
 	    {
@@ -15206,11 +15212,11 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case SIGN_EXTRACT:
       if (CONST_INT_P (XEXP (rtl, 1))
 	  && CONST_INT_P (XEXP (rtl, 2))
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && ((unsigned) INTVAL (XEXP (rtl, 1))
 	      + (unsigned) INTVAL (XEXP (rtl, 2))
-	      <= GET_MODE_BITSIZE (mode))
-	  && SCALAR_INT_MODE_P (mode)
-	  && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE
+	      <= GET_MODE_BITSIZE (int_mode))
+	  && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 	  && GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) <= DWARF2_ADDR_SIZE)
 	{
 	  int shift, size;
@@ -15286,12 +15292,11 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 				    mem_mode, VAR_INIT_STATUS_INITIALIZED);
 	  if (op0 == NULL)
 	    break;
-	  if (SCALAR_INT_MODE_P (GET_MODE (XEXP (rtl, 0)))
+	  if (is_a <scalar_int_mode> (GET_MODE (XEXP (rtl, 0)), &int_mode)
 	      && (GET_CODE (rtl) == FLOAT
-		  || GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)))
-		     <= DWARF2_ADDR_SIZE))
+		  || GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE))
 	    {
-	      type_die = base_type_for_mode (GET_MODE (XEXP (rtl, 0)),
+	      type_die = base_type_for_mode (int_mode,
 					     GET_CODE (rtl) == UNSIGNED_FLOAT);
 	      if (type_die == NULL)
 		break;
@@ -15309,11 +15314,11 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
 	  cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
 	  add_loc_descr (&op0, cvt);
-	  if (SCALAR_INT_MODE_P (mode)
+	  if (is_a <scalar_int_mode> (mode, &int_mode)
 	      && (GET_CODE (rtl) == FIX
-		  || GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE))
+		  || GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE))
 	    {
-	      op0 = convert_descriptor_to_mode (mode, op0);
+	      op0 = convert_descriptor_to_mode (int_mode, op0);
 	      if (op0 == NULL)
 		break;
 	    }
@@ -15554,6 +15559,7 @@ loc_descriptor (rtx rtl, machine_mode mode,
 		enum var_init_status initialized)
 {
   dw_loc_descr_ref loc_result = NULL;
+  scalar_int_mode int_mode;
 
   switch (GET_CODE (rtl))
     {
@@ -15780,9 +15786,9 @@ loc_descriptor (rtx rtl, machine_mode mode,
       /* FALLTHRU */
     do_default:
     default:
-      if ((SCALAR_INT_MODE_P (mode)
-	   && GET_MODE (rtl) == mode
-	   && GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
+      if ((is_a <scalar_int_mode> (mode, &int_mode)
+	   && GET_MODE (rtl) == int_mode
+	   && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
 	   && dwarf_version >= 4)
 	  || (!dwarf_strict && mode != VOIDmode && mode != BLKmode))
 	{
diff --git a/gcc/expmed.c b/gcc/expmed.c
index bf85b7f..d3eb5d6 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -202,14 +202,15 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
 							speed));
     }
 
-  if (SCALAR_INT_MODE_P (mode))
+  scalar_int_mode int_mode_to;
+  if (is_a <scalar_int_mode> (mode, &int_mode_to))
     {
       FOR_EACH_MODE_IN_CLASS (mode_from, MODE_INT)
-	init_expmed_one_conv (all, mode, mode_from, speed);
+	init_expmed_one_conv (all, int_mode_to, mode_from, speed);
 
-      machine_mode wider_mode;
-      if (GET_MODE_CLASS (mode) == MODE_INT
-	  && GET_MODE_WIDER_MODE (mode).exists (&wider_mode))
+      scalar_int_mode wider_mode;
+      if (GET_MODE_CLASS (int_mode_to) == MODE_INT
+	  && GET_MODE_WIDER_MODE (int_mode_to).exists (&wider_mode))
 	{
 	  PUT_MODE (all->zext, wider_mode);
 	  PUT_MODE (all->wide_mult, wider_mode);
@@ -218,8 +219,9 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
 
 	  set_mul_widen_cost (speed, wider_mode,
 			      set_src_cost (all->wide_mult, wider_mode, speed));
-	  set_mul_highpart_cost (speed, mode,
-				 set_src_cost (all->wide_trunc, mode, speed));
+	  set_mul_highpart_cost (speed, int_mode_to,
+				 set_src_cost (all->wide_trunc,
+					       int_mode_to, speed));
 	}
     }
 }
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 4c69237..50aae8e 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3101,14 +3101,15 @@ gfc_type_for_mode (machine_mode mode, int unsignedp)
 {
   int i;
   tree *base;
+  scalar_int_mode int_mode;
 
   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
     base = gfc_real_types;
   else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
     base = gfc_complex_types;
-  else if (SCALAR_INT_MODE_P (mode))
+  else if (is_a <scalar_int_mode> (mode, &int_mode))
     {
-      tree type = gfc_type_for_size (GET_MODE_PRECISION (mode), unsignedp);
+      tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode), unsignedp);
       return type != NULL_TREE && mode == TYPE_MODE (type) ? type : NULL_TREE;
     }
   else if (VECTOR_MODE_P (mode))
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 2ef9ad3..d384248 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -671,8 +671,11 @@ int
 lra_constraint_offset (int regno, machine_mode mode)
 {
   lra_assert (regno < FIRST_PSEUDO_REGISTER);
-  if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (mode) > UNITS_PER_WORD
-      && SCALAR_INT_MODE_P (mode))
+
+  scalar_int_mode int_mode;
+  if (WORDS_BIG_ENDIAN
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD)
     return hard_regno_nregs[regno][mode] - 1;
   return 0;
 }
diff --git a/gcc/optabs.c b/gcc/optabs.c
index c8b70c7..b641cbe 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4973,9 +4973,9 @@ expand_fix (rtx to, rtx from, int unsignedp)
 static rtx
 prepare_libcall_arg (rtx arg, int uintp)
 {
-  machine_mode mode = GET_MODE (arg);
+  scalar_int_mode mode;
   machine_mode arg_mode;
-  if (SCALAR_INT_MODE_P (mode))
+  if (is_a <scalar_int_mode> (GET_MODE (arg), &mode))
     {
       /*  If we need to promote the integer function argument we need to do
 	  it here instead of inside emit_library_call_value because in
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 052b52a..ff77d4c 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -2149,7 +2149,7 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
 {
   rtx_insn *insn = (rtx_insn *) data;
   unsigned int regno = 0;
-  machine_mode mode = GET_MODE (dst);
+  scalar_int_mode mode;
 
   /* Some targets do argument pushes without adding REG_INC notes.  */
 
@@ -2169,8 +2169,10 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
   else
     return;
 
-  if (SCALAR_INT_MODE_P (mode)
-      && GET_CODE (set) == SET)
+  if (!is_a <scalar_int_mode> (GET_MODE (dst), &mode))
+    goto invalidate;
+
+  if (GET_CODE (set) == SET)
     {
       rtx note, sym = NULL_RTX;
       rtx off;
@@ -2197,8 +2199,7 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
 	}
     }
 
-  if (SCALAR_INT_MODE_P (mode)
-      && GET_CODE (set) == SET
+  if (GET_CODE (set) == SET
       && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
       && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
     {
diff --git a/gcc/reload.c b/gcc/reload.c
index 4cba220..4d75fda 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -2264,14 +2264,17 @@ operands_match_p (rtx x, rtx y)
 	 multiple hard register group of scalar integer registers, so that
 	 for example (reg:DI 0) and (reg:SI 1) will be considered the same
 	 register.  */
-      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
-	  && SCALAR_INT_MODE_P (GET_MODE (x))
+      scalar_int_mode int_mode;
+      if (REG_WORDS_BIG_ENDIAN
+	  && is_a <scalar_int_mode> (GET_MODE (x), &int_mode)
+	  && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
 	  && i < FIRST_PSEUDO_REGISTER)
-	i += hard_regno_nregs[i][GET_MODE (x)] - 1;
-      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
-	  && SCALAR_INT_MODE_P (GET_MODE (y))
+	i += hard_regno_nregs[i][int_mode] - 1;
+      if (REG_WORDS_BIG_ENDIAN
+	  && is_a <scalar_int_mode> (GET_MODE (y), &int_mode)
+	  && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD
 	  && j < FIRST_PSEUDO_REGISTER)
-	j += hard_regno_nregs[j][GET_MODE (y)] - 1;
+	j += hard_regno_nregs[j][int_mode] - 1;
 
       return i == j;
     }
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 5a77c4f..7d44e3f 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3819,9 +3819,10 @@ struct GTY(()) cgraph_rtl_info {
 inline rtx_code
 load_extend_op (machine_mode mode)
 {
-  if (SCALAR_INT_MODE_P (mode)
-      && GET_MODE_PRECISION (mode) < BITS_PER_WORD)
-    return LOAD_EXTEND_OP (mode);
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_PRECISION (int_mode) < BITS_PER_WORD)
+    return LOAD_EXTEND_OP (int_mode);
   return UNKNOWN;
 }
 
diff --git a/gcc/rtlhooks.c b/gcc/rtlhooks.c
index 49f54bc..6bebcd6 100644
--- a/gcc/rtlhooks.c
+++ b/gcc/rtlhooks.c
@@ -64,11 +64,12 @@ gen_lowpart_general (machine_mode mode, rtx x)
       gcc_assert (MEM_P (x));
 
       /* The following exposes the use of "x" to CSE.  */
-      if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
-	  && SCALAR_INT_MODE_P (GET_MODE (x))
-	  && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x))
+      scalar_int_mode xmode;
+      if (is_a <scalar_int_mode> (GET_MODE (x), &xmode)
+	  && GET_MODE_SIZE (xmode) <= UNITS_PER_WORD
+	  && TRULY_NOOP_TRUNCATION_MODES_P (mode, xmode)
 	  && !reload_completed)
-	return gen_lowpart_general (mode, force_reg (GET_MODE (x), x));
+	return gen_lowpart_general (mode, force_reg (xmode, x));
 
       if (WORDS_BIG_ENDIAN)
 	offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 637ed4f..cb0e43d 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -641,6 +641,8 @@ simplify_truncation (machine_mode mode, rtx op,
 {
   unsigned int precision = GET_MODE_UNIT_PRECISION (mode);
   unsigned int op_precision = GET_MODE_UNIT_PRECISION (op_mode);
+  scalar_int_mode int_mode, int_op_mode, subreg_mode;
+
   gcc_assert (precision <= op_precision);
 
   /* Optimize truncations of zero and sign extended values.  */
@@ -806,19 +808,19 @@ simplify_truncation (machine_mode mode, rtx op,
      if the MEM has a mode-dependent address.  */
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
-      && SCALAR_INT_MODE_P (op_mode)
+      && is_a <scalar_int_mode> (op_mode, &int_op_mode)
       && MEM_P (XEXP (op, 0))
       && CONST_INT_P (XEXP (op, 1))
       && (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (mode)) == 0
       && INTVAL (XEXP (op, 1)) > 0
-      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (op_mode)
+      && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (int_op_mode)
       && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0),
 				     MEM_ADDR_SPACE (XEXP (op, 0)))
       && ! MEM_VOLATILE_P (XEXP (op, 0))
       && (GET_MODE_SIZE (mode) >= UNITS_PER_WORD
 	  || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN))
     {
-      int byte = subreg_lowpart_offset (mode, op_mode);
+      int byte = subreg_lowpart_offset (mode, int_op_mode);
       int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
       return adjust_address_nv (XEXP (op, 0), mode,
 				(WORDS_BIG_ENDIAN
@@ -839,21 +841,20 @@ simplify_truncation (machine_mode mode, rtx op,
   /* (truncate:A (subreg:B (truncate:C X) 0)) is
      (truncate:A X).  */
   if (GET_CODE (op) == SUBREG
-      && SCALAR_INT_MODE_P (mode)
+      && is_a <scalar_int_mode> (mode, &int_mode)
       && SCALAR_INT_MODE_P (op_mode)
-      && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op)))
+      && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &subreg_mode)
       && GET_CODE (SUBREG_REG (op)) == TRUNCATE
       && subreg_lowpart_p (op))
     {
       rtx inner = XEXP (SUBREG_REG (op), 0);
-      if (GET_MODE_PRECISION (mode)
-	  <= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
-	return simplify_gen_unary (TRUNCATE, mode, inner, GET_MODE (inner));
+      if (GET_MODE_PRECISION (int_mode) <= GET_MODE_PRECISION (subreg_mode))
+	return simplify_gen_unary (TRUNCATE, int_mode, inner,
+				   GET_MODE (inner));
       else
 	/* If subreg above is paradoxical and C is narrower
 	   than A, return (subreg:A (truncate:C X) 0).  */
-	return simplify_gen_subreg (mode, SUBREG_REG (op),
-				    GET_MODE (SUBREG_REG (op)), 0);
+	return simplify_gen_subreg (int_mode, SUBREG_REG (op), subreg_mode, 0);
     }
 
   /* (truncate:A (truncate:B X)) is (truncate:A X).  */
@@ -915,6 +916,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 {
   enum rtx_code reversed;
   rtx temp;
+  scalar_int_mode inner;
 
   switch (code)
     {
@@ -1145,9 +1147,8 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
       /* (neg (lt x 0)) is (lshiftrt X C) if STORE_FLAG_VALUE is -1.  */
       if (GET_CODE (op) == LT
 	  && XEXP (op, 1) == const0_rtx
-	  && SCALAR_INT_MODE_P (GET_MODE (XEXP (op, 0))))
+	  && is_a <scalar_int_mode> (GET_MODE (XEXP (op, 0)), &inner))
 	{
-	  machine_mode inner = GET_MODE (XEXP (op, 0));
 	  int isize = GET_MODE_PRECISION (inner);
 	  if (STORE_FLAG_VALUE == 1)
 	    {
@@ -2123,6 +2124,7 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
   rtx tem, reversed, opleft, opright;
   HOST_WIDE_INT val;
   unsigned int width = GET_MODE_PRECISION (mode);
+  scalar_int_mode int_mode;
 
   /* Even if we can't compute a constant result,
      there are some cases worth simplifying.  */
@@ -2173,66 +2175,66 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	 have X (if C is 2 in the example above).  But don't make
 	 something more expensive than we had before.  */
 
-      if (SCALAR_INT_MODE_P (mode))
+      if (is_a <scalar_int_mode> (mode, &int_mode))
 	{
 	  rtx lhs = op0, rhs = op1;
 
-	  wide_int coeff0 = wi::one (GET_MODE_PRECISION (mode));
-	  wide_int coeff1 = wi::one (GET_MODE_PRECISION (mode));
+	  wide_int coeff0 = wi::one (GET_MODE_PRECISION (int_mode));
+	  wide_int coeff1 = wi::one (GET_MODE_PRECISION (int_mode));
 
 	  if (GET_CODE (lhs) == NEG)
 	    {
-	      coeff0 = wi::minus_one (GET_MODE_PRECISION (mode));
+	      coeff0 = wi::minus_one (GET_MODE_PRECISION (int_mode));
 	      lhs = XEXP (lhs, 0);
 	    }
 	  else if (GET_CODE (lhs) == MULT
 		   && CONST_SCALAR_INT_P (XEXP (lhs, 1)))
 	    {
-	      coeff0 = rtx_mode_t (XEXP (lhs, 1), mode);
+	      coeff0 = rtx_mode_t (XEXP (lhs, 1), int_mode);
 	      lhs = XEXP (lhs, 0);
 	    }
 	  else if (GET_CODE (lhs) == ASHIFT
 		   && CONST_INT_P (XEXP (lhs, 1))
                    && INTVAL (XEXP (lhs, 1)) >= 0
-		   && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (mode))
+		   && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (int_mode))
 	    {
 	      coeff0 = wi::set_bit_in_zero (INTVAL (XEXP (lhs, 1)),
-					    GET_MODE_PRECISION (mode));
+					    GET_MODE_PRECISION (int_mode));
 	      lhs = XEXP (lhs, 0);
 	    }
 
 	  if (GET_CODE (rhs) == NEG)
 	    {
-	      coeff1 = wi::minus_one (GET_MODE_PRECISION (mode));
+	      coeff1 = wi::minus_one (GET_MODE_PRECISION (int_mode));
 	      rhs = XEXP (rhs, 0);
 	    }
 	  else if (GET_CODE (rhs) == MULT
 		   && CONST_INT_P (XEXP (rhs, 1)))
 	    {
-	      coeff1 = rtx_mode_t (XEXP (rhs, 1), mode);
+	      coeff1 = rtx_mode_t (XEXP (rhs, 1), int_mode);
 	      rhs = XEXP (rhs, 0);
 	    }
 	  else if (GET_CODE (rhs) == ASHIFT
 		   && CONST_INT_P (XEXP (rhs, 1))
 		   && INTVAL (XEXP (rhs, 1)) >= 0
-		   && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (mode))
+		   && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (int_mode))
 	    {
 	      coeff1 = wi::set_bit_in_zero (INTVAL (XEXP (rhs, 1)),
-					    GET_MODE_PRECISION (mode));
+					    GET_MODE_PRECISION (int_mode));
 	      rhs = XEXP (rhs, 0);
 	    }
 
 	  if (rtx_equal_p (lhs, rhs))
 	    {
-	      rtx orig = gen_rtx_PLUS (mode, op0, op1);
+	      rtx orig = gen_rtx_PLUS (int_mode, op0, op1);
 	      rtx coeff;
 	      bool speed = optimize_function_for_speed_p (cfun);
 
-	      coeff = immed_wide_int_const (coeff0 + coeff1, mode);
+	      coeff = immed_wide_int_const (coeff0 + coeff1, int_mode);
 
-	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return (set_src_cost (tem, mode, speed)
-		      <= set_src_cost (orig, mode, speed) ? tem : 0);
+	      tem = simplify_gen_binary (MULT, int_mode, lhs, coeff);
+	      return (set_src_cost (tem, int_mode, speed)
+		      <= set_src_cost (orig, int_mode, speed) ? tem : 0);
 	    }
 	}
 
@@ -2350,67 +2352,67 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	 have X (if C is 2 in the example above).  But don't make
 	 something more expensive than we had before.  */
 
-      if (SCALAR_INT_MODE_P (mode))
+      if (is_a <scalar_int_mode> (mode, &int_mode))
 	{
 	  rtx lhs = op0, rhs = op1;
 
-	  wide_int coeff0 = wi::one (GET_MODE_PRECISION (mode));
-	  wide_int negcoeff1 = wi::minus_one (GET_MODE_PRECISION (mode));
+	  wide_int coeff0 = wi::one (GET_MODE_PRECISION (int_mode));
+	  wide_int negcoeff1 = wi::minus_one (GET_MODE_PRECISION (int_mode));
 
 	  if (GET_CODE (lhs) == NEG)
 	    {
-	      coeff0 = wi::minus_one (GET_MODE_PRECISION (mode));
+	      coeff0 = wi::minus_one (GET_MODE_PRECISION (int_mode));
 	      lhs = XEXP (lhs, 0);
 	    }
 	  else if (GET_CODE (lhs) == MULT
 		   && CONST_SCALAR_INT_P (XEXP (lhs, 1)))
 	    {
-	      coeff0 = rtx_mode_t (XEXP (lhs, 1), mode);
+	      coeff0 = rtx_mode_t (XEXP (lhs, 1), int_mode);
 	      lhs = XEXP (lhs, 0);
 	    }
 	  else if (GET_CODE (lhs) == ASHIFT
 		   && CONST_INT_P (XEXP (lhs, 1))
 		   && INTVAL (XEXP (lhs, 1)) >= 0
-		   && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (mode))
+		   && INTVAL (XEXP (lhs, 1)) < GET_MODE_PRECISION (int_mode))
 	    {
 	      coeff0 = wi::set_bit_in_zero (INTVAL (XEXP (lhs, 1)),
-					    GET_MODE_PRECISION (mode));
+					    GET_MODE_PRECISION (int_mode));
 	      lhs = XEXP (lhs, 0);
 	    }
 
 	  if (GET_CODE (rhs) == NEG)
 	    {
-	      negcoeff1 = wi::one (GET_MODE_PRECISION (mode));
+	      negcoeff1 = wi::one (GET_MODE_PRECISION (int_mode));
 	      rhs = XEXP (rhs, 0);
 	    }
 	  else if (GET_CODE (rhs) == MULT
 		   && CONST_INT_P (XEXP (rhs, 1)))
 	    {
-	      negcoeff1 = wi::neg (rtx_mode_t (XEXP (rhs, 1), mode));
+	      negcoeff1 = wi::neg (rtx_mode_t (XEXP (rhs, 1), int_mode));
 	      rhs = XEXP (rhs, 0);
 	    }
 	  else if (GET_CODE (rhs) == ASHIFT
 		   && CONST_INT_P (XEXP (rhs, 1))
 		   && INTVAL (XEXP (rhs, 1)) >= 0
-		   && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (mode))
+		   && INTVAL (XEXP (rhs, 1)) < GET_MODE_PRECISION (int_mode))
 	    {
 	      negcoeff1 = wi::set_bit_in_zero (INTVAL (XEXP (rhs, 1)),
-					       GET_MODE_PRECISION (mode));
+					       GET_MODE_PRECISION (int_mode));
 	      negcoeff1 = -negcoeff1;
 	      rhs = XEXP (rhs, 0);
 	    }
 
 	  if (rtx_equal_p (lhs, rhs))
 	    {
-	      rtx orig = gen_rtx_MINUS (mode, op0, op1);
+	      rtx orig = gen_rtx_MINUS (int_mode, op0, op1);
 	      rtx coeff;
 	      bool speed = optimize_function_for_speed_p (cfun);
 
-	      coeff = immed_wide_int_const (coeff0 + negcoeff1, mode);
+	      coeff = immed_wide_int_const (coeff0 + negcoeff1, int_mode);
 
-	      tem = simplify_gen_binary (MULT, mode, lhs, coeff);
-	      return (set_src_cost (tem, mode, speed)
-		      <= set_src_cost (orig, mode, speed) ? tem : 0);
+	      tem = simplify_gen_binary (MULT, int_mode, lhs, coeff);
+	      return (set_src_cost (tem, int_mode, speed)
+		      <= set_src_cost (orig, int_mode, speed) ? tem : 0);
 	    }
 	}
 
@@ -3882,8 +3884,6 @@ rtx
 simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 				 rtx op0, rtx op1)
 {
-  unsigned int width = GET_MODE_PRECISION (mode);
-
   if (VECTOR_MODE_P (mode)
       && code != VEC_CONCAT
       && GET_CODE (op0) == CONST_VECTOR
@@ -4077,15 +4077,15 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
     }
 
   /* We can fold some multi-word operations.  */
-  if ((GET_MODE_CLASS (mode) == MODE_INT
-       || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode, &int_mode)
       && CONST_SCALAR_INT_P (op0)
       && CONST_SCALAR_INT_P (op1))
     {
       wide_int result;
       bool overflow;
-      rtx_mode_t pop0 = rtx_mode_t (op0, mode);
-      rtx_mode_t pop1 = rtx_mode_t (op1, mode);
+      rtx_mode_t pop0 = rtx_mode_t (op0, int_mode);
+      rtx_mode_t pop1 = rtx_mode_t (op1, int_mode);
 
 #if TARGET_SUPPORTS_WIDE_INT == 0
       /* This assert keeps the simplification from producing a result
@@ -4094,7 +4094,7 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 	 simplify something and so you if you added this to the test
 	 above the code would die later anyway.  If this assert
 	 happens, you just need to make the port support wide int.  */
-      gcc_assert (width <= HOST_BITS_PER_DOUBLE_INT);
+      gcc_assert (GET_MODE_PRECISION (int_mode) <= HOST_BITS_PER_DOUBLE_INT);
 #endif
       switch (code)
 	{
@@ -4168,8 +4168,8 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 	  {
 	    wide_int wop1 = pop1;
 	    if (SHIFT_COUNT_TRUNCATED)
-	      wop1 = wi::umod_trunc (wop1, width);
-	    else if (wi::geu_p (wop1, width))
+	      wop1 = wi::umod_trunc (wop1, GET_MODE_PRECISION (int_mode));
+	    else if (wi::geu_p (wop1, GET_MODE_PRECISION (int_mode)))
 	      return NULL_RTX;
 
 	    switch (code)
@@ -4215,7 +4215,7 @@ simplify_const_binary_operation (enum rtx_code code, machine_mode mode,
 	default:
 	  return NULL_RTX;
 	}
-      return immed_wide_int_const (result, mode);
+      return immed_wide_int_const (result, int_mode);
     }
 
   return NULL_RTX;
@@ -5139,12 +5139,14 @@ simplify_const_relational_operation (enum rtx_code code,
     }
 
   /* Optimize comparisons with upper and lower bounds.  */
-  if (HWI_COMPUTABLE_MODE_P (mode)
-      && CONST_INT_P (trueop1)
+  scalar_int_mode int_mode;
+  if (CONST_INT_P (trueop1)
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && HWI_COMPUTABLE_MODE_P (int_mode)
       && !side_effects_p (trueop0))
     {
       int sign;
-      unsigned HOST_WIDE_INT nonzero = nonzero_bits (trueop0, mode);
+      unsigned HOST_WIDE_INT nonzero = nonzero_bits (trueop0, int_mode);
       HOST_WIDE_INT val = INTVAL (trueop1);
       HOST_WIDE_INT mmin, mmax;
 
@@ -5157,7 +5159,7 @@ simplify_const_relational_operation (enum rtx_code code,
 	sign = 1;
 
       /* Get a reduced range if the sign bit is zero.  */
-      if (nonzero <= (GET_MODE_MASK (mode) >> 1))
+      if (nonzero <= (GET_MODE_MASK (int_mode) >> 1))
 	{
 	  mmin = 0;
 	  mmax = nonzero;
@@ -5165,13 +5167,14 @@ simplify_const_relational_operation (enum rtx_code code,
       else
 	{
 	  rtx mmin_rtx, mmax_rtx;
-	  get_mode_bounds (mode, sign, mode, &mmin_rtx, &mmax_rtx);
+	  get_mode_bounds (int_mode, sign, int_mode, &mmin_rtx, &mmax_rtx);
 
 	  mmin = INTVAL (mmin_rtx);
 	  mmax = INTVAL (mmax_rtx);
 	  if (sign)
 	    {
-	      unsigned int sign_copies = num_sign_bit_copies (trueop0, mode);
+	      unsigned int sign_copies
+		= num_sign_bit_copies (trueop0, int_mode);
 
 	      mmin >>= (sign_copies - 1);
 	      mmax >>= (sign_copies - 1);
@@ -6243,12 +6246,14 @@ simplify_subreg (machine_mode outermode, rtx op,
 	return CONST0_RTX (outermode);
     }
 
-  if (SCALAR_INT_MODE_P (outermode)
-      && SCALAR_INT_MODE_P (innermode)
-      && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)
-      && byte == subreg_lowpart_offset (outermode, innermode))
+  scalar_int_mode int_outermode, int_innermode;
+  if (is_a <scalar_int_mode> (outermode, &int_outermode)
+      && is_a <scalar_int_mode> (innermode, &int_innermode)
+      && (GET_MODE_PRECISION (int_outermode)
+	  < GET_MODE_PRECISION (int_innermode))
+      && byte == subreg_lowpart_offset (int_outermode, int_innermode))
     {
-      rtx tem = simplify_truncation (outermode, op, innermode);
+      rtx tem = simplify_truncation (int_outermode, op, int_innermode);
       if (tem)
 	return tem;
     }
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 1cbef06..5cf4433 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -412,8 +412,10 @@ bitwise_mode_for_mode (machine_mode mode)
 {
   /* Quick exit if we already have a suitable mode.  */
   unsigned int bitsize = GET_MODE_BITSIZE (mode);
-  if (SCALAR_INT_MODE_P (mode) && bitsize <= MAX_FIXED_MODE_SIZE)
-    return mode;
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_BITSIZE (int_mode) <= MAX_FIXED_MODE_SIZE)
+    return int_mode;
 
   /* Reuse the sanity checks from int_mode_for_mode.  */
   gcc_checking_assert ((int_mode_for_mode (mode), true));
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index a187794..31f7a31 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -1008,6 +1008,7 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
   rtx mem, addr = loc, tem;
   machine_mode mem_mode_save;
   bool store_save;
+  scalar_int_mode tem_mode, tem_subreg_mode;
   switch (GET_CODE (loc))
     {
     case REG:
@@ -1122,16 +1123,14 @@ adjust_mems (rtx loc, const_rtx old_rtx, void *data)
 	      || GET_CODE (SUBREG_REG (tem)) == MINUS
 	      || GET_CODE (SUBREG_REG (tem)) == MULT
 	      || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
-	  && (GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
-	      || GET_MODE_CLASS (GET_MODE (tem)) == MODE_PARTIAL_INT)
-	  && (GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
-	      || GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_PARTIAL_INT)
-	  && GET_MODE_PRECISION (GET_MODE (tem))
-	     < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (tem)))
+	  && is_a <scalar_int_mode> (GET_MODE (tem), &tem_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (tem)),
+				     &tem_subreg_mode)
+	  && (GET_MODE_PRECISION (tem_mode)
+	      < GET_MODE_PRECISION (tem_subreg_mode))
 	  && subreg_lowpart_p (tem)
 	  && use_narrower_mode_test (SUBREG_REG (tem), tem))
-	return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
-				  GET_MODE (SUBREG_REG (tem)));
+	return use_narrower_mode (SUBREG_REG (tem), tem_mode, tem_subreg_mode);
       return tem;
     case ASM_OPERANDS:
       /* Don't do any replacements in second and following
@@ -6300,15 +6299,15 @@ prepare_call_arguments (basic_block bb, rtx_insn *insn)
 	else if (REG_P (x))
 	  {
 	    cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
+	    scalar_int_mode mode;
 	    if (val && cselib_preserved_value_p (val))
 	      item = val->val_rtx;
-	    else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
-		     || GET_MODE_CLASS (GET_MODE (x)) == MODE_PARTIAL_INT)
+	    else if (is_a <scalar_int_mode> (GET_MODE (x), &mode))
 	      {
-		machine_mode mode;
-
-		FOR_EACH_WIDER_MODE (mode, GET_MODE (x))
+		opt_scalar_int_mode mode_iter;
+		FOR_EACH_WIDER_MODE (mode_iter, mode)
 		  {
+		    mode = *mode_iter;
 		    if (GET_MODE_BITSIZE (mode) > BITS_PER_WORD)
 		      break;
 
diff --git a/gcc/wide-int.h b/gcc/wide-int.h
index 72f74be..97577a5 100644
--- a/gcc/wide-int.h
+++ b/gcc/wide-int.h
@@ -1453,6 +1453,14 @@ wi::primitive_int_traits <T, signed_p>::decompose (HOST_WIDE_INT *scratch,
 namespace wi
 {
   template <>
+  struct int_traits <unsigned char>
+    : public primitive_int_traits <unsigned char, false> {};
+
+  template <>
+  struct int_traits <unsigned short>
+    : public primitive_int_traits <unsigned short, false> {};
+
+  template <>
   struct int_traits <int>
     : public primitive_int_traits <int, true> {};
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [22/67] Replace !VECTOR_MODE_P with is_a <scalar_int_mode>
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (20 preceding siblings ...)
  2016-12-09 13:06 ` [20/67] Replace MODE_INT checks with is_int_mode Richard Sandiford
@ 2016-12-09 13:07 ` Richard Sandiford
  2016-12-09 13:07 ` [21/67] Replace SCALAR_INT_MODE_P checks " Richard Sandiford
                   ` (47 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:07 UTC (permalink / raw)
  To: gcc-patches

This patch replaces some checks of !VECTOR_MODE_P with checks
of is_a <scalar_int_mode>, in cases where the scalar integer
modes were the only useful alternatives left.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* simplify-rtx.c (simplify_binary_operation_1): Use
	is_a <scalar_int_mode> instead of !VECTOR_MODE_P.

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index cb0e43d..e5e7a71 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -2124,7 +2124,7 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
   rtx tem, reversed, opleft, opright;
   HOST_WIDE_INT val;
   unsigned int width = GET_MODE_PRECISION (mode);
-  scalar_int_mode int_mode;
+  scalar_int_mode int_mode, inner_mode;
 
   /* Even if we can't compute a constant result,
      there are some cases worth simplifying.  */
@@ -3357,27 +3357,24 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	 (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int <c1 + c2>))
 		    <low_part>).  */
       if (code == ASHIFTRT
-	  && !VECTOR_MODE_P (mode)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && SUBREG_P (op0)
 	  && CONST_INT_P (op1)
 	  && GET_CODE (SUBREG_REG (op0)) == LSHIFTRT
-	  && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0)))
+	  && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op0)),
+				     &inner_mode)
 	  && CONST_INT_P (XEXP (SUBREG_REG (op0), 1))
-	  && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
-	      > GET_MODE_BITSIZE (mode))
+	  && GET_MODE_BITSIZE (inner_mode) > GET_MODE_BITSIZE (int_mode)
 	  && (INTVAL (XEXP (SUBREG_REG (op0), 1))
-	      == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
-		  - GET_MODE_BITSIZE (mode)))
+	      == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode))
 	  && subreg_lowpart_p (op0))
 	{
 	  rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1))
 			     + INTVAL (op1));
-	  machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-	  tmp = simplify_gen_binary (ASHIFTRT,
-				     GET_MODE (SUBREG_REG (op0)),
+	  tmp = simplify_gen_binary (ASHIFTRT, inner_mode,
 				     XEXP (SUBREG_REG (op0), 0),
 				     tmp);
-	  return lowpart_subreg (mode, tmp, inner_mode);
+	  return lowpart_subreg (int_mode, tmp, inner_mode);
 	}
     canonicalize_shift:
       if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1))

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [24/67] Replace a != BLKmode check with is_a <scalar_int_mode>
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (22 preceding siblings ...)
  2016-12-09 13:07 ` [21/67] Replace SCALAR_INT_MODE_P checks " Richard Sandiford
@ 2016-12-09 13:08 ` Richard Sandiford
  2016-12-09 13:22   ` Richard Biener
  2016-12-09 13:08 ` [23/67] Replace != VOIDmode checks " Richard Sandiford
                   ` (45 subsequent siblings)
  69 siblings, 1 reply; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:08 UTC (permalink / raw)
  To: gcc-patches

This patch replaces a check against BLKmode with a check
of is_a <scalar_int_mode>, in a case where scalar integer
modes were the only useful alternatives left.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gimple-fold.c (gimple_fold_builtin_memory_op): Use
	is_a <scalar_int_mode> instead of != BLKmode.

diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index d00625b..c6b5411 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -713,31 +713,29 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
 	  unsigned ilen = tree_to_uhwi (len);
 	  if (pow2p_hwi (ilen))
 	    {
+	      scalar_int_mode mode;
 	      tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
 	      if (type
-		  && TYPE_MODE (type) != BLKmode
-		  && (GET_MODE_SIZE (TYPE_MODE (type)) * BITS_PER_UNIT
-		      == ilen * 8)
+		  && is_a <scalar_int_mode> (TYPE_MODE (type), &mode)
+		  && GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
 		  /* If the destination pointer is not aligned we must be able
 		     to emit an unaligned store.  */
-		  && (dest_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type))
-		      || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type), dest_align)
-		      || (optab_handler (movmisalign_optab, TYPE_MODE (type))
+		  && (dest_align >= GET_MODE_ALIGNMENT (mode)
+		      || !SLOW_UNALIGNED_ACCESS (mode, dest_align)
+		      || (optab_handler (movmisalign_optab, mode)
 			  != CODE_FOR_nothing)))
 		{
 		  tree srctype = type;
 		  tree desttype = type;
-		  if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+		  if (src_align < GET_MODE_ALIGNMENT (mode))
 		    srctype = build_aligned_type (type, src_align);
 		  tree srcmem = fold_build2 (MEM_REF, srctype, src, off0);
 		  tree tem = fold_const_aggregate_ref (srcmem);
 		  if (tem)
 		    srcmem = tem;
-		  else if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type))
-			   && SLOW_UNALIGNED_ACCESS (TYPE_MODE (type),
-						     src_align)
-			   && (optab_handler (movmisalign_optab,
-					      TYPE_MODE (type))
+		  else if (src_align < GET_MODE_ALIGNMENT (mode)
+			   && SLOW_UNALIGNED_ACCESS (mode, src_align)
+			   && (optab_handler (movmisalign_optab, mode)
 			       == CODE_FOR_nothing))
 		    srcmem = NULL_TREE;
 		  if (srcmem)
@@ -753,7 +751,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
 			  gimple_set_vuse (new_stmt, gimple_vuse (stmt));
 			  gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
 			}
-		      if (dest_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
+		      if (dest_align < GET_MODE_ALIGNMENT (mode))
 			desttype = build_aligned_type (type, dest_align);
 		      new_stmt
 			= gimple_build_assign (fold_build2 (MEM_REF, desttype,

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [23/67] Replace != VOIDmode checks with is_a <scalar_int_mode>
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (23 preceding siblings ...)
  2016-12-09 13:08 ` [24/67] Replace a != BLKmode check " Richard Sandiford
@ 2016-12-09 13:08 ` Richard Sandiford
  2016-12-09 13:09 ` [25/67] Use is_a <scalar_int_mode> for bitmask optimisations Richard Sandiford
                   ` (44 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:08 UTC (permalink / raw)
  To: gcc-patches

This patch replaces some checks against VOIDmode with checks
of is_a <scalar_int_mode>, in cases where scalar integer modes
were the only useful alternatives left.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* cfgexpand.c (expand_debug_expr): Use is_a <scalar_int_mode>
	instead of != VOIDmode.
	* combine.c (if_then_else_cond): Likewise.
	* dwarf2out.c (mem_loc_descriptor): Likewise.
	* rtlanal.c (canonicalize_condition): Likewise.
	* simplify-rtx.c (simplify_relational_operation_1): Likewise.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index f94be27..1427a97 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4128,7 +4128,7 @@ expand_debug_expr (tree exp)
   machine_mode inner_mode = VOIDmode;
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
   addr_space_t as;
-  scalar_int_mode op1_mode;
+  scalar_int_mode op0_mode, op1_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -4570,23 +4570,23 @@ expand_debug_expr (tree exp)
 	 size_t, we need to check for mis-matched modes and correct
 	 the addend.  */
       if (op0 && op1
-	  && GET_MODE (op0) != VOIDmode && GET_MODE (op1) != VOIDmode
-	  && GET_MODE (op0) != GET_MODE (op1))
+	  && is_a <scalar_int_mode> (GET_MODE (op0), &op0_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (op1), &op1_mode)
+	  && op0_mode != op1_mode)
 	{
-	  if (GET_MODE_BITSIZE (GET_MODE (op0)) < GET_MODE_BITSIZE (GET_MODE (op1))
-	      /* If OP0 is a partial mode, then we must truncate, even if it has
-		 the same bitsize as OP1 as GCC's representation of partial modes
-		 is opaque.  */
-	      || (GET_MODE_CLASS (GET_MODE (op0)) == MODE_PARTIAL_INT
-		  && GET_MODE_BITSIZE (GET_MODE (op0)) == GET_MODE_BITSIZE (GET_MODE (op1))))
-	    op1 = simplify_gen_unary (TRUNCATE, GET_MODE (op0), op1,
-				      GET_MODE (op1));
+	  if (GET_MODE_BITSIZE (op0_mode) < GET_MODE_BITSIZE (op1_mode)
+	      /* If OP0 is a partial mode, then we must truncate, even
+		 if it has the same bitsize as OP1 as GCC's
+		 representation of partial modes is opaque.  */
+	      || (GET_MODE_CLASS (op0_mode) == MODE_PARTIAL_INT
+		  && (GET_MODE_BITSIZE (op0_mode)
+		      == GET_MODE_BITSIZE (op1_mode))))
+	    op1 = simplify_gen_unary (TRUNCATE, op0_mode, op1, op1_mode);
 	  else
 	    /* We always sign-extend, regardless of the signedness of
 	       the operand, because the operand is always unsigned
 	       here even if the original C expression is signed.  */
-	    op1 = simplify_gen_unary (SIGN_EXTEND, GET_MODE (op0), op1,
-				      GET_MODE (op1));
+	    op1 = simplify_gen_unary (SIGN_EXTEND, op0_mode, op1, op1_mode);
 	}
       /* Fall through.  */
     case PLUS_EXPR:
diff --git a/gcc/combine.c b/gcc/combine.c
index 2e2acea..8883194 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -9014,6 +9014,7 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
   enum rtx_code code = GET_CODE (x);
   rtx cond0, cond1, true0, true1, false0, false1;
   unsigned HOST_WIDE_INT nz;
+  scalar_int_mode int_mode;
 
   /* If we are comparing a value against zero, we are done.  */
   if ((code == NE || code == EQ)
@@ -9190,8 +9191,9 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
   /* If X is known to be either 0 or -1, those are the true and
      false values when testing X.  */
   else if (x == constm1_rtx || x == const0_rtx
-	   || (mode != VOIDmode && mode != BLKmode
-	       && num_sign_bit_copies (x, mode) == GET_MODE_PRECISION (mode)))
+	   || (is_a <scalar_int_mode> (mode, &int_mode)
+	       && (num_sign_bit_copies (x, int_mode)
+		   == GET_MODE_PRECISION (int_mode))))
     {
       *ptrue = constm1_rtx, *pfalse = const0_rtx;
       return x;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 19e6d24..7bf210d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14491,7 +14491,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
   if (mode != GET_MODE (rtl) && GET_MODE (rtl) != VOIDmode)
     return NULL;
 
-  scalar_int_mode int_mode, inner_mode;
+  scalar_int_mode int_mode, inner_mode, op1_mode;
   switch (GET_CODE (rtl))
     {
     case POST_INC:
@@ -14929,9 +14929,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 				VAR_INIT_STATUS_INITIALIZED);
       {
 	rtx rtlop1 = XEXP (rtl, 1);
-	if (GET_MODE (rtlop1) != VOIDmode
-	    && GET_MODE_BITSIZE (GET_MODE (rtlop1))
-	       < GET_MODE_BITSIZE (int_mode))
+	if (is_a <scalar_int_mode> (GET_MODE (rtlop1), &op1_mode)
+	    && GET_MODE_BITSIZE (op1_mode) < GET_MODE_BITSIZE (int_mode))
 	  rtlop1 = gen_rtx_ZERO_EXTEND (int_mode, rtlop1);
 	op1 = mem_loc_descriptor (rtlop1, int_mode, mem_mode,
 				  VAR_INIT_STATUS_INITIALIZED);
@@ -15762,7 +15761,8 @@ loc_descriptor (rtx rtl, machine_mode mode,
 	break;
       /* FALLTHROUGH */
     case LABEL_REF:
-      if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && GET_MODE_SIZE (int_mode) == DWARF2_ADDR_SIZE
 	  && (dwarf_version >= 4 || !dwarf_strict))
 	{
          loc_result = new_addr_loc_descr (rtl, dtprel_false);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 92b7580..129f69f 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5501,40 +5501,39 @@ canonicalize_condition (rtx_insn *insn, rtx cond, int reverse,
      if we can do computations in the relevant mode and we do not
      overflow.  */
 
-  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_CC
-      && CONST_INT_P (op1)
-      && GET_MODE (op0) != VOIDmode
-      && GET_MODE_PRECISION (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
+  scalar_int_mode op0_mode;
+  if (CONST_INT_P (op1)
+      && is_a <scalar_int_mode> (GET_MODE (op0), &op0_mode)
+      && GET_MODE_PRECISION (op0_mode) <= HOST_BITS_PER_WIDE_INT)
     {
       HOST_WIDE_INT const_val = INTVAL (op1);
       unsigned HOST_WIDE_INT uconst_val = const_val;
       unsigned HOST_WIDE_INT max_val
-	= (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0));
+	= (unsigned HOST_WIDE_INT) GET_MODE_MASK (op0_mode);
 
       switch (code)
 	{
 	case LE:
 	  if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
-	    code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0));
+	    code = LT, op1 = gen_int_mode (const_val + 1, op0_mode);
 	  break;
 
 	/* When cross-compiling, const_val might be sign-extended from
 	   BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */
 	case GE:
 	  if ((const_val & max_val)
-	      != (HOST_WIDE_INT_1U
-		  << (GET_MODE_PRECISION (GET_MODE (op0)) - 1)))
-	    code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0));
+	      != (HOST_WIDE_INT_1U << (GET_MODE_PRECISION (op0_mode) - 1)))
+	    code = GT, op1 = gen_int_mode (const_val - 1, op0_mode);
 	  break;
 
 	case LEU:
 	  if (uconst_val < max_val)
-	    code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0));
+	    code = LTU, op1 = gen_int_mode (uconst_val + 1, op0_mode);
 	  break;
 
 	case GEU:
 	  if (uconst_val != 0)
-	    code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0));
+	    code = GTU, op1 = gen_int_mode (uconst_val - 1, op0_mode);
 	  break;
 
 	default:
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e5e7a71..9f44da9 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -4812,19 +4812,19 @@ simplify_relational_operation_1 (enum rtx_code code, machine_mode mode,
 
   /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is
      the same as (zero_extract:SI FOO (const_int 1) BAR).  */
-  scalar_int_mode int_mode;
+  scalar_int_mode int_mode, int_cmp_mode;
   if (code == NE
       && op1 == const0_rtx
       && is_int_mode (mode, &int_mode)
-      && cmp_mode != VOIDmode
+      && is_a <scalar_int_mode> (cmp_mode, &int_cmp_mode)
       /* ??? Work-around BImode bugs in the ia64 backend.  */
       && int_mode != BImode
-      && cmp_mode != BImode
-      && nonzero_bits (op0, cmp_mode) == 1
+      && int_cmp_mode != BImode
+      && nonzero_bits (op0, int_cmp_mode) == 1
       && STORE_FLAG_VALUE == 1)
-    return GET_MODE_SIZE (int_mode) > GET_MODE_SIZE (cmp_mode)
-	   ? simplify_gen_unary (ZERO_EXTEND, int_mode, op0, cmp_mode)
-	   : lowpart_subreg (int_mode, op0, cmp_mode);
+    return GET_MODE_SIZE (int_mode) > GET_MODE_SIZE (int_cmp_mode)
+	   ? simplify_gen_unary (ZERO_EXTEND, int_mode, op0, int_cmp_mode)
+	   : lowpart_subreg (int_mode, op0, int_cmp_mode);
 
   /* (eq/ne (xor x y) 0) simplifies to (eq/ne x y).  */
   if ((code == EQ || code == NE)

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [25/67] Use is_a <scalar_int_mode> for bitmask optimisations
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (24 preceding siblings ...)
  2016-12-09 13:08 ` [23/67] Replace != VOIDmode checks " Richard Sandiford
@ 2016-12-09 13:09 ` Richard Sandiford
  2016-12-09 13:10 ` [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP Richard Sandiford
                   ` (43 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:09 UTC (permalink / raw)
  To: gcc-patches

Explicitly check for scalar_int_mode in code that checks for full-mode
bit operations.  These operations wouldn't work correctly for vector
modes, for example.  In many cases this is enforced also by checking
whether an operand is CONST_INT_P, but there were other cases where the
condition is more indirect.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (combine_simplify_rtx): Add checks for
	is_a <scalar_int_mode>.
	(simplify_if_then_else): Likewise.
	(make_field_assignment): Likewise.
	(simplify_comparison): Likewise.
	* ifcvt.c (noce_try_bitop): Likewise.
	* loop-invariant.c (canonicalize_address_split): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.

diff --git a/gcc/combine.c b/gcc/combine.c
index 8883194..e1e8457 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -5825,13 +5825,14 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
       if (!REG_P (temp)
 	  && ! (GET_CODE (temp) == SUBREG
 		&& REG_P (SUBREG_REG (temp)))
-	  && (i = exact_log2 (nonzero_bits (temp, mode))) >= 0)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && (i = exact_log2 (nonzero_bits (temp, int_mode))) >= 0)
 	{
 	  rtx temp1 = simplify_shift_const
-	    (NULL_RTX, ASHIFTRT, mode,
-	     simplify_shift_const (NULL_RTX, ASHIFT, mode, temp,
-				   GET_MODE_PRECISION (mode) - 1 - i),
-	     GET_MODE_PRECISION (mode) - 1 - i);
+	    (NULL_RTX, ASHIFTRT, int_mode,
+	     simplify_shift_const (NULL_RTX, ASHIFT, int_mode, temp,
+				   GET_MODE_PRECISION (int_mode) - 1 - i),
+	     GET_MODE_PRECISION (int_mode) - 1 - i);
 
 	  /* If all we did was surround TEMP with the two shifts, we
 	     haven't improved anything, so don't use it.  Otherwise,
@@ -5922,12 +5923,15 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 	  && !REG_P (XEXP (x, 0))
 	  && ! (GET_CODE (XEXP (x, 0)) == SUBREG
 		&& REG_P (SUBREG_REG (XEXP (x, 0))))
-	  && nonzero_bits (XEXP (x, 0), mode) == 1)
-	return simplify_shift_const (NULL_RTX, ASHIFTRT, mode,
-	   simplify_shift_const (NULL_RTX, ASHIFT, mode,
-				 gen_rtx_XOR (mode, XEXP (x, 0), const1_rtx),
-				 GET_MODE_PRECISION (mode) - 1),
-	   GET_MODE_PRECISION (mode) - 1);
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && nonzero_bits (XEXP (x, 0), int_mode) == 1)
+	return simplify_shift_const
+	  (NULL_RTX, ASHIFTRT, int_mode,
+	   simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
+				 gen_rtx_XOR (int_mode, XEXP (x, 0),
+					      const1_rtx),
+				 GET_MODE_PRECISION (int_mode) - 1),
+	   GET_MODE_PRECISION (int_mode) - 1);
 
       /* If we are adding two things that have no bits in common, convert
 	 the addition into an IOR.  This will often be further simplified,
@@ -5965,11 +5969,12 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
     case MINUS:
       /* (minus <foo> (and <foo> (const_int -pow2))) becomes
 	 (and <foo> (const_int pow2-1))  */
-      if (GET_CODE (XEXP (x, 1)) == AND
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && GET_CODE (XEXP (x, 1)) == AND
 	  && CONST_INT_P (XEXP (XEXP (x, 1), 1))
 	  && pow2p_hwi (-UINTVAL (XEXP (XEXP (x, 1), 1)))
 	  && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
-	return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
+	return simplify_and_const_int (NULL_RTX, int_mode, XEXP (x, 0),
 				       -INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
       break;
 
@@ -6000,14 +6005,16 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
     case UDIV:
       /* If this is a divide by a power of two, treat it as a shift if
 	 its first operand is a shift.  */
-      if (CONST_INT_P (XEXP (x, 1))
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && CONST_INT_P (XEXP (x, 1))
 	  && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0
 	  && (GET_CODE (XEXP (x, 0)) == ASHIFT
 	      || GET_CODE (XEXP (x, 0)) == LSHIFTRT
 	      || GET_CODE (XEXP (x, 0)) == ASHIFTRT
 	      || GET_CODE (XEXP (x, 0)) == ROTATE
 	      || GET_CODE (XEXP (x, 0)) == ROTATERT))
-	return simplify_shift_const (NULL_RTX, LSHIFTRT, mode, XEXP (x, 0), i);
+	return simplify_shift_const (NULL_RTX, LSHIFTRT, int_mode,
+				     XEXP (x, 0), i);
       break;
 
     case EQ:  case NE:
@@ -6291,22 +6298,28 @@ simplify_if_then_else (rtx x)
 	  std::swap (true_rtx, false_rtx);
 	}
 
-      /* If we are comparing against zero and the expression being tested has
-	 only a single bit that might be nonzero, that is its value when it is
-	 not equal to zero.  Similarly if it is known to be -1 or 0.  */
-
-      if (true_code == EQ && true_val == const0_rtx
-	  && pow2p_hwi (nzb = nonzero_bits (from, GET_MODE (from))))
-	{
-	  false_code = EQ;
-	  false_val = gen_int_mode (nzb, GET_MODE (from));
-	}
-      else if (true_code == EQ && true_val == const0_rtx
-	       && (num_sign_bit_copies (from, GET_MODE (from))
-		   == GET_MODE_PRECISION (GET_MODE (from))))
+      scalar_int_mode from_mode;
+      if (is_a <scalar_int_mode> (GET_MODE (from), &from_mode))
 	{
-	  false_code = EQ;
-	  false_val = constm1_rtx;
+	  /* If we are comparing against zero and the expression being
+	     tested has only a single bit that might be nonzero, that is
+	     its value when it is not equal to zero.  Similarly if it is
+	     known to be -1 or 0.  */
+	  if (true_code == EQ
+	      && true_val == const0_rtx
+	      && pow2p_hwi (nzb = nonzero_bits (from, from_mode)))
+	    {
+	      false_code = EQ;
+	      false_val = gen_int_mode (nzb, from_mode);
+	    }
+	  else if (true_code == EQ
+		   && true_val == const0_rtx
+		   && (num_sign_bit_copies (from, from_mode)
+		       == GET_MODE_PRECISION (from_mode)))
+	    {
+	      false_code = EQ;
+	      false_val = constm1_rtx;
+	    }
 	}
 
       /* Now simplify an arm if we know the value of the register in the
@@ -6556,16 +6569,19 @@ simplify_if_then_else (rtx x)
      negation of a single bit, we can convert this operation to a shift.  We
      can actually do this more generally, but it doesn't seem worth it.  */
 
-  if (true_code == NE && XEXP (cond, 1) == const0_rtx
-      && false_rtx == const0_rtx && CONST_INT_P (true_rtx)
-      && ((1 == nonzero_bits (XEXP (cond, 0), mode)
+  if (true_code == NE
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && XEXP (cond, 1) == const0_rtx
+      && false_rtx == const0_rtx
+      && CONST_INT_P (true_rtx)
+      && ((1 == nonzero_bits (XEXP (cond, 0), int_mode)
 	   && (i = exact_log2 (UINTVAL (true_rtx))) >= 0)
-	  || ((num_sign_bit_copies (XEXP (cond, 0), mode)
-	       == GET_MODE_PRECISION (mode))
+	  || ((num_sign_bit_copies (XEXP (cond, 0), int_mode)
+	       == GET_MODE_PRECISION (int_mode))
 	      && (i = exact_log2 (-UINTVAL (true_rtx))) >= 0)))
     return
-      simplify_shift_const (NULL_RTX, ASHIFT, mode,
-			    gen_lowpart (mode, XEXP (cond, 0)), i);
+      simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
+			    gen_lowpart (int_mode, XEXP (cond, 0)), i);
 
   /* (IF_THEN_ELSE (NE A 0) C1 0) is A or a zero-extend of A if the only
      non-zero bit in A is C1.  */
@@ -9436,7 +9452,11 @@ make_field_assignment (rtx x)
   HOST_WIDE_INT pos;
   unsigned HOST_WIDE_INT len;
   rtx other;
-  machine_mode mode;
+
+  /* All the rules in this function are specific to scalar integers.  */
+  scalar_int_mode mode;
+  if (!is_a <scalar_int_mode> (GET_MODE (dest), &mode))
+    return x;
 
   /* If SRC was (and (not (ashift (const_int 1) POS)) DEST), this is
      a clear of a one-bit field.  We will have changed it to
@@ -9509,7 +9529,6 @@ make_field_assignment (rtx x)
       /* Partial overlap.  We can reduce the source AND.  */
       if ((and_mask & ze_mask) != and_mask)
 	{
-	  mode = GET_MODE (src);
 	  src = gen_rtx_AND (mode, XEXP (src, 0),
 			     gen_int_mode (and_mask & ze_mask, mode));
 	  return gen_rtx_SET (dest, src);
@@ -9528,7 +9547,10 @@ make_field_assignment (rtx x)
      assignment.  The first one we are likely to encounter is an outer
      narrowing SUBREG, which we can just strip for the purposes of
      identifying the constant-field assignment.  */
-  if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src))
+  scalar_int_mode src_mode = mode;
+  if (GET_CODE (src) == SUBREG
+      && subreg_lowpart_p (src)
+      && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (src)), &src_mode))
     src = SUBREG_REG (src);
 
   if (GET_CODE (src) != IOR && GET_CODE (src) != XOR)
@@ -9574,10 +9596,11 @@ make_field_assignment (rtx x)
   else
     return x;
 
-  pos = get_pos_from_mask ((~c1) & GET_MODE_MASK (GET_MODE (dest)), &len);
-  if (pos < 0 || pos + len > GET_MODE_PRECISION (GET_MODE (dest))
-      || GET_MODE_PRECISION (GET_MODE (dest)) > HOST_BITS_PER_WIDE_INT
-      || (c1 & nonzero_bits (other, GET_MODE (dest))) != 0)
+  pos = get_pos_from_mask ((~c1) & GET_MODE_MASK (mode), &len);
+  if (pos < 0
+      || pos + len > GET_MODE_PRECISION (mode)
+      || GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
+      || (c1 & nonzero_bits (other, mode)) != 0)
     return x;
 
   assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0);
@@ -9586,18 +9609,17 @@ make_field_assignment (rtx x)
 
   /* The mode to use for the source is the mode of the assignment, or of
      what is inside a possible STRICT_LOW_PART.  */
-  mode = (GET_CODE (assign) == STRICT_LOW_PART
-	  ? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign));
+  machine_mode new_mode = (GET_CODE (assign) == STRICT_LOW_PART
+			   ? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign));
 
   /* Shift OTHER right POS places and make it the source, restricting it
      to the proper length and mode.  */
 
   src = canon_reg_for_combine (simplify_shift_const (NULL_RTX, LSHIFTRT,
-						     GET_MODE (src),
-						     other, pos),
+						     src_mode, other, pos),
 			       dest);
-  src = force_to_mode (src, mode,
-		       GET_MODE_PRECISION (mode) >= HOST_BITS_PER_WIDE_INT
+  src = force_to_mode (src, new_mode,
+		       len >= HOST_BITS_PER_WIDE_INT
 		       ? HOST_WIDE_INT_M1U
 		       : (HOST_WIDE_INT_1U << len) - 1,
 		       0);
@@ -11711,16 +11733,17 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	  && GET_CODE (XEXP (op1, 0)) == ASHIFT
 	  && GET_CODE (XEXP (XEXP (op0, 0), 0)) == SUBREG
 	  && GET_CODE (XEXP (XEXP (op1, 0), 0)) == SUBREG
-	  && (GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0)))
-	      == GET_MODE (SUBREG_REG (XEXP (XEXP (op1, 0), 0))))
+	  && is_a <scalar_int_mode> (GET_MODE (op0), &mode)
+	  && (is_a <scalar_int_mode>
+	      (GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0))), &inner_mode))
+	  && inner_mode == GET_MODE (SUBREG_REG (XEXP (XEXP (op1, 0), 0)))
 	  && CONST_INT_P (XEXP (op0, 1))
 	  && XEXP (op0, 1) == XEXP (op1, 1)
 	  && XEXP (op0, 1) == XEXP (XEXP (op0, 0), 1)
 	  && XEXP (op0, 1) == XEXP (XEXP (op1, 0), 1)
 	  && (INTVAL (XEXP (op0, 1))
-	      == (GET_MODE_PRECISION (GET_MODE (op0))
-		  - (GET_MODE_PRECISION
-		     (GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0))))))))
+	      == (GET_MODE_PRECISION (mode)
+		  - GET_MODE_PRECISION (inner_mode))))
 	{
 	  op0 = SUBREG_REG (XEXP (XEXP (op0, 0), 0));
 	  op1 = SUBREG_REG (XEXP (XEXP (op1, 0), 0));
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index b22ed41..876353d 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2839,7 +2839,7 @@ noce_try_bitop (struct noce_if_info *if_info)
 {
   rtx cond, x, a, result;
   rtx_insn *seq;
-  machine_mode mode;
+  scalar_int_mode mode;
   enum rtx_code code;
   int bitnum;
 
@@ -2847,6 +2847,10 @@ noce_try_bitop (struct noce_if_info *if_info)
   cond = if_info->cond;
   code = GET_CODE (cond);
 
+  /* Check for an integer operation.  */
+  if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
+    return FALSE;
+
   if (!noce_simple_bbs (if_info))
     return FALSE;
 
@@ -2869,7 +2873,6 @@ noce_try_bitop (struct noce_if_info *if_info)
 	  || ! rtx_equal_p (x, XEXP (cond, 0)))
 	return FALSE;
       bitnum = INTVAL (XEXP (cond, 2));
-      mode = GET_MODE (x);
       if (BITS_BIG_ENDIAN)
 	bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
       if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index f617241..30fdf44 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -774,16 +774,16 @@ canonicalize_address_mult (rtx x)
   FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
     {
       rtx sub = *iter;
-
-      if (GET_CODE (sub) == ASHIFT
+      scalar_int_mode sub_mode;
+      if (is_a <scalar_int_mode> (GET_MODE (sub), &sub_mode)
+	  && GET_CODE (sub) == ASHIFT
 	  && CONST_INT_P (XEXP (sub, 1))
-	  && INTVAL (XEXP (sub, 1)) < GET_MODE_BITSIZE (GET_MODE (sub))
+	  && INTVAL (XEXP (sub, 1)) < GET_MODE_BITSIZE (sub_mode)
 	  && INTVAL (XEXP (sub, 1)) >= 0)
 	{
 	  HOST_WIDE_INT shift = INTVAL (XEXP (sub, 1));
 	  PUT_CODE (sub, MULT);
-	  XEXP (sub, 1) = gen_int_mode (HOST_WIDE_INT_1 << shift,
-					GET_MODE (sub));
+	  XEXP (sub, 1) = gen_int_mode (HOST_WIDE_INT_1 << shift, sub_mode);
 	  iter.skip_subrtxes ();
 	}
     }
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 9f44da9..1e6dd22 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -916,7 +916,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 {
   enum rtx_code reversed;
   rtx temp;
-  scalar_int_mode inner;
+  scalar_int_mode inner, int_mode;
 
   switch (code)
     {
@@ -975,10 +975,11 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	 minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1,
 	 so we can perform the above simplification.  */
       if (STORE_FLAG_VALUE == -1
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && GET_CODE (op) == ASHIFTRT
 	  && CONST_INT_P (XEXP (op, 1))
-	  && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1)
-	return simplify_gen_relational (GE, mode, VOIDmode,
+	  && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (int_mode) - 1)
+	return simplify_gen_relational (GE, int_mode, VOIDmode,
 					XEXP (op, 0), const0_rtx);
 
 
@@ -1328,8 +1329,10 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	return op;
 
       /* If operand is known to be only -1 or 0, convert ABS to NEG.  */
-      if (num_sign_bit_copies (op, mode) == GET_MODE_PRECISION (mode))
-	return gen_rtx_NEG (mode, op);
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && (num_sign_bit_copies (op, int_mode)
+	      == GET_MODE_PRECISION (int_mode)))
+	return gen_rtx_NEG (int_mode, op);
 
       break;
 
@@ -1483,12 +1486,13 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	 is similarly (zero_extend:M (subreg:O <X>)).  */
       if ((GET_CODE (op) == ASHIFTRT || GET_CODE (op) == LSHIFTRT)
 	  && GET_CODE (XEXP (op, 0)) == ASHIFT
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && CONST_INT_P (XEXP (op, 1))
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
 	  && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
 	{
 	  scalar_int_mode tmode;
-	  gcc_assert (GET_MODE_BITSIZE (mode)
+	  gcc_assert (GET_MODE_BITSIZE (int_mode)
 		      > GET_MODE_BITSIZE (GET_MODE (op)));
 	  if (int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
 				 - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
@@ -1498,7 +1502,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	      if (inner)
 		return simplify_gen_unary (GET_CODE (op) == ASHIFTRT
 					   ? SIGN_EXTEND : ZERO_EXTEND,
-					   mode, inner, tmode);
+					   int_mode, inner, tmode);
 	    }
 	}
 
@@ -1599,6 +1603,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	 GET_MODE_PRECISION (N) - I bits.  */
       if (GET_CODE (op) == LSHIFTRT
 	  && GET_CODE (XEXP (op, 0)) == ASHIFT
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && CONST_INT_P (XEXP (op, 1))
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
 	  && GET_MODE_PRECISION (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
@@ -1610,7 +1615,8 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	      rtx inner =
 		rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
 	      if (inner)
-		return simplify_gen_unary (ZERO_EXTEND, mode, inner, tmode);
+		return simplify_gen_unary (ZERO_EXTEND, int_mode,
+					   inner, tmode);
 	    }
 	}
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (25 preceding siblings ...)
  2016-12-09 13:09 ` [25/67] Use is_a <scalar_int_mode> for bitmask optimisations Richard Sandiford
@ 2016-12-09 13:10 ` Richard Sandiford
  2016-12-09 13:10 ` [26/67] Use is_a <scalar_int_mode> in subreg/extract simplifications Richard Sandiford
                   ` (42 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:10 UTC (permalink / raw)
  To: gcc-patches

Add is_a <scalar_int_mode> checks before load_extend_op/
LOAD_EXTEND_OP calls, if that becomes useful for later patches.
(load_extend_op will return UNKNOWN for any other type of mode.)

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* cse.c (cse_insn): Add is_a <scalar_int_mode> checks.
	* reload.c (push_reload): Likewise.

diff --git a/gcc/cse.c b/gcc/cse.c
index cc29d4a..e3fda8e 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4923,7 +4923,8 @@ cse_insn (rtx_insn *insn)
       rtx_code extend_op;
       if (flag_expensive_optimizations && src_related == 0
 	  && MEM_P (src) && ! do_not_record
-	  && (extend_op = load_extend_op (mode)) != UNKNOWN)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && (extend_op = load_extend_op (int_mode)) != UNKNOWN)
 	{
 	  struct rtx_def memory_extend_buf;
 	  rtx memory_extend_rtx = &memory_extend_buf;
@@ -4935,7 +4936,7 @@ cse_insn (rtx_insn *insn)
 	  PUT_CODE (memory_extend_rtx, extend_op);
 	  XEXP (memory_extend_rtx, 0) = src;
 
-	  FOR_EACH_WIDER_MODE (tmode, mode)
+	  FOR_EACH_WIDER_MODE (tmode, int_mode)
 	    {
 	      struct table_elt *larger_elt;
 
@@ -4952,7 +4953,7 @@ cse_insn (rtx_insn *insn)
 		   larger_elt; larger_elt = larger_elt->next_same_value)
 		if (REG_P (larger_elt->exp))
 		  {
-		    src_related = gen_lowpart (mode, larger_elt->exp);
+		    src_related = gen_lowpart (int_mode, larger_elt->exp);
 		    break;
 		  }
 
diff --git a/gcc/reload.c b/gcc/reload.c
index 4d75fda..a513cf4 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -1050,6 +1050,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
      register class.  But if it is inside a STRICT_LOW_PART, we have
      no choice, so we hope we do get the right register class there.  */
 
+#ifdef LOAD_EXTEND_OP
+  scalar_int_mode inner_int_mode;
+#endif
   if (in != 0 && GET_CODE (in) == SUBREG
       && (subreg_lowpart_p (in) || strict_low)
 #ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1065,12 +1068,12 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
 	      && ((GET_MODE_PRECISION (inmode)
 		   > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
 		  || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
-		      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
-			  <= UNITS_PER_WORD)
+		      && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (in)),
+						 &inner_int_mode)
+		      && GET_MODE_SIZE (inner_int_mode) <= UNITS_PER_WORD
 		      && (GET_MODE_PRECISION (inmode)
-			  > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
-		      && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
-		      && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
+			  > GET_MODE_PRECISION (inner_int_mode))
+		      && LOAD_EXTEND_OP (inner_int_mode) != UNKNOWN)
 		  || (WORD_REGISTER_OPERATIONS
 		      && (GET_MODE_PRECISION (inmode)
 			  < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
@@ -3108,6 +3111,9 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
 		  operand = SUBREG_REG (operand);
 		  /* Force reload if this is a constant or PLUS or if there may
 		     be a problem accessing OPERAND in the outer mode.  */
+#ifdef LOAD_EXTEND_OP
+		  scalar_int_mode int_mode;
+#endif
 		  if (CONSTANT_P (operand)
 		      || GET_CODE (operand) == PLUS
 		      /* We must force a reload of paradoxical SUBREGs
@@ -3145,13 +3151,13 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
 			      || BYTES_BIG_ENDIAN
 			      || ((GET_MODE_SIZE (operand_mode[i])
 				   <= UNITS_PER_WORD)
-				  && (GET_MODE_SIZE (GET_MODE (operand))
+				  && (is_a <scalar_int_mode>
+				      (GET_MODE (operand), &int_mode))
+				  && (GET_MODE_SIZE (int_mode)
 				      <= UNITS_PER_WORD)
 				  && (GET_MODE_SIZE (operand_mode[i])
-				      > GET_MODE_SIZE (GET_MODE (operand)))
-				  && INTEGRAL_MODE_P (GET_MODE (operand))
-				  && LOAD_EXTEND_OP (GET_MODE (operand))
-				     != UNKNOWN)))
+				      > GET_MODE_SIZE (int_mode))
+				  && LOAD_EXTEND_OP (int_mode) != UNKNOWN)))
 		      )
 		    force_reload = 1;
 		}

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [26/67] Use is_a <scalar_int_mode> in subreg/extract simplifications
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (26 preceding siblings ...)
  2016-12-09 13:10 ` [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP Richard Sandiford
@ 2016-12-09 13:10 ` Richard Sandiford
  2016-12-09 13:11 ` [28/67] Use is_a <scalar_int_mode> for miscellaneous types of test Richard Sandiford
                   ` (41 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:10 UTC (permalink / raw)
  To: gcc-patches

Add is_a <scalar_int_mode> checks to various places that were
optimising subregs or extractions in ways that only made sense
for scalar integers.  Often the subreg transformations were
looking for extends, truncates or shifts and trying to remove
the subreg, which wouldn't be correct if the SUBREG_REG was
a vector rather than a scalar.

The simplify_binary_operation_1 part also removes a redundant:

  GET_MODE (opleft) == GET_MODE (XEXP (opright, 0))

since this must be true for:

  (ior A (lshifrt B ...))  A == opleft, B == XEXP (opright, 0)

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (find_split_point): Add is_a <scalar_int_mode> checks.
	(make_compound_operation): Likewise.
	(change_zero_ext): Likewise.
	* expr.c (convert_move): Likewise.
	(convert_modes): Likewise.
	* fwprop.c (forward_propagate_subreg): Likewise.
	* loop-iv.c (get_biv_step_1): Likewise.
	* optabs.c (widen_operand): Likewise.
	* postreload.c (move2add_valid_value_p): Likewise.
	* recog.c (simplify_while_replacing): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.
	(simplify_binary_operation_1): Likewise.  Remove redundant
	mode equality check.

diff --git a/gcc/combine.c b/gcc/combine.c
index e1e8457..7f943be 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4768,7 +4768,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
   HOST_WIDE_INT pos = 0;
   int unsignedp = 0;
   rtx inner = NULL_RTX;
-  scalar_int_mode inner_mode;
+  scalar_int_mode mode, inner_mode;
 
   /* First special-case some codes.  */
   switch (code)
@@ -5022,7 +5022,9 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
 
 	case SIGN_EXTRACT:
 	case ZERO_EXTRACT:
-	  if (CONST_INT_P (XEXP (SET_SRC (x), 1))
+	  if (is_a <scalar_int_mode> (GET_MODE (XEXP (SET_SRC (x), 0)),
+				      &inner_mode)
+	      && CONST_INT_P (XEXP (SET_SRC (x), 1))
 	      && CONST_INT_P (XEXP (SET_SRC (x), 2)))
 	    {
 	      inner = XEXP (SET_SRC (x), 0);
@@ -5030,7 +5032,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
 	      pos = INTVAL (XEXP (SET_SRC (x), 2));
 
 	      if (BITS_BIG_ENDIAN)
-		pos = GET_MODE_PRECISION (GET_MODE (inner)) - len - pos;
+		pos = GET_MODE_PRECISION (inner_mode) - len - pos;
 	      unsignedp = (code == ZERO_EXTRACT);
 	    }
 	  break;
@@ -5040,10 +5042,9 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
 	}
 
       if (len && pos >= 0
-	  && pos + len <= GET_MODE_PRECISION (GET_MODE (inner)))
+	  && pos + len <= GET_MODE_PRECISION (GET_MODE (inner))
+	  && is_a <scalar_int_mode> (GET_MODE (SET_SRC (x)), &mode))
 	{
-	  machine_mode mode = GET_MODE (SET_SRC (x));
-
 	  /* For unsigned, we have a choice of a shift followed by an
 	     AND or two shifts.  Use two shifts for field sizes where the
 	     constant might be too large.  We assume here that we can
@@ -7836,6 +7837,7 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
   int i;
   rtx tem;
   bool equality_comparison = false;
+  scalar_int_mode inner_mode;
 
   if (in_code == EQ)
     {
@@ -7943,11 +7945,12 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
       /* Same as previous, but for (subreg (lshiftrt ...)) in first op.  */
       else if (GET_CODE (XEXP (x, 0)) == SUBREG
 	       && subreg_lowpart_p (XEXP (x, 0))
+	       && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (XEXP (x, 0))),
+					  &inner_mode)
 	       && GET_CODE (SUBREG_REG (XEXP (x, 0))) == LSHIFTRT
 	       && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
 	{
 	  rtx inner_x0 = SUBREG_REG (XEXP (x, 0));
-	  machine_mode inner_mode = GET_MODE (inner_x0);
 	  new_rtx = make_compound_operation (XEXP (inner_x0, 0), next_code);
 	  new_rtx = make_extraction (inner_mode, new_rtx, 0,
 				     XEXP (inner_x0, 1),
@@ -8146,10 +8149,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
 	/* If the SUBREG is masking of a logical right shift,
 	   make an extraction.  */
 	if (GET_CODE (inner) == LSHIFTRT
+	    && is_a <scalar_int_mode> (GET_MODE (inner), &inner_mode)
+	    && GET_MODE_SIZE (mode) < GET_MODE_SIZE (inner_mode)
 	    && CONST_INT_P (XEXP (inner, 1))
-	    && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
-	    && (UINTVAL (XEXP (inner, 1))
-		< GET_MODE_PRECISION (GET_MODE (inner)))
+	    && UINTVAL (XEXP (inner, 1)) < GET_MODE_PRECISION (inner_mode)
 	    && subreg_lowpart_p (x))
 	  {
 	    new_rtx = make_compound_operation (XEXP (inner, 0), next_code);
@@ -11324,15 +11327,16 @@ change_zero_ext (rtx pat)
       maybe_swap_commutative_operands (**iter);
 
   rtx *dst = &SET_DEST (pat);
+  scalar_int_mode mode;
   if (GET_CODE (*dst) == ZERO_EXTRACT
       && REG_P (XEXP (*dst, 0))
+      && is_a <scalar_int_mode> (GET_MODE (XEXP (*dst, 0)), &mode)
       && CONST_INT_P (XEXP (*dst, 1))
       && CONST_INT_P (XEXP (*dst, 2)))
     {
       rtx reg = XEXP (*dst, 0);
       int width = INTVAL (XEXP (*dst, 1));
       int offset = INTVAL (XEXP (*dst, 2));
-      machine_mode mode = GET_MODE (reg);
       int reg_width = GET_MODE_PRECISION (mode);
       if (BITS_BIG_ENDIAN)
 	offset = reg_width - width - offset;
diff --git a/gcc/expr.c b/gcc/expr.c
index 467c873..843c402 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -237,11 +237,14 @@ convert_move (rtx to, rtx from, int unsignedp)
      the required extension, strip it.  We don't handle such SUBREGs as
      TO here.  */
 
-  if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
+  scalar_int_mode to_int_mode;
+  if (GET_CODE (from) == SUBREG
+      && SUBREG_PROMOTED_VAR_P (from)
+      && is_a <scalar_int_mode> (to_mode, &to_int_mode)
       && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (from)))
-	  >= GET_MODE_PRECISION (to_mode))
+	  >= GET_MODE_PRECISION (to_int_mode))
       && SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp))
-    from = gen_lowpart (to_mode, from), from_mode = to_mode;
+    from = gen_lowpart (to_int_mode, from), from_mode = to_int_mode;
 
   gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to));
 
@@ -633,10 +636,12 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
   /* If FROM is a SUBREG that indicates that we have already done at least
      the required extension, strip it.  */
 
-  if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
-      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
+  if (GET_CODE (x) == SUBREG
+      && SUBREG_PROMOTED_VAR_P (x)
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (int_mode)
       && SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
-    x = gen_lowpart (mode, SUBREG_REG (x));
+    x = gen_lowpart (int_mode, SUBREG_REG (x));
 
   if (GET_MODE (x) != VOIDmode)
     oldmode = GET_MODE (x);
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index a3fbb34..2f22e4d 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -1089,6 +1089,7 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
   rtx use_reg = DF_REF_REG (use);
   rtx_insn *use_insn;
   rtx src;
+  scalar_int_mode int_use_mode, src_mode;
 
   /* Only consider subregs... */
   machine_mode use_mode = GET_MODE (use_reg);
@@ -1132,17 +1133,19 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set)
      definition of Y or, failing that, allow A to be deleted after
      reload through register tying.  Introducing more uses of Y
      prevents both optimisations.  */
-  else if (subreg_lowpart_p (use_reg))
+  else if (is_a <scalar_int_mode> (use_mode, &int_use_mode)
+	   && subreg_lowpart_p (use_reg))
     {
       use_insn = DF_REF_INSN (use);
       src = SET_SRC (def_set);
       if ((GET_CODE (src) == ZERO_EXTEND
 	   || GET_CODE (src) == SIGN_EXTEND)
+	  && is_a <scalar_int_mode> (GET_MODE (src), &src_mode)
 	  && REG_P (XEXP (src, 0))
 	  && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
 	  && GET_MODE (XEXP (src, 0)) == use_mode
 	  && !free_load_extend (src, def_insn)
-	  && (targetm.mode_rep_extended (use_mode, GET_MODE (src))
+	  && (targetm.mode_rep_extended (int_use_mode, src_mode)
 	      != (int) GET_CODE (src))
 	  && all_uses_available_at (def_insn, use_insn))
 	return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0),
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 9e13938..f684da2 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -739,9 +739,9 @@ get_biv_step_1 (df_ref def, rtx reg,
 
   if (GET_CODE (next) == SUBREG)
     {
-      machine_mode amode = GET_MODE (next);
-
-      if (GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode))
+      scalar_int_mode amode;
+      if (!is_a <scalar_int_mode> (GET_MODE (next), &amode)
+	  || GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode))
 	return false;
 
       *inner_mode = amode;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index b641cbe..acf89bd 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -195,6 +195,7 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
 	       int unsignedp, int no_extend)
 {
   rtx result;
+  scalar_int_mode int_mode;
 
   /* If we don't have to extend and this is a constant, return it.  */
   if (no_extend && GET_MODE (op) == VOIDmode)
@@ -204,19 +205,20 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
      extend since it will be more efficient to do so unless the signedness of
      a promoted object differs from our extension.  */
   if (! no_extend
+      || !is_a <scalar_int_mode> (mode, &int_mode)
       || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
 	  && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp)))
     return convert_modes (mode, oldmode, op, unsignedp);
 
   /* If MODE is no wider than a single word, we return a lowpart or paradoxical
      SUBREG.  */
-  if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
-    return gen_lowpart (mode, force_reg (GET_MODE (op), op));
+  if (GET_MODE_SIZE (int_mode) <= UNITS_PER_WORD)
+    return gen_lowpart (int_mode, force_reg (GET_MODE (op), op));
 
   /* Otherwise, get an object of MODE, clobber it, and set the low-order
      part to OP.  */
 
-  result = gen_reg_rtx (mode);
+  result = gen_reg_rtx (int_mode);
   emit_clobber (result);
   emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
   return result;
diff --git a/gcc/postreload.c b/gcc/postreload.c
index ff77d4c..ff7e7c3 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1694,14 +1694,16 @@ move2add_valid_value_p (int regno, machine_mode mode)
 
   if (mode != reg_mode[regno])
     {
-      if (!MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno]))
+      scalar_int_mode old_mode;
+      if (!is_a <scalar_int_mode> (reg_mode[regno], &old_mode)
+	  || !MODES_OK_FOR_MOVE2ADD (mode, old_mode))
 	return false;
       /* The value loaded into regno in reg_mode[regno] is also valid in
 	 mode after truncation only if (REG:mode regno) is the lowpart of
 	 (REG:reg_mode[regno] regno).  Now, for big endian, the starting
 	 regno of the lowpart might be different.  */
-      int s_off = subreg_lowpart_offset (mode, reg_mode[regno]);
-      s_off = subreg_regno_offset (regno, reg_mode[regno], s_off, mode);
+      int s_off = subreg_lowpart_offset (mode, old_mode);
+      s_off = subreg_regno_offset (regno, old_mode, s_off, mode);
       if (s_off != 0)
 	/* We could in principle adjust regno, check reg_mode[regno] to be
 	   BLKmode, and return s_off to the caller (vs. -1 for failure),
diff --git a/gcc/recog.c b/gcc/recog.c
index 22b5aaa..3a17de2 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -560,6 +560,7 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
   rtx x = *loc;
   enum rtx_code code = GET_CODE (x);
   rtx new_rtx = NULL_RTX;
+  scalar_int_mode is_mode;
 
   if (SWAPPABLE_OPERANDS_P (x)
       && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
@@ -655,6 +656,7 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
          happen, we might just fail in some cases).  */
 
       if (MEM_P (XEXP (x, 0))
+	  && is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &is_mode)
 	  && CONST_INT_P (XEXP (x, 1))
 	  && CONST_INT_P (XEXP (x, 2))
 	  && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0),
@@ -662,7 +664,6 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
 	  && !MEM_VOLATILE_P (XEXP (x, 0)))
 	{
 	  machine_mode wanted_mode = VOIDmode;
-	  machine_mode is_mode = GET_MODE (XEXP (x, 0));
 	  int pos = INTVAL (XEXP (x, 2));
 
 	  if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ())
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 1e6dd22..854d026 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -916,7 +916,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 {
   enum rtx_code reversed;
   rtx temp;
-  scalar_int_mode inner, int_mode;
+  scalar_int_mode inner, int_mode, op0_mode;
 
   switch (code)
     {
@@ -1626,21 +1626,19 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	 (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is
 	 (and:SI (reg:SI) (const_int 63)).  */
       if (GET_CODE (op) == SUBREG
-	  && GET_MODE_PRECISION (GET_MODE (op))
-	     < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
-	  && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
-	     <= HOST_BITS_PER_WIDE_INT
-	  && GET_MODE_PRECISION (mode)
-	     >= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &op0_mode)
+	  && GET_MODE_PRECISION (GET_MODE (op)) < GET_MODE_PRECISION (op0_mode)
+	  && GET_MODE_PRECISION (op0_mode) <= HOST_BITS_PER_WIDE_INT
+	  && GET_MODE_PRECISION (int_mode) >= GET_MODE_PRECISION (op0_mode)
 	  && subreg_lowpart_p (op)
-	  && (nonzero_bits (SUBREG_REG (op), GET_MODE (SUBREG_REG (op)))
+	  && (nonzero_bits (SUBREG_REG (op), op0_mode)
 	      & ~GET_MODE_MASK (GET_MODE (op))) == 0)
 	{
-	  if (GET_MODE_PRECISION (mode)
-	      == GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))))
+	  if (GET_MODE_PRECISION (int_mode) == GET_MODE_PRECISION (op0_mode))
 	    return SUBREG_REG (op);
-	  return simplify_gen_unary (ZERO_EXTEND, mode, SUBREG_REG (op),
-				     GET_MODE (SUBREG_REG (op)));
+	  return simplify_gen_unary (ZERO_EXTEND, int_mode, SUBREG_REG (op),
+				     op0_mode);
 	}
 
 #if defined(POINTERS_EXTEND_UNSIGNED)
@@ -2702,21 +2700,23 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
         by simplify_shift_const.  */
 
       if (GET_CODE (opleft) == SUBREG
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)),
+				     &inner_mode)
           && GET_CODE (SUBREG_REG (opleft)) == ASHIFT
           && GET_CODE (opright) == LSHIFTRT
           && GET_CODE (XEXP (opright, 0)) == SUBREG
-          && GET_MODE (opleft) == GET_MODE (XEXP (opright, 0))
           && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0))
-          && (GET_MODE_SIZE (GET_MODE (opleft))
-              < GET_MODE_SIZE (GET_MODE (SUBREG_REG (opleft))))
+	  && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode)
           && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0),
                           SUBREG_REG (XEXP (opright, 0)))
           && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1))
           && CONST_INT_P (XEXP (opright, 1))
-          && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1))
-              == GET_MODE_PRECISION (mode)))
-        return gen_rtx_ROTATE (mode, XEXP (opright, 0),
-                               XEXP (SUBREG_REG (opleft), 1));
+	  && (INTVAL (XEXP (SUBREG_REG (opleft), 1))
+	      + INTVAL (XEXP (opright, 1))
+	      == GET_MODE_PRECISION (int_mode)))
+	return gen_rtx_ROTATE (int_mode, XEXP (opright, 0),
+			       XEXP (SUBREG_REG (opleft), 1));
 
       /* If we have (ior (and (X C1) C2)), simplify this by making
 	 C1 as small as possible if C1 actually changes.  */

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [28/67] Use is_a <scalar_int_mode> for miscellaneous types of test
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (27 preceding siblings ...)
  2016-12-09 13:10 ` [26/67] Use is_a <scalar_int_mode> in subreg/extract simplifications Richard Sandiford
@ 2016-12-09 13:11 ` Richard Sandiford
  2016-12-09 13:12 ` [30/67] Use scalar_int_mode for doubleword splits Richard Sandiford
                   ` (40 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:11 UTC (permalink / raw)
  To: gcc-patches

This patch adds is_a <scalar_int_mode> checks to various places
that were explicitly or implicitly restricted to integers already,
in cases where adding an explicit is_a <scalar_int_mode> is useful
for later patches.

In simplify_if_then_else, the:

  GET_MODE (XEXP (XEXP (t, 0), N))

expressions were equivalent to:

  GET_MODE (XEXP (t, 0))

due to the type of operation.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (sign_extend_short_imm): Add is_a <scalar_int_mode>
	checks.
	(try_combine): Likewise.
	(simplify_if_then_else): Likewise.
	* cse.c (cse_insn): Likewise.
	* dwarf2out.c (mem_loc_descriptor): Likewise.
	* emit-rtl.c (gen_lowpart_common): Likewise.
	* simplify-rtx.c (simplify_truncation): Likewise.
	(simplify_ternary_operation): Likewise.
	* tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Likewise.

diff --git a/gcc/combine.c b/gcc/combine.c
index 7f943be..92b2ec9 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -1631,11 +1631,13 @@ setup_incoming_promotions (rtx_insn *first)
 static rtx
 sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec)
 {
-  if (GET_MODE_PRECISION (mode) < prec
-      && CONST_INT_P (src)
+  scalar_int_mode int_mode;
+  if (CONST_INT_P (src)
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_PRECISION (int_mode) < prec
       && INTVAL (src) > 0
-      && val_signbit_known_set_p (mode, INTVAL (src)))
-    src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (mode));
+      && val_signbit_known_set_p (int_mode, INTVAL (src)))
+    src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (int_mode));
 
   return src;
 }
@@ -3150,6 +3152,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       rtx op0 = i2src, op1 = XEXP (SET_SRC (PATTERN (i3)), 1);
       machine_mode compare_mode, orig_compare_mode;
       enum rtx_code compare_code = UNKNOWN, orig_compare_code = UNKNOWN;
+      scalar_int_mode mode;
 
       newpat = PATTERN (i3);
       newpat_dest = SET_DEST (newpat);
@@ -3160,8 +3163,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 					    &cc_use_insn)))
 	{
 	  compare_code = orig_compare_code = GET_CODE (*cc_use_loc);
-	  compare_code = simplify_compare_const (compare_code,
-						 GET_MODE (i2dest), op0, &op1);
+	  if (is_a <scalar_int_mode> (GET_MODE (i2dest), &mode))
+	    compare_code = simplify_compare_const (compare_code, mode,
+						   op0, &op1);
 	  target_canonicalize_comparison (&compare_code, &op0, &op1, 1);
 	}
 
@@ -6263,7 +6267,7 @@ simplify_if_then_else (rtx x)
   int i;
   enum rtx_code false_code;
   rtx reversed;
-  scalar_int_mode int_mode;
+  scalar_int_mode int_mode, inner_mode;
 
   /* Simplify storing of the truth value.  */
   if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
@@ -6458,7 +6462,7 @@ simplify_if_then_else (rtx x)
       rtx cond_op0 = XEXP (cond, 0);
       rtx cond_op1 = XEXP (cond, 1);
       enum rtx_code op = UNKNOWN, extend_op = UNKNOWN;
-      machine_mode m = int_mode;
+      scalar_int_mode m = int_mode;
       rtx z = 0, c1 = NULL_RTX;
 
       if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
@@ -6475,6 +6479,7 @@ simplify_if_then_else (rtx x)
 	       && rtx_equal_p (XEXP (t, 1), f))
 	c1 = XEXP (t, 0), op = GET_CODE (t), z = f;
       else if (GET_CODE (t) == SIGN_EXTEND
+	       && is_a <scalar_int_mode> (GET_MODE (XEXP (t, 0)), &inner_mode)
 	       && (GET_CODE (XEXP (t, 0)) == PLUS
 		   || GET_CODE (XEXP (t, 0)) == MINUS
 		   || GET_CODE (XEXP (t, 0)) == IOR
@@ -6488,13 +6493,14 @@ simplify_if_then_else (rtx x)
 	       && (num_sign_bit_copies (f, GET_MODE (f))
 		   > (unsigned int)
 		     (GET_MODE_PRECISION (int_mode)
-		      - GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (t, 0), 0))))))
+		      - GET_MODE_PRECISION (inner_mode))))
 	{
 	  c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
 	  extend_op = SIGN_EXTEND;
-	  m = GET_MODE (XEXP (t, 0));
+	  m = inner_mode;
 	}
       else if (GET_CODE (t) == SIGN_EXTEND
+	       && is_a <scalar_int_mode> (GET_MODE (XEXP (t, 0)), &inner_mode)
 	       && (GET_CODE (XEXP (t, 0)) == PLUS
 		   || GET_CODE (XEXP (t, 0)) == IOR
 		   || GET_CODE (XEXP (t, 0)) == XOR)
@@ -6504,13 +6510,14 @@ simplify_if_then_else (rtx x)
 	       && (num_sign_bit_copies (f, GET_MODE (f))
 		   > (unsigned int)
 		     (GET_MODE_PRECISION (int_mode)
-		      - GET_MODE_PRECISION (GET_MODE (XEXP (XEXP (t, 0), 1))))))
+		      - GET_MODE_PRECISION (inner_mode))))
 	{
 	  c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
 	  extend_op = SIGN_EXTEND;
-	  m = GET_MODE (XEXP (t, 0));
+	  m = inner_mode;
 	}
       else if (GET_CODE (t) == ZERO_EXTEND
+	       && is_a <scalar_int_mode> (GET_MODE (XEXP (t, 0)), &inner_mode)
 	       && (GET_CODE (XEXP (t, 0)) == PLUS
 		   || GET_CODE (XEXP (t, 0)) == MINUS
 		   || GET_CODE (XEXP (t, 0)) == IOR
@@ -6523,14 +6530,15 @@ simplify_if_then_else (rtx x)
 	       && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
 	       && ((nonzero_bits (f, GET_MODE (f))
-		    & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 0))))
+		    & ~GET_MODE_MASK (inner_mode))
 		   == 0))
 	{
 	  c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
 	  extend_op = ZERO_EXTEND;
-	  m = GET_MODE (XEXP (t, 0));
+	  m = inner_mode;
 	}
       else if (GET_CODE (t) == ZERO_EXTEND
+	       && is_a <scalar_int_mode> (GET_MODE (XEXP (t, 0)), &inner_mode)
 	       && (GET_CODE (XEXP (t, 0)) == PLUS
 		   || GET_CODE (XEXP (t, 0)) == IOR
 		   || GET_CODE (XEXP (t, 0)) == XOR)
@@ -6539,12 +6547,12 @@ simplify_if_then_else (rtx x)
 	       && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
 	       && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
 	       && ((nonzero_bits (f, GET_MODE (f))
-		    & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 1))))
+		    & ~GET_MODE_MASK (inner_mode))
 		   == 0))
 	{
 	  c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
 	  extend_op = ZERO_EXTEND;
-	  m = GET_MODE (XEXP (t, 0));
+	  m = inner_mode;
 	}
 
       if (z)
diff --git a/gcc/cse.c b/gcc/cse.c
index e3fda8e..2f29062 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4878,13 +4878,14 @@ cse_insn (rtx_insn *insn)
 	 value.  */
 
       if (flag_expensive_optimizations && ! src_related
+	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))
-	  && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+	  && GET_MODE_SIZE (int_mode) < UNITS_PER_WORD)
 	{
 	  machine_mode tmode;
 	  rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
 
-	  FOR_EACH_WIDER_MODE (tmode, mode)
+	  FOR_EACH_WIDER_MODE (tmode, int_mode)
 	    {
 	      if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
 		break;
@@ -4905,7 +4906,7 @@ cse_insn (rtx_insn *insn)
 		    if (REG_P (larger_elt->exp))
 		      {
 			src_related
-			  = gen_lowpart (mode, larger_elt->exp);
+			  = gen_lowpart (int_mode, larger_elt->exp);
 			break;
 		      }
 
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7bf210d..0b8b12d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14626,31 +14626,29 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 
     case SIGN_EXTEND:
     case ZERO_EXTEND:
-      if (!is_a <scalar_int_mode> (mode, &int_mode))
+      if (!is_a <scalar_int_mode> (mode, &int_mode)
+	  || !is_a <scalar_int_mode> (GET_MODE (XEXP (rtl, 0)), &inner_mode))
 	break;
-      op0 = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (XEXP (rtl, 0)),
+      op0 = mem_loc_descriptor (XEXP (rtl, 0), inner_mode,
 				mem_mode, VAR_INIT_STATUS_INITIALIZED);
       if (op0 == 0)
 	break;
       else if (GET_CODE (rtl) == ZERO_EXTEND
 	       && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
-	       && GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0)))
-		  < HOST_BITS_PER_WIDE_INT
+	       && GET_MODE_BITSIZE (inner_mode) < HOST_BITS_PER_WIDE_INT
 	       /* If DW_OP_const{1,2,4}u won't be used, it is shorter
 		  to expand zero extend as two shifts instead of
 		  masking.  */
-	       && GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) <= 4)
+	       && GET_MODE_SIZE (inner_mode) <= 4)
 	{
-	  machine_mode imode = GET_MODE (XEXP (rtl, 0));
 	  mem_loc_result = op0;
 	  add_loc_descr (&mem_loc_result,
-			 int_loc_descriptor (GET_MODE_MASK (imode)));
+			 int_loc_descriptor (GET_MODE_MASK (inner_mode)));
 	  add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_and, 0, 0));
 	}
       else if (GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE)
 	{
-	  int shift = DWARF2_ADDR_SIZE
-		      - GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)));
+	  int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (inner_mode);
 	  shift *= BITS_PER_UNIT;
 	  if (GET_CODE (rtl) == SIGN_EXTEND)
 	    op = DW_OP_shra;
@@ -14667,7 +14665,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  dw_die_ref type_die1, type_die2;
 	  dw_loc_descr_ref cvt;
 
-	  type_die1 = base_type_for_mode (GET_MODE (XEXP (rtl, 0)),
+	  type_die1 = base_type_for_mode (inner_mode,
 					  GET_CODE (rtl) == ZERO_EXTEND);
 	  if (type_die1 == NULL)
 	    break;
@@ -15212,14 +15210,15 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       if (CONST_INT_P (XEXP (rtl, 1))
 	  && CONST_INT_P (XEXP (rtl, 2))
 	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && is_a <scalar_int_mode> (GET_MODE (XEXP (rtl, 0)), &inner_mode)
+	  && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
+	  && GET_MODE_SIZE (inner_mode) <= DWARF2_ADDR_SIZE
 	  && ((unsigned) INTVAL (XEXP (rtl, 1))
 	      + (unsigned) INTVAL (XEXP (rtl, 2))
-	      <= GET_MODE_BITSIZE (int_mode))
-	  && GET_MODE_SIZE (int_mode) <= DWARF2_ADDR_SIZE
-	  && GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) <= DWARF2_ADDR_SIZE)
+	      <= GET_MODE_BITSIZE (int_mode)))
 	{
 	  int shift, size;
-	  op0 = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (XEXP (rtl, 0)),
+	  op0 = mem_loc_descriptor (XEXP (rtl, 0), inner_mode,
 				    mem_mode, VAR_INIT_STATUS_INITIALIZED);
 	  if (op0 == 0)
 	    break;
@@ -15231,8 +15230,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	  size = INTVAL (XEXP (rtl, 1));
 	  shift = INTVAL (XEXP (rtl, 2));
 	  if (BITS_BIG_ENDIAN)
-	    shift = GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0)))
-		    - shift - size;
+	    shift = GET_MODE_BITSIZE (inner_mode) - shift - size;
 	  if (shift + size != (int) DWARF2_ADDR_SIZE)
 	    {
 	      add_loc_descr (&mem_loc_result,
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 569a478..9fbd7a2 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1408,9 +1408,11 @@ gen_lowpart_common (machine_mode mode, rtx x)
   if (SCALAR_FLOAT_MODE_P (mode) && msize > xsize)
     return 0;
 
+  scalar_int_mode int_mode, int_innermode, from_mode;
   if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
-      && (GET_MODE_CLASS (mode) == MODE_INT
-	  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT))
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && is_a <scalar_int_mode> (innermode, &int_innermode)
+      && is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &from_mode))
     {
       /* If we are getting the low-order part of something that has been
 	 sign- or zero-extended, we can either just use the object being
@@ -1420,12 +1422,12 @@ gen_lowpart_common (machine_mode mode, rtx x)
 
 	 This case is used mostly by combine and cse.  */
 
-      if (GET_MODE (XEXP (x, 0)) == mode)
+      if (from_mode == int_mode)
 	return XEXP (x, 0);
-      else if (msize < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
-	return gen_lowpart_common (mode, XEXP (x, 0));
-      else if (msize < xsize)
-	return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
+      else if (GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (from_mode))
+	return gen_lowpart_common (int_mode, XEXP (x, 0));
+      else if (GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (int_innermode))
+	return gen_rtx_fmt_e (GET_CODE (x), int_mode, XEXP (x, 0));
     }
   else if (GET_CODE (x) == SUBREG || REG_P (x)
 	   || GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 854d026..ac7cb24 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -808,21 +808,22 @@ simplify_truncation (machine_mode mode, rtx op,
      if the MEM has a mode-dependent address.  */
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)
+      && is_a <scalar_int_mode> (mode, &int_mode)
       && is_a <scalar_int_mode> (op_mode, &int_op_mode)
       && MEM_P (XEXP (op, 0))
       && CONST_INT_P (XEXP (op, 1))
-      && (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (mode)) == 0
+      && INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (int_mode) == 0
       && INTVAL (XEXP (op, 1)) > 0
       && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (int_op_mode)
       && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0),
 				     MEM_ADDR_SPACE (XEXP (op, 0)))
       && ! MEM_VOLATILE_P (XEXP (op, 0))
-      && (GET_MODE_SIZE (mode) >= UNITS_PER_WORD
+      && (GET_MODE_SIZE (int_mode) >= UNITS_PER_WORD
 	  || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN))
     {
-      int byte = subreg_lowpart_offset (mode, int_op_mode);
+      int byte = subreg_lowpart_offset (int_mode, int_op_mode);
       int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
-      return adjust_address_nv (XEXP (op, 0), mode,
+      return adjust_address_nv (XEXP (op, 0), int_mode,
 				(WORDS_BIG_ENDIAN
 				 ? byte - shifted_bytes
 				 : byte + shifted_bytes));
@@ -2975,19 +2976,21 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	 is (lt foo (const_int 0)), so we can perform the above
 	 simplification if STORE_FLAG_VALUE is 1.  */
 
-      if (STORE_FLAG_VALUE == 1
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && STORE_FLAG_VALUE == 1
 	  && trueop1 == const1_rtx
 	  && GET_CODE (op0) == LSHIFTRT
 	  && CONST_INT_P (XEXP (op0, 1))
-	  && INTVAL (XEXP (op0, 1)) == GET_MODE_PRECISION (mode) - 1)
-	return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx);
+	  && INTVAL (XEXP (op0, 1)) == GET_MODE_PRECISION (int_mode) - 1)
+	return gen_rtx_GE (int_mode, XEXP (op0, 0), const0_rtx);
 
       /* (xor (comparison foo bar) (const_int sign-bit))
 	 when STORE_FLAG_VALUE is the sign bit.  */
-      if (val_signbit_p (mode, STORE_FLAG_VALUE)
+      if (is_a <scalar_int_mode> (mode, &int_mode)
+	  && val_signbit_p (int_mode, STORE_FLAG_VALUE)
 	  && trueop1 == const_true_rtx
 	  && COMPARISON_P (op0)
-	  && (reversed = reversed_comparison (op0, mode)))
+	  && (reversed = reversed_comparison (op0, int_mode)))
 	return reversed;
 
       tem = simplify_byte_swapping_operation (code, mode, op0, op1);
@@ -3407,17 +3410,17 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
 	return op0;
       /* Optimize (lshiftrt (clz X) C) as (eq X 0).  */
       if (GET_CODE (op0) == CLZ
+	  && is_a <scalar_int_mode> (GET_MODE (XEXP (op0, 0)), &inner_mode)
 	  && CONST_INT_P (trueop1)
 	  && STORE_FLAG_VALUE == 1
 	  && INTVAL (trueop1) < (HOST_WIDE_INT)width)
 	{
-	  machine_mode imode = GET_MODE (XEXP (op0, 0));
 	  unsigned HOST_WIDE_INT zero_val = 0;
 
-	  if (CLZ_DEFINED_VALUE_AT_ZERO (imode, zero_val)
-	      && zero_val == GET_MODE_PRECISION (imode)
+	  if (CLZ_DEFINED_VALUE_AT_ZERO (inner_mode, zero_val)
+	      && zero_val == GET_MODE_PRECISION (inner_mode)
 	      && INTVAL (trueop1) == exact_log2 (zero_val))
-	    return simplify_gen_relational (EQ, mode, imode,
+	    return simplify_gen_relational (EQ, mode, inner_mode,
 					    XEXP (op0, 0), const0_rtx);
 	}
       goto canonicalize_shift;
@@ -5260,7 +5263,9 @@ simplify_const_relational_operation (enum rtx_code code,
     }
 
   /* Optimize integer comparisons with zero.  */
-  if (trueop1 == const0_rtx && !side_effects_p (trueop0))
+  if (is_a <scalar_int_mode> (mode, &int_mode)
+      && trueop1 == const0_rtx
+      && !side_effects_p (trueop0))
     {
       /* Some addresses are known to be nonzero.  We don't know
 	 their sign, but equality comparisons are known.  */
@@ -5279,7 +5284,7 @@ simplify_const_relational_operation (enum rtx_code code,
 	  rtx inner_const = avoid_constant_pool_reference (XEXP (op0, 1));
 	  if (CONST_INT_P (inner_const) && inner_const != const0_rtx)
 	    {
-	      int sign_bitnum = GET_MODE_PRECISION (mode) - 1;
+	      int sign_bitnum = GET_MODE_PRECISION (int_mode) - 1;
 	      int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum
 			      && (UINTVAL (inner_const)
 				  & (HOST_WIDE_INT_1U
@@ -5415,13 +5420,9 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode,
 			    machine_mode op0_mode, rtx op0, rtx op1,
 			    rtx op2)
 {
-  unsigned int width = GET_MODE_PRECISION (mode);
   bool any_change = false;
   rtx tem, trueop2;
-
-  /* VOIDmode means "infinite" precision.  */
-  if (width == 0)
-    width = HOST_BITS_PER_WIDE_INT;
+  scalar_int_mode int_mode, int_op0_mode;
 
   switch (code)
     {
@@ -5455,17 +5456,20 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode,
       if (CONST_INT_P (op0)
 	  && CONST_INT_P (op1)
 	  && CONST_INT_P (op2)
-	  && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width)
-	  && width <= (unsigned) HOST_BITS_PER_WIDE_INT)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && INTVAL (op1) + INTVAL (op2) <= GET_MODE_PRECISION (int_mode))
 	{
 	  /* Extracting a bit-field from a constant */
 	  unsigned HOST_WIDE_INT val = UINTVAL (op0);
 	  HOST_WIDE_INT op1val = INTVAL (op1);
 	  HOST_WIDE_INT op2val = INTVAL (op2);
-	  if (BITS_BIG_ENDIAN)
-	    val >>= GET_MODE_PRECISION (op0_mode) - op2val - op1val;
-	  else
+	  if (!BITS_BIG_ENDIAN)
 	    val >>= op2val;
+	  else if (is_a <scalar_int_mode> (op0_mode, &int_op0_mode))
+	    val >>= GET_MODE_PRECISION (int_op0_mode) - op2val - op1val;
+	  else
+	    /* Not enough information to calculate the bit position.  */
+	    break;
 
 	  if (HOST_BITS_PER_WIDE_INT != op1val)
 	    {
@@ -5478,7 +5482,7 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode,
 		val |= ~ ((HOST_WIDE_INT_1U << op1val) - 1);
 	    }
 
-	  return gen_int_mode (val, mode);
+	  return gen_int_mode (val, int_mode);
 	}
       break;
 
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 00b287a..3653586 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -4336,6 +4336,7 @@ force_expr_to_var_cost (tree expr, bool speed)
   tree op0, op1;
   comp_cost cost0, cost1, cost;
   machine_mode mode;
+  scalar_int_mode int_mode;
 
   if (!costs_initialized)
     {
@@ -4452,8 +4453,9 @@ force_expr_to_var_cost (tree expr, bool speed)
 	    mult = op0;
 
 	  if (mult != NULL_TREE
+	      && is_a <scalar_int_mode> (mode, &int_mode)
 	      && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1))
-	      && get_shiftadd_cost (expr, mode, cost0, cost1, mult,
+	      && get_shiftadd_cost (expr, int_mode, cost0, cost1, mult,
 				    speed, &sa_cost))
 	    return sa_cost;
 	}

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [29/67] Make some *_loc_descriptor helpers take scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (29 preceding siblings ...)
  2016-12-09 13:12 ` [30/67] Use scalar_int_mode for doubleword splits Richard Sandiford
@ 2016-12-09 13:12 ` Richard Sandiford
  2016-12-09 13:13 ` [31/67] Use scalar_int_mode for move2add Richard Sandiford
                   ` (38 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:12 UTC (permalink / raw)
  To: gcc-patches

The *_loc_descriptor routines for clz, popcount, bswap and rotate
all required SCALAR_INT_MODE_P.  This patch moves the checks into
the caller (mem_loc_descriptor) so that the types of the mode
parameters can be scalar_int_mode instead of machine_mode.

The MOD handling in mem_loc_descriptor is also specific to
scalar integer modes.  Adding an explicit check allows
typed_binop to take a scalar_int_mode too.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* dwarf2out.c (typed_binop): Change mode parameter to scalar_int_mode.
	(clz_loc_descriptor): Likewise.  Remove SCALAR_INT_MODE_P check.
	(popcount_loc_descriptor): Likewise.
	(bswap_loc_descriptor): Likewise.
	(rotate_loc_descriptor): Likewise.
	(mem_loc_descriptor): Add is_a <scalar_int_mode> checks before
	calling the functions above.

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 0b8b12d..ed5ec24 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14040,7 +14040,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
 
 static dw_loc_descr_ref
 typed_binop (enum dwarf_location_atom op, rtx rtl, dw_die_ref type_die,
-	     machine_mode mode, machine_mode mem_mode)
+	     scalar_int_mode mode, machine_mode mem_mode)
 {
   dw_loc_descr_ref cvt, op0, op1;
 
@@ -14096,7 +14096,7 @@ typed_binop (enum dwarf_location_atom op, rtx rtl, dw_die_ref type_die,
    L4: DW_OP_nop  */
 
 static dw_loc_descr_ref
-clz_loc_descriptor (rtx rtl, machine_mode mode,
+clz_loc_descriptor (rtx rtl, scalar_int_mode mode,
 		    machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
@@ -14107,8 +14107,7 @@ clz_loc_descriptor (rtx rtl, machine_mode mode,
   dw_loc_descr_ref l4jump, l4label;
   rtx msb;
 
-  if (!SCALAR_INT_MODE_P (mode)
-      || GET_MODE (XEXP (rtl, 0)) != mode)
+  if (GET_MODE (XEXP (rtl, 0)) != mode)
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -14208,15 +14207,14 @@ clz_loc_descriptor (rtx rtl, machine_mode mode,
    L2: DW_OP_drop  */
 
 static dw_loc_descr_ref
-popcount_loc_descriptor (rtx rtl, machine_mode mode,
+popcount_loc_descriptor (rtx rtl, scalar_int_mode mode,
 			 machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
   dw_loc_descr_ref l1jump, l1label;
   dw_loc_descr_ref l2jump, l2label;
 
-  if (!SCALAR_INT_MODE_P (mode)
-      || GET_MODE (XEXP (rtl, 0)) != mode)
+  if (GET_MODE (XEXP (rtl, 0)) != mode)
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -14269,17 +14267,16 @@ popcount_loc_descriptor (rtx rtl, machine_mode mode,
    L2: DW_OP_drop DW_OP_swap DW_OP_drop  */
 
 static dw_loc_descr_ref
-bswap_loc_descriptor (rtx rtl, machine_mode mode,
+bswap_loc_descriptor (rtx rtl, scalar_int_mode mode,
 		      machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
   dw_loc_descr_ref l1jump, l1label;
   dw_loc_descr_ref l2jump, l2label;
 
-  if (!SCALAR_INT_MODE_P (mode)
-      || BITS_PER_UNIT != 8
+  if (BITS_PER_UNIT != 8
       || (GET_MODE_BITSIZE (mode) != 32
-	  &&  GET_MODE_BITSIZE (mode) != 64))
+	  && GET_MODE_BITSIZE (mode) != 64))
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -14354,16 +14351,13 @@ bswap_loc_descriptor (rtx rtl, machine_mode mode,
    [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or  */
 
 static dw_loc_descr_ref
-rotate_loc_descriptor (rtx rtl, machine_mode mode,
+rotate_loc_descriptor (rtx rtl, scalar_int_mode mode,
 		       machine_mode mem_mode)
 {
   rtx rtlop1 = XEXP (rtl, 1);
   dw_loc_descr_ref op0, op1, ret, mask[2] = { NULL, NULL };
   int i;
 
-  if (!SCALAR_INT_MODE_P (mode))
-    return NULL;
-
   if (GET_MODE (rtlop1) != VOIDmode
       && GET_MODE_BITSIZE (GET_MODE (rtlop1)) < GET_MODE_BITSIZE (mode))
     rtlop1 = gen_rtx_ZERO_EXTEND (mode, rtlop1);
@@ -14969,12 +14963,13 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
       break;
 
     case MOD:
-      if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
-	  && (!dwarf_strict || dwarf_version >= 5))
+      if ((!dwarf_strict || dwarf_version >= 5)
+	  && is_a <scalar_int_mode> (mode, &int_mode)
+	  && GET_MODE_SIZE (int_mode) > DWARF2_ADDR_SIZE)
 	{
 	  mem_loc_result = typed_binop (DW_OP_mod, rtl,
 					base_type_for_mode (mode, 0),
-					mode, mem_mode);
+					int_mode, mem_mode);
 	  break;
 	}
 
@@ -15326,21 +15321,25 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
     case CLZ:
     case CTZ:
     case FFS:
-      mem_loc_result = clz_loc_descriptor (rtl, mode, mem_mode);
+      if (is_a <scalar_int_mode> (mode, &int_mode))
+	mem_loc_result = clz_loc_descriptor (rtl, int_mode, mem_mode);
       break;
 
     case POPCOUNT:
     case PARITY:
-      mem_loc_result = popcount_loc_descriptor (rtl, mode, mem_mode);
+      if (is_a <scalar_int_mode> (mode, &int_mode))
+	mem_loc_result = popcount_loc_descriptor (rtl, int_mode, mem_mode);
       break;
 
     case BSWAP:
-      mem_loc_result = bswap_loc_descriptor (rtl, mode, mem_mode);
+      if (is_a <scalar_int_mode> (mode, &int_mode))
+	mem_loc_result = bswap_loc_descriptor (rtl, int_mode, mem_mode);
       break;
 
     case ROTATE:
     case ROTATERT:
-      mem_loc_result = rotate_loc_descriptor (rtl, mode, mem_mode);
+      if (is_a <scalar_int_mode> (mode, &int_mode))
+	mem_loc_result = rotate_loc_descriptor (rtl, int_mode, mem_mode);
       break;
 
     case COMPARE:

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [30/67] Use scalar_int_mode for doubleword splits
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (28 preceding siblings ...)
  2016-12-09 13:11 ` [28/67] Use is_a <scalar_int_mode> for miscellaneous types of test Richard Sandiford
@ 2016-12-09 13:12 ` Richard Sandiford
  2016-12-09 13:12 ` [29/67] Make some *_loc_descriptor helpers take scalar_int_mode Richard Sandiford
                   ` (39 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:12 UTC (permalink / raw)
  To: gcc-patches

Add is_a <scalar_int_mode> tests to a couple of places that
were splitting doubleword integer operations into word_mode
operations.  Also use scalar_int_mode in the expand_expr_real_2
handling of doubleword shifts.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* expr.c (expand_expr_real_2): Use scalar_int_mode for the
	double-word mode.
	* lower-subreg.c (resolve_shift_zext): Use is_a <scalar_int_mode>.
	* optabs.c (expand_unop): Likewise.

diff --git a/gcc/expr.c b/gcc/expr.c
index 843c402..0d88e41 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8197,6 +8197,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
   tree type;
   int unsignedp;
   machine_mode mode;
+  scalar_int_mode int_mode;
   enum tree_code code = ops->code;
   optab this_optab;
   rtx subtarget, original_target;
@@ -9102,8 +9103,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	    && target
 	    && REG_P (target)
 	    && ! unsignedp
-	    && mode == GET_MODE_WIDER_MODE (word_mode).else_void ()
-	    && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode)
+	    && GET_MODE_2XWIDER_MODE (word_mode).exists (&int_mode)
+	    && mode == int_mode
 	    && TREE_CONSTANT (treeop1)
 	    && TREE_CODE (treeop0) == SSA_NAME)
 	  {
@@ -9114,18 +9115,18 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		machine_mode rmode = TYPE_MODE
 		  (TREE_TYPE (gimple_assign_rhs1 (def)));
 
-		if (GET_MODE_SIZE (rmode) < GET_MODE_SIZE (mode)
+		if (GET_MODE_SIZE (rmode) < GET_MODE_SIZE (int_mode)
 		    && TREE_INT_CST_LOW (treeop1) < GET_MODE_BITSIZE (word_mode)
 		    && ((TREE_INT_CST_LOW (treeop1) + GET_MODE_BITSIZE (rmode))
 			>= GET_MODE_BITSIZE (word_mode)))
 		  {
 		    rtx_insn *seq, *seq_old;
 		    unsigned int high_off = subreg_highpart_offset (word_mode,
-								    mode);
-		    rtx low = lowpart_subreg (word_mode, op0, mode);
-		    rtx dest_low = lowpart_subreg (word_mode, target, mode);
+								    int_mode);
+		    rtx low = lowpart_subreg (word_mode, op0, int_mode);
+		    rtx dest_low = lowpart_subreg (word_mode, target, int_mode);
 		    rtx dest_high = simplify_gen_subreg (word_mode, target,
-							 mode, high_off);
+							 int_mode, high_off);
 		    HOST_WIDE_INT ramount = (BITS_PER_WORD
 					     - TREE_INT_CST_LOW (treeop1));
 		    tree rshift = build_int_cst (TREE_TYPE (treeop1), ramount);
@@ -9147,12 +9148,13 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		    end_sequence ();
 		    temp = target ;
 
-		    if (have_insn_for (ASHIFT, mode))
+		    if (have_insn_for (ASHIFT, int_mode))
 		      {
 			bool speed_p = optimize_insn_for_speed_p ();
 			start_sequence ();
-			rtx ret_old = expand_variable_shift (code, mode, op0,
-							     treeop1, target,
+			rtx ret_old = expand_variable_shift (code, int_mode,
+							     op0, treeop1,
+							     target,
 							     unsignedp);
 
 			seq_old = get_insns ();
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index 520eed1..f82bb87 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -1225,6 +1225,7 @@ resolve_shift_zext (rtx_insn *insn)
   rtx_insn *insns;
   rtx src_reg, dest_reg, dest_upper, upper_src = NULL_RTX;
   int src_reg_num, dest_reg_num, offset1, offset2, src_offset;
+  scalar_int_mode inner_mode;
 
   set = single_set (insn);
   if (!set)
@@ -1238,6 +1239,8 @@ resolve_shift_zext (rtx_insn *insn)
     return NULL;
 
   op_operand = XEXP (op, 0);
+  if (!is_a <scalar_int_mode> (GET_MODE (op_operand), &inner_mode))
+    return NULL;
 
   /* We can tear this operation apart only if the regs were already
      torn apart.  */
@@ -1250,8 +1253,7 @@ resolve_shift_zext (rtx_insn *insn)
   src_reg_num = (GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT)
 		? 1 : 0;
 
-  if (WORDS_BIG_ENDIAN
-      && GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD)
+  if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
     src_reg_num = 1 - src_reg_num;
 
   if (GET_CODE (op) == ZERO_EXTEND)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index acf89bd..77ca419 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2735,22 +2735,24 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
     }
 
   if (unoptab == popcount_optab
-      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
       && optab_handler (unoptab, word_mode) != CODE_FOR_nothing
       && optimize_insn_for_speed_p ())
     {
-      temp = expand_doubleword_popcount (mode, op0, target);
+      temp = expand_doubleword_popcount (int_mode, op0, target);
       if (temp)
 	return temp;
     }
 
   if (unoptab == parity_optab
-      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
       && (optab_handler (unoptab, word_mode) != CODE_FOR_nothing
 	  || optab_handler (popcount_optab, word_mode) != CODE_FOR_nothing)
       && optimize_insn_for_speed_p ())
     {
-      temp = expand_doubleword_parity (mode, op0, target);
+      temp = expand_doubleword_parity (int_mode, op0, target);
       if (temp)
 	return temp;
     }

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [31/67] Use scalar_int_mode for move2add
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (30 preceding siblings ...)
  2016-12-09 13:12 ` [29/67] Make some *_loc_descriptor helpers take scalar_int_mode Richard Sandiford
@ 2016-12-09 13:13 ` Richard Sandiford
  2016-12-09 13:14 ` [32/67] Check is_a <scalar_int_mode> before calling valid_pointer_mode Richard Sandiford
                   ` (37 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:13 UTC (permalink / raw)
  To: gcc-patches

The postreload move2add optimisations are specific to scalar
integers.  This patch adds an explicit check to the main guarding
"if" and propagates the information through subroutines.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* postreload.c (move2add_valid_value_p): Change type of mode
	parameter to scalar_int_mode.
	(move2add_use_add2_insn): Add a mode parameter and use it instead
	of GET_MODE (reg).
	(move2add_use_add3_insn): Likewise.
	(reload_cse_move2add): Update accordingly.

diff --git a/gcc/postreload.c b/gcc/postreload.c
index ff7e7c3..37669cd 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1687,7 +1687,7 @@ move2add_record_sym_value (rtx reg, rtx sym, rtx off)
 /* Check if REGNO contains a valid value in MODE.  */
 
 static bool
-move2add_valid_value_p (int regno, machine_mode mode)
+move2add_valid_value_p (int regno, scalar_int_mode mode)
 {
   if (reg_set_luid[regno] <= move2add_last_label_luid)
     return false;
@@ -1718,21 +1718,21 @@ move2add_valid_value_p (int regno, machine_mode mode)
   return true;
 }
 
-/* This function is called with INSN that sets REG to (SYM + OFF),
-   while REG is known to already have value (SYM + offset).
+/* This function is called with INSN that sets REG (of mode MODE)
+   to (SYM + OFF), while REG is known to already have value (SYM + offset).
    This function tries to change INSN into an add instruction
    (set (REG) (plus (REG) (OFF - offset))) using the known value.
    It also updates the information about REG's known value.
    Return true if we made a change.  */
 
 static bool
-move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
+move2add_use_add2_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
+			rtx_insn *insn)
 {
   rtx pat = PATTERN (insn);
   rtx src = SET_SRC (pat);
   int regno = REGNO (reg);
-  rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[regno],
-			      GET_MODE (reg));
+  rtx new_src = gen_int_mode (UINTVAL (off) - reg_offset[regno], mode);
   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
   bool changed = false;
 
@@ -1754,7 +1754,7 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
   else
     {
       struct full_rtx_costs oldcst, newcst;
-      rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
+      rtx tem = gen_rtx_PLUS (mode, reg, new_src);
 
       get_full_set_rtx_cost (pat, &oldcst);
       SET_SRC (pat) = tem;
@@ -1764,10 +1764,10 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
       if (costs_lt_p (&newcst, &oldcst, speed)
 	  && have_add2_insn (reg, new_src))
 	changed = validate_change (insn, &SET_SRC (pat), tem, 0);	
-      else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
+      else if (sym == NULL_RTX && mode != BImode)
 	{
-	  machine_mode narrow_mode;
-	  FOR_EACH_MODE_UNTIL (narrow_mode, GET_MODE (reg))
+	  scalar_int_mode narrow_mode;
+	  FOR_EACH_MODE_UNTIL (narrow_mode, mode)
 	    {
 	      if (have_insn_for (STRICT_LOW_PART, narrow_mode)
 		  && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
@@ -1797,9 +1797,9 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
 }
 
 
-/* This function is called with INSN that sets REG to (SYM + OFF),
-   but REG doesn't have known value (SYM + offset).  This function
-   tries to find another register which is known to already have
+/* This function is called with INSN that sets REG (of mode MODE) to
+   (SYM + OFF), but REG doesn't have known value (SYM + offset).  This
+   function tries to find another register which is known to already have
    value (SYM + offset) and change INSN into an add instruction
    (set (REG) (plus (the found register) (OFF - offset))) if such
    a register is found.  It also updates the information about
@@ -1807,7 +1807,8 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
    Return true iff we made a change.  */
 
 static bool
-move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
+move2add_use_add3_insn (scalar_int_mode mode, rtx reg, rtx sym, rtx off,
+			rtx_insn *insn)
 {
   rtx pat = PATTERN (insn);
   rtx src = SET_SRC (pat);
@@ -1826,7 +1827,7 @@ move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
   SET_SRC (pat) = plus_expr;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (move2add_valid_value_p (i, GET_MODE (reg))
+    if (move2add_valid_value_p (i, mode)
 	&& reg_base_reg[i] < 0
 	&& reg_symbol_ref[i] != NULL_RTX
 	&& rtx_equal_p (sym, reg_symbol_ref[i]))
@@ -1916,8 +1917,10 @@ reload_cse_move2add (rtx_insn *first)
       pat = PATTERN (insn);
       /* For simplicity, we only perform this optimization on
 	 straightforward SETs.  */
+      scalar_int_mode mode;
       if (GET_CODE (pat) == SET
-	  && REG_P (SET_DEST (pat)))
+	  && REG_P (SET_DEST (pat))
+	  && is_a <scalar_int_mode> (GET_MODE (SET_DEST (pat)), &mode))
 	{
 	  rtx reg = SET_DEST (pat);
 	  int regno = REGNO (reg);
@@ -1925,7 +1928,7 @@ reload_cse_move2add (rtx_insn *first)
 
 	  /* Check if we have valid information on the contents of this
 	     register in the mode of REG.  */
-	  if (move2add_valid_value_p (regno, GET_MODE (reg))
+	  if (move2add_valid_value_p (regno, mode)
               && dbg_cnt (cse2_move2add))
 	    {
 	      /* Try to transform (set (REGX) (CONST_INT A))
@@ -1945,7 +1948,8 @@ reload_cse_move2add (rtx_insn *first)
 		  && reg_base_reg[regno] < 0
 		  && reg_symbol_ref[regno] == NULL_RTX)
 		{
-		  changed |= move2add_use_add2_insn (reg, NULL_RTX, src, insn);
+		  changed |= move2add_use_add2_insn (mode, reg, NULL_RTX,
+						     src, insn);
 		  continue;
 		}
 
@@ -1962,7 +1966,7 @@ reload_cse_move2add (rtx_insn *first)
 	      else if (REG_P (src)
 		       && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
 		       && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
-		       && move2add_valid_value_p (REGNO (src), GET_MODE (reg)))
+		       && move2add_valid_value_p (REGNO (src), mode))
 		{
 		  rtx_insn *next = next_nonnote_nondebug_insn (insn);
 		  rtx set = NULL_RTX;
@@ -1982,7 +1986,7 @@ reload_cse_move2add (rtx_insn *first)
 			gen_int_mode (added_offset
 				      + base_offset
 				      - regno_offset,
-				      GET_MODE (reg));
+				      mode);
 		      bool success = false;
 		      bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
 
@@ -1994,11 +1998,11 @@ reload_cse_move2add (rtx_insn *first)
 			{
 			  rtx old_src = SET_SRC (set);
 			  struct full_rtx_costs oldcst, newcst;
-			  rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
+			  rtx tem = gen_rtx_PLUS (mode, reg, new_src);
 
 			  get_full_set_rtx_cost (set, &oldcst);
 			  SET_SRC (set) = tem;
-			  get_full_set_src_cost (tem, GET_MODE (reg), &newcst);
+			  get_full_set_src_cost (tem, mode, &newcst);
 			  SET_SRC (set) = old_src;
 			  costs_add_n_insns (&oldcst, 1);
 
@@ -2018,7 +2022,7 @@ reload_cse_move2add (rtx_insn *first)
 		      move2add_record_mode (reg);
 		      reg_offset[regno]
 			= trunc_int_for_mode (added_offset + base_offset,
-					      GET_MODE (reg));
+					      mode);
 		      continue;
 		    }
 		}
@@ -2054,16 +2058,16 @@ reload_cse_move2add (rtx_insn *first)
 
 	      /* If the reg already contains the value which is sum of
 		 sym and some constant value, we can use an add2 insn.  */
-	      if (move2add_valid_value_p (regno, GET_MODE (reg))
+	      if (move2add_valid_value_p (regno, mode)
 		  && reg_base_reg[regno] < 0
 		  && reg_symbol_ref[regno] != NULL_RTX
 		  && rtx_equal_p (sym, reg_symbol_ref[regno]))
-		changed |= move2add_use_add2_insn (reg, sym, off, insn);
+		changed |= move2add_use_add2_insn (mode, reg, sym, off, insn);
 
 	      /* Otherwise, we have to find a register whose value is sum
 		 of sym and some constant value.  */
 	      else
-		changed |= move2add_use_add3_insn (reg, sym, off, insn);
+		changed |= move2add_use_add3_insn (mode, reg, sym, off, insn);
 
 	      continue;
 	    }

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [32/67] Check is_a <scalar_int_mode> before calling valid_pointer_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (31 preceding siblings ...)
  2016-12-09 13:13 ` [31/67] Use scalar_int_mode for move2add Richard Sandiford
@ 2016-12-09 13:14 ` Richard Sandiford
  2016-12-09 13:14 ` [33/67] Add a NARROWEST_INT_MODE macro Richard Sandiford
                   ` (36 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:14 UTC (permalink / raw)
  To: gcc-patches

A future patch will make valid_pointer_mode take a scalar_int_mode
instead of a machine_mode.  is_a <...> rather than as_a <...> is
needed here because we're checking a mode supplied by the user.

gcc/c-family/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* c-attribs.c (handle_mode_attribute): Check for a scalar_int_mode
	before calling targetm.addr_space.valid_pointer_mode.

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 4c4017a..14b43fe 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1356,10 +1356,12 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
       if (POINTER_TYPE_P (type))
 	{
+	  scalar_int_mode addr_mode;
 	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
 	  tree (*fn)(tree, machine_mode, bool);
 
-	  if (!targetm.addr_space.valid_pointer_mode (mode, as))
+	  if (!is_a <scalar_int_mode> (mode, &addr_mode)
+	      || !targetm.addr_space.valid_pointer_mode (addr_mode, as))
 	    {
 	      error ("invalid pointer mode %qs", p);
 	      return NULL_TREE;
@@ -1369,7 +1371,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 	    fn = build_pointer_type_for_mode;
 	  else
 	    fn = build_reference_type_for_mode;
-	  typefm = fn (TREE_TYPE (type), mode, false);
+	  typefm = fn (TREE_TYPE (type), addr_mode, false);
 	}
       else
 	{

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [33/67] Add a NARROWEST_INT_MODE macro
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (32 preceding siblings ...)
  2016-12-09 13:14 ` [32/67] Check is_a <scalar_int_mode> before calling valid_pointer_mode Richard Sandiford
@ 2016-12-09 13:14 ` Richard Sandiford
  2016-12-09 13:15 ` [34/67] Add a SCALAR_INT_TYPE_MODE macro Richard Sandiford
                   ` (35 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:14 UTC (permalink / raw)
  To: gcc-patches

Replace uses of GET_CLASS_NARROWEST_MODE (MODE_INT) with a new
NARROWEST_INT_MODE macro, which has type scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (NARROWEST_INT_MODE): New macro.
	* expr.c (alignment_for_piecewise_move): Use it instead of
	GET_CLASS_NARROWEST_MODE (MODE_INT).
	(push_block): Likewise.
	* stor-layout.c (bit_field_mode_iterator::bit_field_mode_iterator):
	Likewise.
	* tree-vrp.c (simplify_float_conversion_using_ranges): Likewise.

gcc/ada/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* gcc-interface/decl.c (validate_size): Use NARROWEST_INT_MODE
	instead of GET_CLASS_NARROWEST_MODE (MODE_INT).

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index e300892..eb21cd6 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -8526,7 +8526,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
      by the smallest integral mode that's valid for pointers.  */
   if (TREE_CODE (gnu_type) == POINTER_TYPE || TYPE_IS_FAT_POINTER_P (gnu_type))
     {
-      machine_mode p_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+      scalar_int_mode p_mode = NARROWEST_INT_MODE;
       while (!targetm.valid_pointer_mode (p_mode))
 	p_mode = *GET_MODE_WIDER_MODE (p_mode);
       type_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
diff --git a/gcc/expr.c b/gcc/expr.c
index 0d88e41..ea66027 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -705,7 +705,7 @@ alignment_for_piecewise_move (unsigned int max_pieces, unsigned int align)
     {
       machine_mode tmode, xmode;
 
-      xmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+      xmode = NARROWEST_INT_MODE;
       FOR_EACH_MODE_IN_CLASS (tmode, MODE_INT)
 	{
 	  if (GET_MODE_SIZE (tmode) > max_pieces
@@ -3903,7 +3903,7 @@ push_block (rtx size, int extra, int below)
 			     negate_rtx (Pmode, size));
     }
 
-  return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
+  return memory_address (NARROWEST_INT_MODE, temp);
 }
 
 /* A utility routine that returns the base of an auto-inc memory, or NULL.  */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index fdbf174..75184b5 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -656,6 +656,11 @@ extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
 #define GET_CLASS_NARROWEST_MODE(CLASS) \
   (machine_mode ((machine_mode_enum) class_narrowest_mode[CLASS]))
 
+/* The narrowest full integer mode available on the target.  */
+
+#define NARROWEST_INT_MODE \
+  (scalar_int_mode::from_int (class_narrowest_mode[MODE_INT]))
+
 /* Return the narrowest mode in T's class.  */
 
 template<typename T>
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 5cf4433..a1b6c94 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2687,7 +2687,7 @@ bit_field_mode_iterator
 			   HOST_WIDE_INT bitregion_start,
 			   HOST_WIDE_INT bitregion_end,
 			   unsigned int align, bool volatilep)
-: m_mode (GET_CLASS_NARROWEST_MODE (MODE_INT)), m_bitsize (bitsize),
+: m_mode (NARROWEST_INT_MODE), m_bitsize (bitsize),
   m_bitpos (bitpos), m_bitregion_start (bitregion_start),
   m_bitregion_end (bitregion_end), m_align (align),
   m_volatilep (volatilep), m_count (0)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 88ddbf8..9a5f69d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9995,7 +9995,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
      integer mode available.  */
   else
     {
-      mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+      mode = NARROWEST_INT_MODE;
       for (;;)
 	{
 	  /* If we cannot do a signed conversion to float from mode

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [34/67] Add a SCALAR_INT_TYPE_MODE macro
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (33 preceding siblings ...)
  2016-12-09 13:14 ` [33/67] Add a NARROWEST_INT_MODE macro Richard Sandiford
@ 2016-12-09 13:15 ` Richard Sandiford
  2016-12-09 13:16 ` [35/67] Add uses of as_a <scalar_int_mode> Richard Sandiford
                   ` (34 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:15 UTC (permalink / raw)
  To: gcc-patches

This patch adds a SCALAR_INT_TYPE_MODE macro that asserts
that the type has a scalar integer mode and returns it as
a scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* tree.h (SCALAR_INT_TYPE_MODE): New macro.
	* builtins.c (expand_builtin_signbit): Use it.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* dojump.c (do_jump): Likewise.
	(do_compare_and_jump): Likewise.
	* dwarf2cfi.c (expand_builtin_init_dwarf_reg_sizes): Likewise.
	* expmed.c (make_tree): Likewise.
	* expr.c (expand_expr_real_2): Likewise.
	(expand_expr_real_1): Likewise.
	(try_casesi): Likewise.
	* fold-const-call.c (fold_const_call_ss): Likewise.
	* fold-const.c (unextend): Likewise.
	(extract_muldiv_1): Likewise.
	(fold_single_bit_test): Likewise.
	(native_encode_int): Likewise.
	(native_encode_string): Likewise.
	(native_interpret_int): Likewise.
	* gimple-fold.c (gimple_fold_builtin_memset): Likewise.
	* internal-fn.c (expand_addsub_overflow): Likewise.
	(expand_neg_overflow): Likewise.
	(expand_mul_overflow): Likewise.
	(expand_arith_overflow): Likewise.
	* match.pd: Likewise.
	* stor-layout.c (layout_type): Likewise.
	* tree-cfg.c (verify_gimple_assign_ternary): Likewise.
	* tree-ssa-math-opts.c (convert_mult_to_widen): Likewise.
	* tree-ssanames.c (get_range_info): Likewise.
	* tree-switch-conversion.c (array_value_type) Likewise.:
	* tree-vect-patterns.c (vect_recog_rotate_pattern): Likewise.
	(vect_recog_divmod_pattern): Likewise.
	(vect_recog_mixed_size_cond_pattern): Likewise.
	* tree-vrp.c (extract_range_basic): Likewise.
	(simplify_float_conversion_using_ranges): Likewise.
	* tree.c (int_fits_type_p): Likewise.
	* ubsan.c (instrument_bool_enum_load): Likewise.
	* varasm.c (mergeable_string_section): Likewise.
	(narrowing_initializer_constant_valid_p): Likewise.
	(output_constant): Likewise.

gcc/cp/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* cvt.c (cp_convert_to_pointer): Use SCALAR_INT_TYPE_MODE.

gcc/fortran/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* target-memory.c (size_integer): Use SCALAR_INT_TYPE_MODE.
	(size_logical): Likewise.

gcc/objc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* objc-encoding.c (encode_type): Use SCALAR_INT_TYPE_MODE.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 00a0a73..cf22e96 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5223,7 +5223,7 @@ expand_builtin_signbit (tree exp, rtx target)
 
   arg = CALL_EXPR_ARG (exp, 0);
   fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg));
-  rmode = TYPE_MODE (TREE_TYPE (exp));
+  rmode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
   fmt = REAL_MODE_FORMAT (fmode);
 
   arg = builtin_save_expr (arg);
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1427a97..dbb7bca 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4128,7 +4128,7 @@ expand_debug_expr (tree exp)
   machine_mode inner_mode = VOIDmode;
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
   addr_space_t as;
-  scalar_int_mode op0_mode, op1_mode;
+  scalar_int_mode op0_mode, op1_mode, addr_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -4903,7 +4903,8 @@ expand_debug_expr (tree exp)
 	}
 
       as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
-      op0 = convert_debug_memory_address (mode, XEXP (op0, 0), as);
+      addr_mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (exp));
+      op0 = convert_debug_memory_address (addr_mode, XEXP (op0, 0), as);
 
       return op0;
 
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 400566f..971a1b0 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -234,8 +234,8 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
       /* Modes may be different but sizes should be the same.  There
 	 is supposed to be some integral type that is the same width
 	 as a pointer.  */
-      gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
-		  == GET_MODE_SIZE (TYPE_MODE (type)));
+      gcc_assert (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (expr)))
+		  == GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type)));
 
       return convert_to_pointer_maybe_fold (type, expr, dofold);
     }
diff --git a/gcc/dojump.c b/gcc/dojump.c
index dbc76dc..749742b 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -575,7 +575,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
 	      if (TREE_CODE (shift) == INTEGER_CST
 		  && compare_tree_int (shift, 0) >= 0
 		  && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
-		  && prefer_and_bit_test (TYPE_MODE (argtype),
+		  && prefer_and_bit_test (SCALAR_INT_TYPE_MODE (argtype),
 					  TREE_INT_CST_LOW (shift)))
 		{
 		  unsigned HOST_WIDE_INT mask
@@ -1185,17 +1185,14 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum rtx_code signed_code,
     return;
 
   type = TREE_TYPE (treeop0);
-  mode = TYPE_MODE (type);
   if (TREE_CODE (treeop0) == INTEGER_CST
       && (TREE_CODE (treeop1) != INTEGER_CST
-          || (GET_MODE_BITSIZE (mode)
-              > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (treeop1))))))
-    {
-      /* op0 might have been replaced by promoted constant, in which
-         case the type of second argument should be used.  */
-      type = TREE_TYPE (treeop1);
-      mode = TYPE_MODE (type);
-    }
+	  || (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type))
+	      > GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (treeop1))))))
+    /* op0 might have been replaced by promoted constant, in which
+       case the type of second argument should be used.  */
+    type = TREE_TYPE (treeop1);
+  mode = TYPE_MODE (type);
   unsignedp = TYPE_UNSIGNED (type);
   code = unsignedp ? unsigned_code : signed_code;
 
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index b93faa8..d7b0e5c 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -301,7 +301,7 @@ void
 expand_builtin_init_dwarf_reg_sizes (tree address)
 {
   unsigned int i;
-  machine_mode mode = TYPE_MODE (char_type_node);
+  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (char_type_node);
   rtx addr = expand_normal (address);
   rtx mem = gen_rtx_MEM (BLKmode, addr);
 
diff --git a/gcc/expmed.c b/gcc/expmed.c
index d3eb5d6..f056e96 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -5185,7 +5185,7 @@ make_tree (tree type, rtx x)
 	 address mode to pointer mode.  */
       if (POINTER_TYPE_P (type))
 	x = convert_memory_address_addr_space
-	      (TYPE_MODE (type), x, TYPE_ADDR_SPACE (TREE_TYPE (type)));
+	  (SCALAR_INT_TYPE_MODE (type), x, TYPE_ADDR_SPACE (TREE_TYPE (type)));
 
       /* Note that we do *not* use SET_DECL_RTL here, because we do not
 	 want set_decl_rtl to go adjusting REG_ATTRS for this temporary.  */
diff --git a/gcc/expr.c b/gcc/expr.c
index ea66027..fb7709a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9018,11 +9018,12 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	 instead.  */
       if (reduce_bit_field && TYPE_UNSIGNED (type))
 	{
+	  int_mode = SCALAR_INT_TYPE_MODE (type);
 	  wide_int mask = wi::mask (TYPE_PRECISION (type),
-				    false, GET_MODE_PRECISION (mode));
+				    false, GET_MODE_PRECISION (int_mode));
 
-	  temp = expand_binop (mode, xor_optab, op0,
-			       immed_wide_int_const (mask, mode),
+	  temp = expand_binop (int_mode, xor_optab, op0,
+			       immed_wide_int_const (mask, int_mode),
 			       target, 1, OPTAB_LIB_WIDEN);
 	}
       else
@@ -9112,7 +9113,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	    if (is_gimple_assign (def)
 		&& gimple_assign_rhs_code (def) == NOP_EXPR)
 	      {
-		machine_mode rmode = TYPE_MODE
+		scalar_int_mode rmode = SCALAR_INT_TYPE_MODE
 		  (TREE_TYPE (gimple_assign_rhs1 (def)));
 
 		if (GET_MODE_SIZE (rmode) < GET_MODE_SIZE (int_mode)
@@ -9874,15 +9875,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
       return decl_rtl;
 
     case INTEGER_CST:
-      /* Given that TYPE_PRECISION (type) is not always equal to
-         GET_MODE_PRECISION (TYPE_MODE (type)), we need to extend from
-         the former to the latter according to the signedness of the
-         type. */
-      temp = immed_wide_int_const (wi::to_wide
-				   (exp,
-				    GET_MODE_PRECISION (TYPE_MODE (type))),
-				   TYPE_MODE (type));
-      return temp;
+      {
+	/* Given that TYPE_PRECISION (type) is not always equal to
+	   GET_MODE_PRECISION (TYPE_MODE (type)), we need to extend from
+	   the former to the latter according to the signedness of the
+	   type.  */
+	scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
+	temp = immed_wide_int_const
+	  (wi::to_wide (exp, GET_MODE_PRECISION (mode)), mode);
+	return temp;
+      }
 
     case VECTOR_CST:
       {
@@ -10341,7 +10343,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 		if (DECL_BIT_FIELD (field))
 		  {
 		    HOST_WIDE_INT bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
-		    machine_mode imode = TYPE_MODE (TREE_TYPE (field));
+		    scalar_int_mode imode
+		      = SCALAR_INT_TYPE_MODE (TREE_TYPE (field));
 
 		    if (TYPE_UNSIGNED (TREE_TYPE (field)))
 		      {
@@ -11470,10 +11473,10 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
   if (! targetm.have_casesi ())
     return 0;
 
-  /* Convert the index to SImode.  */
-  if (GET_MODE_BITSIZE (TYPE_MODE (index_type)) > GET_MODE_BITSIZE (index_mode))
+  /* The index must be some form of integer.  Convert it to SImode.  */
+  scalar_int_mode omode = SCALAR_INT_TYPE_MODE (index_type);
+  if (GET_MODE_BITSIZE (omode) > GET_MODE_BITSIZE (index_mode))
     {
-      machine_mode omode = TYPE_MODE (index_type);
       rtx rangertx = expand_normal (range);
 
       /* We must handle the endpoints in the original mode.  */
@@ -11490,7 +11493,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
     }
   else
     {
-      if (TYPE_MODE (index_type) != index_mode)
+      if (omode != index_mode)
 	{
 	  index_type = lang_hooks.types.type_for_mode (index_mode, 0);
 	  index_expr = fold_convert (index_type, index_expr);
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index f978da3..62eb859 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -844,7 +844,8 @@ fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
 	int tmp;
 	if (wi::ne_p (arg, 0))
 	  tmp = wi::clz (arg);
-	else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
+	else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
+					     tmp))
 	  tmp = TYPE_PRECISION (arg_type);
 	*result = wi::shwi (tmp, precision);
 	return true;
@@ -855,7 +856,8 @@ fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,
 	int tmp;
 	if (wi::ne_p (arg, 0))
 	  tmp = wi::ctz (arg);
-	else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
+	else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type),
+					     tmp))
 	  tmp = TYPE_PRECISION (arg_type);
 	*result = wi::shwi (tmp, precision);
 	return true;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c4a2ae3..088751f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5317,7 +5317,7 @@ static tree
 unextend (tree c, int p, int unsignedp, tree mask)
 {
   tree type = TREE_TYPE (c);
-  int modesize = GET_MODE_BITSIZE (TYPE_MODE (type));
+  int modesize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
   tree temp;
 
   if (p == modesize || unsignedp)
@@ -5907,8 +5907,9 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
 {
   tree type = TREE_TYPE (t);
   enum tree_code tcode = TREE_CODE (t);
-  tree ctype = (wide_type != 0 && (GET_MODE_SIZE (TYPE_MODE (wide_type))
-				   > GET_MODE_SIZE (TYPE_MODE (type)))
+  tree ctype = (wide_type != 0
+		&& (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (wide_type))
+		    > GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type)))
 		? wide_type : type);
   tree t1, t2;
   int same_p = tcode == code;
@@ -6605,7 +6606,7 @@ fold_single_bit_test (location_t loc, enum tree_code code,
       tree inner = TREE_OPERAND (arg0, 0);
       tree type = TREE_TYPE (arg0);
       int bitnum = tree_log2 (TREE_OPERAND (arg0, 1));
-      machine_mode operand_mode = TYPE_MODE (type);
+      scalar_int_mode operand_mode = SCALAR_INT_TYPE_MODE (type);
       int ops_unsigned;
       tree signed_type, unsigned_type, intermediate_type;
       tree tem, one;
@@ -6893,7 +6894,7 @@ static int
 native_encode_int (const_tree expr, unsigned char *ptr, int len, int off)
 {
   tree type = TREE_TYPE (expr);
-  int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+  int total_bytes = GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type));
   int byte, offset, word, words;
   unsigned char value;
 
@@ -7103,7 +7104,8 @@ native_encode_string (const_tree expr, unsigned char *ptr, int len, int off)
 
   if (TREE_CODE (type) != ARRAY_TYPE
       || TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
-      || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))) != BITS_PER_UNIT
+      || (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (type)))
+	  != BITS_PER_UNIT)
       || !tree_fits_shwi_p (TYPE_SIZE_UNIT (type)))
     return 0;
   total_bytes = tree_to_shwi (TYPE_SIZE_UNIT (type));
@@ -7175,7 +7177,7 @@ native_encode_expr (const_tree expr, unsigned char *ptr, int len, int off)
 static tree
 native_interpret_int (tree type, const unsigned char *ptr, int len)
 {
-  int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+  int total_bytes = GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type));
 
   if (total_bytes > len
       || total_bytes * BITS_PER_UNIT > HOST_BITS_PER_DOUBLE_INT)
diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c
index b498f19..7f24dbb 100644
--- a/gcc/fortran/target-memory.c
+++ b/gcc/fortran/target-memory.c
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 static size_t
 size_integer (int kind)
 {
-  return GET_MODE_SIZE (TYPE_MODE (gfc_get_int_type (kind)));;
+  return GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (gfc_get_int_type (kind)));
 }
 
 
@@ -60,7 +60,7 @@ size_complex (int kind)
 static size_t
 size_logical (int kind)
 {
-  return GET_MODE_SIZE (TYPE_MODE (gfc_get_logical_type (kind)));;
+  return GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (gfc_get_logical_type (kind)));
 }
 
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index c6b5411..558f6cb 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1118,7 +1118,7 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
     return NULL_TREE;
 
   length = tree_to_uhwi (len);
-  if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
+  if (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (etype)) != length
       || get_pointer_alignment (dest) / BITS_PER_UNIT < length)
     return NULL_TREE;
 
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 49075c2..3b06dc2 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -657,7 +657,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
   do_pending_stack_adjust ();
   rtx op0 = expand_normal (arg0);
   rtx op1 = expand_normal (arg1);
-  machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
+  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
   int prec = GET_MODE_PRECISION (mode);
   rtx sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
   bool do_xor = false;
@@ -1107,7 +1107,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan,
   do_pending_stack_adjust ();
   op1 = expand_normal (arg1);
 
-  machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
+  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg1));
   if (lhs)
     {
       target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
@@ -1201,7 +1201,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
   op0 = expand_normal (arg0);
   op1 = expand_normal (arg1);
 
-  machine_mode mode = TYPE_MODE (TREE_TYPE (arg0));
+  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
   bool uns = unsr_p;
   if (lhs)
     {
@@ -2118,7 +2118,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
 	  /* The infinity precision result will always fit into result.  */
 	  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
 	  write_complex_part (target, const0_rtx, true);
-	  machine_mode mode = TYPE_MODE (type);
+	  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
 	  struct separate_ops ops;
 	  ops.code = code;
 	  ops.type = type;
diff --git a/gcc/match.pd b/gcc/match.pd
index feaa4a1..a4d5f4e 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2936,7 +2936,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	     associated with the mode of @1, so the sign bit is
 	     specified by this mode.  Check that @1 is the signed
 	     max associated with this sign bit.  */
-	  && prec == GET_MODE_PRECISION (TYPE_MODE (arg1_type))
+	  && prec == GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (arg1_type))
 	  /* signed_type does not work on pointer types.  */
 	  && INTEGRAL_TYPE_P (arg1_type))
       /* The following case also applies to X < signed_max+1
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index 3b72dd2..a22970b 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -626,7 +626,7 @@ encode_type (tree type, int curtype, int format)
     case INTEGER_TYPE:
       {
 	char c;
-	switch (GET_MODE_BITSIZE (TYPE_MODE (type)))
+	switch (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type)))
 	  {
 	  case 8:  c = TYPE_UNSIGNED (type) ? 'C' : 'c'; break;
 	  case 16: c = TYPE_UNSIGNED (type) ? 'S' : 's'; break;
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index a1b6c94..9acd90e 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2235,7 +2235,7 @@ layout_type (tree type)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
-	machine_mode mode = TYPE_MODE (type);
+	scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
 	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 6cb5b6f..d83c405 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4146,7 +4146,7 @@ verify_gimple_assign_ternary (gassign *stmt)
 	}
 
       if (TREE_CODE (TREE_TYPE (rhs3_type)) != INTEGER_TYPE
-	  || GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs3_type)))
+	  || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs3_type)))
 	     != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type))))
 	{
 	  error ("invalid mask type in vector permute expression");
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index e0883ff..4d6e4d9 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3133,8 +3133,8 @@ convert_mult_to_widen (gimple *stmt, gimple_stmt_iterator *gsi)
   if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
     return false;
 
-  to_mode = TYPE_MODE (type);
-  from_mode = TYPE_MODE (type1);
+  to_mode = SCALAR_INT_TYPE_MODE (type);
+  from_mode = SCALAR_INT_TYPE_MODE (type1);
   from_unsigned1 = TYPE_UNSIGNED (type1);
   from_unsigned2 = TYPE_UNSIGNED (type2);
 
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index bd5d10a..7a777c1 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -378,7 +378,7 @@ get_range_info (const_tree name, wide_int *min, wide_int *max)
 
   /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
      with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
-  if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name)))
+  if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (name)))
 	      > 2 * HOST_BITS_PER_WIDE_INT))
     return VR_VARYING;
 
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 62c3a78..e4c8a60 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -951,7 +951,7 @@ array_value_type (gswitch *swtch, tree type, int num,
   if (!INTEGRAL_TYPE_P (type))
     return type;
 
-  machine_mode type_mode = TYPE_MODE (type);
+  scalar_int_mode type_mode = SCALAR_INT_TYPE_MODE (type);
   machine_mode mode = get_narrowest_mode (type_mode);
   if (GET_MODE_SIZE (type_mode) <= GET_MODE_SIZE (mode))
     return type;
@@ -998,8 +998,8 @@ array_value_type (gswitch *swtch, tree type, int num,
   if (sign == 0)
     sign = TYPE_UNSIGNED (type) ? 1 : -1;
   smaller_type = lang_hooks.types.type_for_mode (mode, sign >= 0);
-  if (GET_MODE_SIZE (TYPE_MODE (type))
-      <= GET_MODE_SIZE (TYPE_MODE (smaller_type)))
+  if (GET_MODE_SIZE (type_mode)
+      <= GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (smaller_type)))
     return type;
 
   return smaller_type;
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 835d9b5..e677238 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1882,13 +1882,14 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
     }
 
   def = NULL_TREE;
+  scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
   if (TREE_CODE (oprnd1) == INTEGER_CST
-      || TYPE_MODE (TREE_TYPE (oprnd1)) == TYPE_MODE (type))
+      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
     def = oprnd1;
   else if (def_stmt && gimple_assign_cast_p (def_stmt))
     {
       tree rhs1 = gimple_assign_rhs1 (def_stmt);
-      if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (type)
+      if (TYPE_MODE (TREE_TYPE (rhs1)) == mode
 	  && TYPE_PRECISION (TREE_TYPE (rhs1))
 	     == TYPE_PRECISION (type))
 	def = rhs1;
@@ -1909,16 +1910,16 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
 	append_pattern_def_seq (stmt_vinfo, def_stmt);
     }
   stype = TREE_TYPE (def);
+  scalar_int_mode smode = SCALAR_INT_TYPE_MODE (stype);
 
   if (TREE_CODE (def) == INTEGER_CST)
     {
       if (!tree_fits_uhwi_p (def)
-	  || tree_to_uhwi (def) >= GET_MODE_PRECISION (TYPE_MODE (type))
+	  || tree_to_uhwi (def) >= GET_MODE_PRECISION (mode)
 	  || integer_zerop (def))
 	return NULL;
       def2 = build_int_cst (stype,
-			    GET_MODE_PRECISION (TYPE_MODE (type))
-			    - tree_to_uhwi (def));
+			    GET_MODE_PRECISION (mode) - tree_to_uhwi (def));
     }
   else
     {
@@ -1944,8 +1945,7 @@ vect_recog_rotate_pattern (vec<gimple *> *stmts, tree *type_in, tree *type_out)
 	}
 
       def2 = vect_recog_temp_ssa_var (stype, NULL);
-      tree mask
-	= build_int_cst (stype, GET_MODE_PRECISION (TYPE_MODE (stype)) - 1);
+      tree mask = build_int_cst (stype, GET_MODE_PRECISION (smode) - 1);
       def_stmt = gimple_build_assign (def2, BIT_AND_EXPR,
 				      gimple_assign_lhs (def_stmt), mask);
       if (ext_def)
@@ -2588,6 +2588,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
       || TYPE_PRECISION (itype) != GET_MODE_PRECISION (TYPE_MODE (itype)))
     return NULL;
 
+  scalar_int_mode itype_mode = SCALAR_INT_TYPE_MODE (itype);
   vectype = get_vectype_for_scalar_type (itype);
   if (vectype == NULL_TREE)
     return NULL;
@@ -2655,7 +2656,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
 		= build_nonstandard_integer_type (prec, 1);
 	      tree vecutype = get_vectype_for_scalar_type (utype);
 	      tree shift
-		= build_int_cst (utype, GET_MODE_BITSIZE (TYPE_MODE (itype))
+		= build_int_cst (utype, GET_MODE_BITSIZE (itype_mode)
 					- tree_log2 (oprnd1));
 	      tree var = vect_recog_temp_ssa_var (utype, NULL);
 
@@ -2721,7 +2722,7 @@ vect_recog_divmod_pattern (vec<gimple *> *stmts,
       unsigned HOST_WIDE_INT mh, ml;
       int pre_shift, post_shift;
       unsigned HOST_WIDE_INT d = (TREE_INT_CST_LOW (oprnd1)
-				  & GET_MODE_MASK (TYPE_MODE (itype)));
+				  & GET_MODE_MASK (itype_mode));
       tree t1, t2, t3, t4;
 
       if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
@@ -3066,7 +3067,8 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
   HOST_WIDE_INT cmp_mode_size
     = GET_MODE_UNIT_BITSIZE (TYPE_MODE (comp_vectype));
 
-  if (GET_MODE_BITSIZE (TYPE_MODE (type)) == cmp_mode_size)
+  scalar_int_mode type_mode = SCALAR_INT_TYPE_MODE (type);
+  if (GET_MODE_BITSIZE (type_mode) == cmp_mode_size)
     return NULL;
 
   vectype = get_vectype_for_scalar_type (type);
@@ -3091,7 +3093,7 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
   if (!expand_vec_cond_expr_p (vecitype, comp_vectype, TREE_CODE (cond_expr)))
     return NULL;
 
-  if (GET_MODE_BITSIZE (TYPE_MODE (type)) > cmp_mode_size)
+  if (GET_MODE_BITSIZE (type_mode) > cmp_mode_size)
     {
       if ((TREE_CODE (then_clause) == INTEGER_CST
 	   && !int_fits_type_p (then_clause, itype))
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 9a5f69d..acd536c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3824,6 +3824,7 @@ extract_range_basic (value_range *vr, gimple *stmt)
       int mini, maxi, zerov = 0, prec;
       enum tree_code subcode = ERROR_MARK;
       combined_fn cfn = gimple_call_combined_fn (stmt);
+      scalar_int_mode mode;
 
       switch (cfn)
 	{
@@ -3887,10 +3888,9 @@ extract_range_basic (value_range *vr, gimple *stmt)
 	  prec = TYPE_PRECISION (TREE_TYPE (arg));
 	  mini = 0;
 	  maxi = prec;
-	  if (optab_handler (clz_optab, TYPE_MODE (TREE_TYPE (arg)))
-	      != CODE_FOR_nothing
-	      && CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)),
-					    zerov)
+	  mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+	  if (optab_handler (clz_optab, mode) != CODE_FOR_nothing
+	      && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov)
 	      /* Handle only the single common value.  */
 	      && zerov != prec)
 	    /* Magic value to give up, unless vr0 proves
@@ -3942,10 +3942,9 @@ extract_range_basic (value_range *vr, gimple *stmt)
 	  prec = TYPE_PRECISION (TREE_TYPE (arg));
 	  mini = 0;
 	  maxi = prec - 1;
-	  if (optab_handler (ctz_optab, TYPE_MODE (TREE_TYPE (arg)))
-	      != CODE_FOR_nothing
-	      && CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)),
-					    zerov))
+	  mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg));
+	  if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing
+	      && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov))
 	    {
 	      /* Handle only the two common values.  */
 	      if (zerov == -1)
@@ -9982,13 +9981,13 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
     return false;
 
   /* First check if we can use a signed type in place of an unsigned.  */
+  scalar_int_mode rhs_mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs1));
   if (TYPE_UNSIGNED (TREE_TYPE (rhs1))
-      && (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)), 0)
-	  != CODE_FOR_nothing)
+      && can_float_p (fltmode, rhs_mode, 0) != CODE_FOR_nothing
       && range_fits_type_p (vr, TYPE_PRECISION (TREE_TYPE (rhs1)), SIGNED))
-    mode = TYPE_MODE (TREE_TYPE (rhs1));
+    mode = rhs_mode;
   /* If we can do the conversion in the current input mode do nothing.  */
-  else if (can_float_p (fltmode, TYPE_MODE (TREE_TYPE (rhs1)),
+  else if (can_float_p (fltmode, rhs_mode,
 			TYPE_UNSIGNED (TREE_TYPE (rhs1))) != CODE_FOR_nothing)
     return false;
   /* Otherwise search for a mode we can use, starting from the narrowest
diff --git a/gcc/tree.c b/gcc/tree.c
index 5124576..b58f503 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9199,7 +9199,7 @@ retry:
   /* Third, unsigned integers with top bit set never fit signed types.  */
   if (!TYPE_UNSIGNED (type) && sgn_c == UNSIGNED)
     {
-      int prec = GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (c))) - 1;
+      int prec = GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (c))) - 1;
       if (prec < TYPE_PRECISION (TREE_TYPE (c)))
 	{
 	  /* When a tree_cst is converted to a wide-int, the precision
diff --git a/gcc/tree.h b/gcc/tree.h
index 7791c22..1c2f71f 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1829,6 +1829,8 @@ extern void protected_set_expr_location (tree, location_t);
    ((const machine_mode &) \
     (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
      ? vector_type_mode (NODE) : machine_mode ((NODE)->type_common.mode)))
+#define SCALAR_INT_TYPE_MODE(NODE) \
+  (as_a <scalar_int_mode> (TYPE_CHECK (NODE)->type_common.mode))
 #define SCALAR_FLOAT_TYPE_MODE(NODE) \
   (as_a <scalar_float_mode> (TYPE_CHECK (NODE)->type_common.mode))
 #define SET_TYPE_MODE(NODE, MODE) \
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index d5422a1..10f3eaa 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1360,7 +1360,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
 	   && TREE_TYPE (type) != NULL_TREE
 	   && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
 	   && (TYPE_PRECISION (TREE_TYPE (type))
-	       < GET_MODE_PRECISION (TYPE_MODE (type))))
+	       < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
     {
       minv = TYPE_MIN_VALUE (TREE_TYPE (type));
       maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
@@ -1368,7 +1368,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
   else
     return;
 
-  int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
+  int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
   machine_mode mode;
@@ -1380,7 +1380,7 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
   if ((VAR_P (base) && DECL_HARD_REGISTER (base))
       || (bitpos % modebitsize) != 0
       || bitsize != modebitsize
-      || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
+      || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
       || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
     return;
 
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 320a5a6..b9206b8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -783,7 +783,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
       && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
       && TREE_STRING_LENGTH (decl) >= len)
     {
-      machine_mode mode;
+      scalar_int_mode mode;
       unsigned int modesize;
       const char *str;
       HOST_WIDE_INT i;
@@ -791,7 +791,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
       const char *prefix = function_mergeable_rodata_prefix ();
       char *name = (char *) alloca (strlen (prefix) + 30);
 
-      mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
+      mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
       modesize = GET_MODE_BITSIZE (mode);
       if (modesize >= 8 && modesize <= 256
 	  && (modesize & (modesize - 1)) == 0)
@@ -4281,8 +4281,8 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
       tree inner = TREE_OPERAND (op0, 0);
       if (inner == error_mark_node
 	  || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
-	  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
-	      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+	  || (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (op0)))
+	      > GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (inner)))))
 	break;
       op0 = inner;
     }
@@ -4293,8 +4293,8 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
       tree inner = TREE_OPERAND (op1, 0);
       if (inner == error_mark_node
 	  || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
-	  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
-	      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+	  || (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (op1)))
+	      > GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (inner)))))
 	break;
       op1 = inner;
     }
@@ -4712,7 +4712,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
   if (TREE_CODE (exp) == NOP_EXPR
       && POINTER_TYPE_P (TREE_TYPE (exp))
       && targetm.addr_space.valid_pointer_mode
-	   (TYPE_MODE (TREE_TYPE (exp)),
+	   (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)),
 	    TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
     {
       tree saved_type = TREE_TYPE (exp);
@@ -4722,7 +4722,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
       while (TREE_CODE (exp) == NOP_EXPR
 	     && POINTER_TYPE_P (TREE_TYPE (exp))
 	     && targetm.addr_space.valid_pointer_mode
-		  (TYPE_MODE (TREE_TYPE (exp)),
+		  (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)),
 		   TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
 	exp = TREE_OPERAND (exp, 0);
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [35/67] Add uses of as_a <scalar_int_mode>
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (34 preceding siblings ...)
  2016-12-09 13:15 ` [34/67] Add a SCALAR_INT_TYPE_MODE macro Richard Sandiford
@ 2016-12-09 13:16 ` Richard Sandiford
  2016-12-09 13:16 ` [36/67] Use scalar_int_mode in the RTL iv routines Richard Sandiford
                   ` (33 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:16 UTC (permalink / raw)
  To: gcc-patches

This patch adds asserting as_a <scalar_int_mode> conversions
in contexts where the input is known to be a scalar integer mode.

In expand_divmod, op1 is always a scalar_int_mode if
op1_is_constant (but might not be otherwise).

In expand_binop, the patch reverses a < comparison in order to
avoid splitting a long line.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* cfgexpand.c (convert_debug_memory_address): Use
	as_a <scalar_int_mode>.
	* combine.c (expand_compound_operation): Likewise.
	(make_extraction): Likewise.
	(change_zero_ext): Likewise.
	(simplify_comparison): Likewise.
	* cse.c (cse_insn): Likewise.
	* dwarf2out.c (minmax_loc_descriptor): Likewise.
	(mem_loc_descriptor): Likewise.
	(loc_descriptor): Likewise.
	* expmed.c (synth_mult): Likewise.
	(emit_store_flag_1): Likewise.
	(expand_divmod): Likewise.  Use HWI_COMPUTABLE_MODE_P instead
	of a comparison with size.
	* expr.c (expand_assignment): Use as_a <scalar_int_mode>.
	(reduce_to_bit_field_precision): Likewise.
	* function.c (expand_function_end): Likewise.
	* internal-fn.c (expand_arith_overflow_result_store): Likewise.
	* loop-doloop.c (doloop_modify): Likewise.
	* optabs.c (expand_binop): Likewise.
	(expand_unop): Likewise.
	(expand_copysign_absneg): Likewise.
	(prepare_cmp_insn): Likewise.
	(maybe_legitimize_operand): Likewise.
	* recog.c (const_scalar_int_operand): Likewise.
	* rtlanal.c (get_address_mode): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.
	(simplify_cond_clz_ctz): Likewise.
	* tree-nested.c (get_nl_goto_field): Likewise.
	* tree.c (build_vector_type_for_mode): Likewise.
	* var-tracking.c (use_narrower_mode): Likewise.

gcc/c-family/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* c-common.c (c_common_type_for_mode): Use as_a <scalar_int_mode>.

gcc/lto/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* lto-lang.c (lto_type_for_mode): Use as_a <scalar_int_mode>.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index cb04536..0e06725 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2216,15 +2216,15 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
   if (mode == TYPE_MODE (void_type_node))
     return void_type_node;
 
-  if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
-    return (unsignedp
-	    ? make_unsigned_type (GET_MODE_PRECISION (mode))
-	    : make_signed_type (GET_MODE_PRECISION (mode)));
-
-  if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
-    return (unsignedp
-	    ? make_unsigned_type (GET_MODE_PRECISION (mode))
-	    : make_signed_type (GET_MODE_PRECISION (mode)));
+  if (mode == TYPE_MODE (build_pointer_type (char_type_node))
+      || mode == TYPE_MODE (build_pointer_type (integer_type_node)))
+    {
+      unsigned int precision
+	= GET_MODE_PRECISION (as_a <scalar_int_mode> (mode));
+      return (unsignedp
+	      ? make_unsigned_type (precision)
+	      : make_signed_type (precision));
+    }
 
   if (COMPLEX_MODE_P (mode))
     {
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index dbb7bca..c4863dd 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3954,12 +3954,10 @@ static rtx
 convert_debug_memory_address (machine_mode mode, rtx x,
 			      addr_space_t as)
 {
-  machine_mode xmode = GET_MODE (x);
-
 #ifndef POINTERS_EXTEND_UNSIGNED
   gcc_assert (mode == Pmode
 	      || mode == targetm.addr_space.address_mode (as));
-  gcc_assert (xmode == mode || xmode == VOIDmode);
+  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
 #else
   rtx temp;
 
@@ -3968,6 +3966,8 @@ convert_debug_memory_address (machine_mode mode, rtx x,
   if (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode)
     return x;
 
+  /* X must have some form of address mode already.  */
+  scalar_int_mode xmode = as_a <scalar_int_mode> (GET_MODE (x));
   if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (xmode))
     x = lowpart_subreg (mode, x, xmode);
   else if (POINTERS_EXTEND_UNSIGNED > 0)
diff --git a/gcc/combine.c b/gcc/combine.c
index 92b2ec9..0f25782 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7121,16 +7121,19 @@ expand_compound_operation (rtx x)
     default:
       return x;
     }
+
+  /* We've rejected non-scalar operations by now.  */
+  scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (x));
+
   /* Convert sign extension to zero extension, if we know that the high
      bit is not set, as this is easier to optimize.  It will be converted
      back to cheaper alternative in make_extraction.  */
   if (GET_CODE (x) == SIGN_EXTEND
-      && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
+      && HWI_COMPUTABLE_MODE_P (mode)
       && ((nonzero_bits (XEXP (x, 0), inner_mode)
 	   & ~(((unsigned HOST_WIDE_INT) GET_MODE_MASK (inner_mode)) >> 1))
 	  == 0))
     {
-      machine_mode mode = GET_MODE (x);
       rtx temp = gen_rtx_ZERO_EXTEND (mode, XEXP (x, 0));
       rtx temp2 = expand_compound_operation (temp);
 
@@ -7152,27 +7155,27 @@ expand_compound_operation (rtx x)
 	 know that the last value didn't have any inappropriate bits
 	 set.  */
       if (GET_CODE (XEXP (x, 0)) == TRUNCATE
-	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
-	  && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
-	  && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
+	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode
+	  && HWI_COMPUTABLE_MODE_P (mode)
+	  && (nonzero_bits (XEXP (XEXP (x, 0), 0), mode)
 	      & ~GET_MODE_MASK (inner_mode)) == 0)
 	return XEXP (XEXP (x, 0), 0);
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
       if (GET_CODE (XEXP (x, 0)) == SUBREG
-	  && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+	  && GET_MODE (SUBREG_REG (XEXP (x, 0))) == mode
 	  && subreg_lowpart_p (XEXP (x, 0))
-	  && HWI_COMPUTABLE_MODE_P (GET_MODE (x))
-	  && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
+	  && HWI_COMPUTABLE_MODE_P (mode)
+	  && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), mode)
 	      & ~GET_MODE_MASK (inner_mode)) == 0)
 	return SUBREG_REG (XEXP (x, 0));
 
       /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo
 	 is a comparison and STORE_FLAG_VALUE permits.  This is like
-	 the first case, but it works even when GET_MODE (x) is larger
+	 the first case, but it works even when MODE is larger
 	 than HOST_WIDE_INT.  */
       if (GET_CODE (XEXP (x, 0)) == TRUNCATE
-	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
+	  && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode
 	  && COMPARISON_P (XEXP (XEXP (x, 0), 0))
 	  && GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
 	  && (STORE_FLAG_VALUE & ~GET_MODE_MASK (inner_mode)) == 0)
@@ -7180,7 +7183,7 @@ expand_compound_operation (rtx x)
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
       if (GET_CODE (XEXP (x, 0)) == SUBREG
-	  && GET_MODE (SUBREG_REG (XEXP (x, 0))) == GET_MODE (x)
+	  && GET_MODE (SUBREG_REG (XEXP (x, 0))) == mode
 	  && subreg_lowpart_p (XEXP (x, 0))
 	  && COMPARISON_P (SUBREG_REG (XEXP (x, 0)))
 	  && GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
@@ -7204,10 +7207,9 @@ expand_compound_operation (rtx x)
      extraction.  Then the constant of 31 would be substituted in
      to produce such a position.  */
 
-  modewidth = GET_MODE_PRECISION (GET_MODE (x));
+  modewidth = GET_MODE_PRECISION (mode);
   if (modewidth >= pos + len)
     {
-      machine_mode mode = GET_MODE (x);
       tem = gen_lowpart (mode, XEXP (x, 0));
       if (!tem || GET_CODE (tem) == CLOBBER)
 	return x;
@@ -7217,10 +7219,10 @@ expand_compound_operation (rtx x)
 				  mode, tem, modewidth - len);
     }
   else if (unsignedp && len < HOST_BITS_PER_WIDE_INT)
-    tem = simplify_and_const_int (NULL_RTX, GET_MODE (x),
+    tem = simplify_and_const_int (NULL_RTX, mode,
 				  simplify_shift_const (NULL_RTX, LSHIFTRT,
-							GET_MODE (x),
-							XEXP (x, 0), pos),
+							mode, XEXP (x, 0),
+							pos),
 				  (HOST_WIDE_INT_1U << len) - 1);
   else
     /* Any other cases we can't handle.  */
@@ -7721,9 +7723,13 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
     }
 
   /* Adjust mode of POS_RTX, if needed.  If we want a wider mode, we
-     have to zero extend.  Otherwise, we can just use a SUBREG.  */
+     have to zero extend.  Otherwise, we can just use a SUBREG.
+
+     We dealt with constant rtxes earlier, so pos_rtx cannot
+     have VOIDmode at this point.  */
   if (pos_rtx != 0
-      && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx)))
+      && (GET_MODE_SIZE (pos_mode)
+	  > GET_MODE_SIZE (as_a <scalar_int_mode> (GET_MODE (pos_rtx)))))
     {
       rtx temp = simplify_gen_unary (ZERO_EXTEND, pos_mode, pos_rtx,
 				     GET_MODE (pos_rtx));
@@ -11307,7 +11313,9 @@ change_zero_ext (rtx pat)
 	       && !paradoxical_subreg_p (XEXP (x, 0))
 	       && subreg_lowpart_p (XEXP (x, 0)))
 	{
-	  size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
+	  scalar_int_mode inner_mode
+	    = as_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)));
+	  size = GET_MODE_PRECISION (inner_mode);
 	  x = SUBREG_REG (XEXP (x, 0));
 	  if (GET_MODE (x) != mode)
 	    x = gen_lowpart_SUBREG (mode, x);
@@ -11317,7 +11325,9 @@ change_zero_ext (rtx pat)
 	       && HARD_REGISTER_P (XEXP (x, 0))
 	       && can_change_dest_mode (XEXP (x, 0), 0, mode))
 	{
-	  size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
+	  scalar_int_mode inner_mode
+	    = as_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)));
+	  size = GET_MODE_PRECISION (inner_mode);
 	  x = gen_rtx_REG (mode, REGNO (XEXP (x, 0)));
 	}
       else
@@ -11730,8 +11740,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
   rtx op1 = *pop1;
   rtx tem, tem1;
   int i;
-  scalar_int_mode mode, inner_mode;
-  machine_mode tmode;
+  scalar_int_mode mode, inner_mode, tmode;
+  opt_scalar_int_mode tmode_iter;
 
   /* Try a few ways of applying the same transformation to both operands.  */
   while (1)
@@ -11839,7 +11849,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	    }
 
 	  else if (c0 == c1)
-	    FOR_EACH_MODE_UNTIL (tmode, GET_MODE (op0))
+	    FOR_EACH_MODE_UNTIL (tmode,
+				 as_a <scalar_int_mode> (GET_MODE (op0)))
 	      if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
 		{
 		  op0 = gen_lowpart_or_truncate (tmode, inner_op0);
@@ -12708,8 +12719,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
   if (is_int_mode (GET_MODE (op0), &mode)
       && GET_MODE_SIZE (mode) < UNITS_PER_WORD
       && ! have_insn_for (COMPARE, mode))
-    FOR_EACH_WIDER_MODE (tmode, mode)
+    FOR_EACH_WIDER_MODE (tmode_iter, mode)
       {
+	tmode = *tmode_iter;
 	if (!HWI_COMPUTABLE_MODE_P (tmode))
 	  break;
 	if (have_insn_for (COMPARE, tmode))
diff --git a/gcc/cse.c b/gcc/cse.c
index 2f29062..4d22d78 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4552,14 +4552,17 @@ cse_insn (rtx_insn *insn)
 	       && CONST_INT_P (XEXP (SET_DEST (sets[0].rtl), 2)))
 	{
 	  rtx dest_reg = XEXP (SET_DEST (sets[0].rtl), 0);
+	  /* This is the mode of XEXP (tem, 0) as well.  */
+	  scalar_int_mode dest_mode
+	    = as_a <scalar_int_mode> (GET_MODE (dest_reg));
 	  rtx width = XEXP (SET_DEST (sets[0].rtl), 1);
 	  rtx pos = XEXP (SET_DEST (sets[0].rtl), 2);
 	  HOST_WIDE_INT val = INTVAL (XEXP (tem, 0));
 	  HOST_WIDE_INT mask;
 	  unsigned int shift;
 	  if (BITS_BIG_ENDIAN)
-	    shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
-	      - INTVAL (pos) - INTVAL (width);
+	    shift = (GET_MODE_PRECISION (dest_mode)
+		     - INTVAL (pos) - INTVAL (width));
 	  else
 	    shift = INTVAL (pos);
 	  if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
@@ -5231,8 +5234,11 @@ cse_insn (rtx_insn *insn)
 		  HOST_WIDE_INT val = INTVAL (dest_cst);
 		  HOST_WIDE_INT mask;
 		  unsigned int shift;
+		  /* This is the mode of DEST_CST as well.  */
+		  scalar_int_mode dest_mode
+		    = as_a <scalar_int_mode> (GET_MODE (dest_reg));
 		  if (BITS_BIG_ENDIAN)
-		    shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
+		    shift = GET_MODE_PRECISION (dest_mode)
 			    - INTVAL (pos) - INTVAL (width);
 		  else
 		    shift = INTVAL (pos);
@@ -5242,7 +5248,7 @@ cse_insn (rtx_insn *insn)
 		    mask = (HOST_WIDE_INT_1 << INTVAL (width)) - 1;
 		  val &= ~(mask << shift);
 		  val |= (INTVAL (trial) & mask) << shift;
-		  val = trunc_int_for_mode (val, GET_MODE (dest_reg));
+		  val = trunc_int_for_mode (val, dest_mode);
 		  validate_unshare_change (insn, &SET_DEST (sets[i].rtl),
 					   dest_reg, 1);
 		  validate_unshare_change (insn, &SET_SRC (sets[i].rtl),
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ed5ec24..accca42 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -13969,15 +13969,17 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
   add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0));
   if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX)
     {
-      if (GET_MODE_SIZE (mode) < DWARF2_ADDR_SIZE)
+      /* Checked by the caller.  */
+      int_mode = as_a <scalar_int_mode> (mode);
+      if (GET_MODE_SIZE (int_mode) < DWARF2_ADDR_SIZE)
 	{
-	  HOST_WIDE_INT mask = GET_MODE_MASK (mode);
+	  HOST_WIDE_INT mask = GET_MODE_MASK (int_mode);
 	  add_loc_descr (&op0, int_loc_descriptor (mask));
 	  add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
 	  add_loc_descr (&op1, int_loc_descriptor (mask));
 	  add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
 	}
-      else if (GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE)
+      else if (GET_MODE_SIZE (int_mode) == DWARF2_ADDR_SIZE)
 	{
 	  HOST_WIDE_INT bias = 1;
 	  bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
@@ -14860,7 +14862,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
 	    break;
 
 	  if (CONST_INT_P (XEXP (rtl, 1))
-	      && GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
+	      && (GET_MODE_SIZE (as_a <scalar_int_mode> (mode))
+		  <= DWARF2_ADDR_SIZE))
 	    loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1)));
 	  else
 	    {
@@ -15643,8 +15646,11 @@ loc_descriptor (rtx rtl, machine_mode mode,
 
     case CONST_INT:
       if (mode != VOIDmode && mode != BLKmode)
-	loc_result = address_of_int_loc_descriptor (GET_MODE_SIZE (mode),
-						    INTVAL (rtl));
+	{
+	  int_mode = as_a <scalar_int_mode> (mode);
+	  loc_result = address_of_int_loc_descriptor (GET_MODE_SIZE (int_mode),
+						      INTVAL (rtl));
+	}
       break;
 
     case CONST_DOUBLE:
@@ -15689,11 +15695,12 @@ loc_descriptor (rtx rtl, machine_mode mode,
 
       if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
 	{
+	  int_mode = as_a <scalar_int_mode> (mode);
 	  loc_result = new_loc_descr (DW_OP_implicit_value,
-				      GET_MODE_SIZE (mode), 0);
+				      GET_MODE_SIZE (int_mode), 0);
 	  loc_result->dw_loc_oprnd2.val_class = dw_val_class_wide_int;
 	  loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<wide_int> ();
-	  *loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, mode);
+	  *loc_result->dw_loc_oprnd2.v.val_wide = rtx_mode_t (rtl, int_mode);
 	}
       break;
 
diff --git a/gcc/expmed.c b/gcc/expmed.c
index f056e96..dea4923 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2513,7 +2513,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
   bool cache_hit = false;
   enum alg_code cache_alg = alg_zero;
   bool speed = optimize_insn_for_speed_p ();
-  machine_mode imode;
+  scalar_int_mode imode;
   struct alg_hash_entry *entry_ptr;
 
   /* Indicate that no algorithm is yet found.  If no algorithm
@@ -2526,7 +2526,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
     return;
 
   /* Be prepared for vector modes.  */
-  imode = GET_MODE_INNER (mode);
+  imode = as_a <scalar_int_mode> (GET_MODE_INNER (mode));
 
   maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (imode));
 
@@ -3970,7 +3970,6 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
   rtx tquotient;
   rtx quotient = 0, remainder = 0;
   rtx_insn *last;
-  int size;
   rtx_insn *insn;
   optab optab1, optab2;
   int op1_is_constant, op1_is_pow2 = 0;
@@ -4092,7 +4091,6 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
   else
     tquotient = gen_reg_rtx (compute_mode);
 
-  size = GET_MODE_BITSIZE (compute_mode);
 #if 0
   /* It should be possible to restrict the precision to GET_MODE_BITSIZE
      (mode), and thereby get better code when OP1 is a constant.  Do that
@@ -4165,12 +4163,14 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
       case TRUNC_DIV_EXPR:
 	if (op1_is_constant)
 	  {
+	    scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode);
+	    int size = GET_MODE_BITSIZE (int_mode);
 	    if (unsignedp)
 	      {
 		unsigned HOST_WIDE_INT mh, ml;
 		int pre_shift, post_shift;
 		int dummy;
-		wide_int wd = rtx_mode_t (op1, compute_mode);
+		wide_int wd = rtx_mode_t (op1, int_mode);
 		unsigned HOST_WIDE_INT d = wd.to_uhwi ();
 
 		if (wi::popcount (wd) == 1)
@@ -4181,14 +4181,14 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			unsigned HOST_WIDE_INT mask
 			  = (HOST_WIDE_INT_1U << pre_shift) - 1;
 			remainder
-			  = expand_binop (compute_mode, and_optab, op0,
-					  gen_int_mode (mask, compute_mode),
+			  = expand_binop (int_mode, and_optab, op0,
+					  gen_int_mode (mask, int_mode),
 					  remainder, 1,
 					  OPTAB_LIB_WIDEN);
 			if (remainder)
 			  return gen_lowpart (mode, remainder);
 		      }
-		    quotient = expand_shift (RSHIFT_EXPR, compute_mode, op0,
+		    quotient = expand_shift (RSHIFT_EXPR, int_mode, op0,
 					     pre_shift, tquotient, 1);
 		  }
 		else if (size <= HOST_BITS_PER_WIDE_INT)
@@ -4198,7 +4198,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			/* Most significant bit of divisor is set; emit an scc
 			   insn.  */
 			quotient = emit_store_flag_force (tquotient, GEU, op0, op1,
-							  compute_mode, 1, 1);
+							  int_mode, 1, 1);
 		      }
 		    else
 		      {
@@ -4230,25 +4230,25 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			      goto fail1;
 
 			    extra_cost
-			      = (shift_cost (speed, compute_mode, post_shift - 1)
-				 + shift_cost (speed, compute_mode, 1)
-				 + 2 * add_cost (speed, compute_mode));
+			      = (shift_cost (speed, int_mode, post_shift - 1)
+				 + shift_cost (speed, int_mode, 1)
+				 + 2 * add_cost (speed, int_mode));
 			    t1 = expmed_mult_highpart
-			      (compute_mode, op0,
-			       gen_int_mode (ml, compute_mode),
+			      (int_mode, op0,
+			       gen_int_mode (ml, int_mode),
 			       NULL_RTX, 1, max_cost - extra_cost);
 			    if (t1 == 0)
 			      goto fail1;
-			    t2 = force_operand (gen_rtx_MINUS (compute_mode,
+			    t2 = force_operand (gen_rtx_MINUS (int_mode,
 							       op0, t1),
 						NULL_RTX);
-			    t3 = expand_shift (RSHIFT_EXPR, compute_mode,
+			    t3 = expand_shift (RSHIFT_EXPR, int_mode,
 					       t2, 1, NULL_RTX, 1);
-			    t4 = force_operand (gen_rtx_PLUS (compute_mode,
+			    t4 = force_operand (gen_rtx_PLUS (int_mode,
 							      t1, t3),
 						NULL_RTX);
 			    quotient = expand_shift
-			      (RSHIFT_EXPR, compute_mode, t4,
+			      (RSHIFT_EXPR, int_mode, t4,
 			       post_shift - 1, tquotient, 1);
 			  }
 			else
@@ -4260,19 +4260,19 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			      goto fail1;
 
 			    t1 = expand_shift
-			      (RSHIFT_EXPR, compute_mode, op0,
+			      (RSHIFT_EXPR, int_mode, op0,
 			       pre_shift, NULL_RTX, 1);
 			    extra_cost
-			      = (shift_cost (speed, compute_mode, pre_shift)
-				 + shift_cost (speed, compute_mode, post_shift));
+			      = (shift_cost (speed, int_mode, pre_shift)
+				 + shift_cost (speed, int_mode, post_shift));
 			    t2 = expmed_mult_highpart
-			      (compute_mode, t1,
-			       gen_int_mode (ml, compute_mode),
+			      (int_mode, t1,
+			       gen_int_mode (ml, int_mode),
 			       NULL_RTX, 1, max_cost - extra_cost);
 			    if (t2 == 0)
 			      goto fail1;
 			    quotient = expand_shift
-			      (RSHIFT_EXPR, compute_mode, t2,
+			      (RSHIFT_EXPR, int_mode, t2,
 			       post_shift, tquotient, 1);
 			  }
 		      }
@@ -4283,7 +4283,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 		insn = get_last_insn ();
 		if (insn != last)
 		  set_dst_reg_note (insn, REG_EQUAL,
-				    gen_rtx_UDIV (compute_mode, op0, op1),
+				    gen_rtx_UDIV (int_mode, op0, op1),
 				    quotient);
 	      }
 	    else		/* TRUNC_DIV, signed */
@@ -4305,36 +4305,36 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 		if (rem_flag && d < 0)
 		  {
 		    d = abs_d;
-		    op1 = gen_int_mode (abs_d, compute_mode);
+		    op1 = gen_int_mode (abs_d, int_mode);
 		  }
 
 		if (d == 1)
 		  quotient = op0;
 		else if (d == -1)
-		  quotient = expand_unop (compute_mode, neg_optab, op0,
+		  quotient = expand_unop (int_mode, neg_optab, op0,
 					  tquotient, 0);
 		else if (size <= HOST_BITS_PER_WIDE_INT
 			 && abs_d == HOST_WIDE_INT_1U << (size - 1))
 		  {
 		    /* This case is not handled correctly below.  */
 		    quotient = emit_store_flag (tquotient, EQ, op0, op1,
-						compute_mode, 1, 1);
+						int_mode, 1, 1);
 		    if (quotient == 0)
 		      goto fail1;
 		  }
 		else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
 			 && (size <= HOST_BITS_PER_WIDE_INT || d >= 0)
 			 && (rem_flag
-			     ? smod_pow2_cheap (speed, compute_mode)
-			     : sdiv_pow2_cheap (speed, compute_mode))
+			     ? smod_pow2_cheap (speed, int_mode)
+			     : sdiv_pow2_cheap (speed, int_mode))
 			 /* We assume that cheap metric is true if the
 			    optab has an expander for this mode.  */
 			 && ((optab_handler ((rem_flag ? smod_optab
 					      : sdiv_optab),
-					     compute_mode)
+					     int_mode)
 			      != CODE_FOR_nothing)
 			     || (optab_handler (sdivmod_optab,
-						compute_mode)
+						int_mode)
 				 != CODE_FOR_nothing)))
 		  ;
 		else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)
@@ -4343,23 +4343,23 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 		  {
 		    if (rem_flag)
 		      {
-			remainder = expand_smod_pow2 (compute_mode, op0, d);
+			remainder = expand_smod_pow2 (int_mode, op0, d);
 			if (remainder)
 			  return gen_lowpart (mode, remainder);
 		      }
 
-		    if (sdiv_pow2_cheap (speed, compute_mode)
-			&& ((optab_handler (sdiv_optab, compute_mode)
+		    if (sdiv_pow2_cheap (speed, int_mode)
+			&& ((optab_handler (sdiv_optab, int_mode)
 			     != CODE_FOR_nothing)
-			    || (optab_handler (sdivmod_optab, compute_mode)
+			    || (optab_handler (sdivmod_optab, int_mode)
 				!= CODE_FOR_nothing)))
 		      quotient = expand_divmod (0, TRUNC_DIV_EXPR,
-						compute_mode, op0,
+						int_mode, op0,
 						gen_int_mode (abs_d,
-							      compute_mode),
+							      int_mode),
 						NULL_RTX, 0);
 		    else
-		      quotient = expand_sdiv_pow2 (compute_mode, op0, abs_d);
+		      quotient = expand_sdiv_pow2 (int_mode, op0, abs_d);
 
 		    /* We have computed OP0 / abs(OP1).  If OP1 is negative,
 		       negate the quotient.  */
@@ -4370,13 +4370,13 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			    && abs_d < (HOST_WIDE_INT_1U
 					<< (HOST_BITS_PER_WIDE_INT - 1)))
 			  set_dst_reg_note (insn, REG_EQUAL,
-					    gen_rtx_DIV (compute_mode, op0,
+					    gen_rtx_DIV (int_mode, op0,
 							 gen_int_mode
 							   (abs_d,
-							    compute_mode)),
+							    int_mode)),
 					    quotient);
 
-			quotient = expand_unop (compute_mode, neg_optab,
+			quotient = expand_unop (int_mode, neg_optab,
 						quotient, quotient, 0);
 		      }
 		  }
@@ -4392,29 +4392,27 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			    || size - 1 >= BITS_PER_WORD)
 			  goto fail1;
 
-			extra_cost = (shift_cost (speed, compute_mode, post_shift)
-				      + shift_cost (speed, compute_mode, size - 1)
-				      + add_cost (speed, compute_mode));
+			extra_cost = (shift_cost (speed, int_mode, post_shift)
+				      + shift_cost (speed, int_mode, size - 1)
+				      + add_cost (speed, int_mode));
 			t1 = expmed_mult_highpart
-			  (compute_mode, op0, gen_int_mode (ml, compute_mode),
+			  (int_mode, op0, gen_int_mode (ml, int_mode),
 			   NULL_RTX, 0, max_cost - extra_cost);
 			if (t1 == 0)
 			  goto fail1;
 			t2 = expand_shift
-			  (RSHIFT_EXPR, compute_mode, t1,
+			  (RSHIFT_EXPR, int_mode, t1,
 			   post_shift, NULL_RTX, 0);
 			t3 = expand_shift
-			  (RSHIFT_EXPR, compute_mode, op0,
+			  (RSHIFT_EXPR, int_mode, op0,
 			   size - 1, NULL_RTX, 0);
 			if (d < 0)
 			  quotient
-			    = force_operand (gen_rtx_MINUS (compute_mode,
-							    t3, t2),
+			    = force_operand (gen_rtx_MINUS (int_mode, t3, t2),
 					     tquotient);
 			else
 			  quotient
-			    = force_operand (gen_rtx_MINUS (compute_mode,
-							    t2, t3),
+			    = force_operand (gen_rtx_MINUS (int_mode, t2, t3),
 					     tquotient);
 		      }
 		    else
@@ -4426,33 +4424,30 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			  goto fail1;
 
 			ml |= HOST_WIDE_INT_M1U << (size - 1);
-			mlr = gen_int_mode (ml, compute_mode);
-			extra_cost = (shift_cost (speed, compute_mode, post_shift)
-				      + shift_cost (speed, compute_mode, size - 1)
-				      + 2 * add_cost (speed, compute_mode));
-			t1 = expmed_mult_highpart (compute_mode, op0, mlr,
+			mlr = gen_int_mode (ml, int_mode);
+			extra_cost = (shift_cost (speed, int_mode, post_shift)
+				      + shift_cost (speed, int_mode, size - 1)
+				      + 2 * add_cost (speed, int_mode));
+			t1 = expmed_mult_highpart (int_mode, op0, mlr,
 						   NULL_RTX, 0,
 						   max_cost - extra_cost);
 			if (t1 == 0)
 			  goto fail1;
-			t2 = force_operand (gen_rtx_PLUS (compute_mode,
-							  t1, op0),
+			t2 = force_operand (gen_rtx_PLUS (int_mode, t1, op0),
 					    NULL_RTX);
 			t3 = expand_shift
-			  (RSHIFT_EXPR, compute_mode, t2,
+			  (RSHIFT_EXPR, int_mode, t2,
 			   post_shift, NULL_RTX, 0);
 			t4 = expand_shift
-			  (RSHIFT_EXPR, compute_mode, op0,
+			  (RSHIFT_EXPR, int_mode, op0,
 			   size - 1, NULL_RTX, 0);
 			if (d < 0)
 			  quotient
-			    = force_operand (gen_rtx_MINUS (compute_mode,
-							    t4, t3),
+			    = force_operand (gen_rtx_MINUS (int_mode, t4, t3),
 					     tquotient);
 			else
 			  quotient
-			    = force_operand (gen_rtx_MINUS (compute_mode,
-							    t3, t4),
+			    = force_operand (gen_rtx_MINUS (int_mode, t3, t4),
 					     tquotient);
 		      }
 		  }
@@ -4462,7 +4457,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 		insn = get_last_insn ();
 		if (insn != last)
 		  set_dst_reg_note (insn, REG_EQUAL,
-				    gen_rtx_DIV (compute_mode, op0, op1),
+				    gen_rtx_DIV (int_mode, op0, op1),
 				    quotient);
 	      }
 	    break;
@@ -4474,8 +4469,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
       case FLOOR_DIV_EXPR:
       case FLOOR_MOD_EXPR:
       /* We will come here only for signed operations.  */
-	if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
+	if (op1_is_constant && HWI_COMPUTABLE_MODE_P (compute_mode))
 	  {
+	    scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode);
+	    int size = GET_MODE_BITSIZE (int_mode);
 	    unsigned HOST_WIDE_INT mh, ml;
 	    int pre_shift, lgup, post_shift;
 	    HOST_WIDE_INT d = INTVAL (op1);
@@ -4492,14 +4489,14 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			unsigned HOST_WIDE_INT mask
 			  = (HOST_WIDE_INT_1U << pre_shift) - 1;
 			remainder = expand_binop
-			  (compute_mode, and_optab, op0,
-			   gen_int_mode (mask, compute_mode),
+			  (int_mode, and_optab, op0,
+			   gen_int_mode (mask, int_mode),
 			   remainder, 0, OPTAB_LIB_WIDEN);
 			if (remainder)
 			  return gen_lowpart (mode, remainder);
 		      }
 		    quotient = expand_shift
-		      (RSHIFT_EXPR, compute_mode, op0,
+		      (RSHIFT_EXPR, int_mode, op0,
 		       pre_shift, tquotient, 0);
 		  }
 		else
@@ -4514,22 +4511,22 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 			&& size - 1 < BITS_PER_WORD)
 		      {
 			t1 = expand_shift
-			  (RSHIFT_EXPR, compute_mode, op0,
+			  (RSHIFT_EXPR, int_mode, op0,
 			   size - 1, NULL_RTX, 0);
-			t2 = expand_binop (compute_mode, xor_optab, op0, t1,
+			t2 = expand_binop (int_mode, xor_optab, op0, t1,
 					   NULL_RTX, 0, OPTAB_WIDEN);
-			extra_cost = (shift_cost (speed, compute_mode, post_shift)
-				      + shift_cost (speed, compute_mode, size - 1)
-				      + 2 * add_cost (speed, compute_mode));
+			extra_cost = (shift_cost (speed, int_mode, post_shift)
+				      + shift_cost (speed, int_mode, size - 1)
+				      + 2 * add_cost (speed, int_mode));
 			t3 = expmed_mult_highpart
-			  (compute_mode, t2, gen_int_mode (ml, compute_mode),
+			  (int_mode, t2, gen_int_mode (ml, int_mode),
 			   NULL_RTX, 1, max_cost - extra_cost);
 			if (t3 != 0)
 			  {
 			    t4 = expand_shift
-			      (RSHIFT_EXPR, compute_mode, t3,
+			      (RSHIFT_EXPR, int_mode, t3,
 			       post_shift, NULL_RTX, 1);
-			    quotient = expand_binop (compute_mode, xor_optab,
+			    quotient = expand_binop (int_mode, xor_optab,
 						     t4, t1, tquotient, 0,
 						     OPTAB_WIDEN);
 			  }
@@ -4539,23 +4536,22 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 	    else
 	      {
 		rtx nsign, t1, t2, t3, t4;
-		t1 = force_operand (gen_rtx_PLUS (compute_mode,
+		t1 = force_operand (gen_rtx_PLUS (int_mode,
 						  op0, constm1_rtx), NULL_RTX);
-		t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
+		t2 = expand_binop (int_mode, ior_optab, op0, t1, NULL_RTX,
 				   0, OPTAB_WIDEN);
-		nsign = expand_shift (RSHIFT_EXPR, compute_mode, t2,
+		nsign = expand_shift (RSHIFT_EXPR, int_mode, t2,
 				      size - 1, NULL_RTX, 0);
-		t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
+		t3 = force_operand (gen_rtx_MINUS (int_mode, t1, nsign),
 				    NULL_RTX);
-		t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
+		t4 = expand_divmod (0, TRUNC_DIV_EXPR, int_mode, t3, op1,
 				    NULL_RTX, 0);
 		if (t4)
 		  {
 		    rtx t5;
-		    t5 = expand_unop (compute_mode, one_cmpl_optab, nsign,
+		    t5 = expand_unop (int_mode, one_cmpl_optab, nsign,
 				      NULL_RTX, 0);
-		    quotient = force_operand (gen_rtx_PLUS (compute_mode,
-							    t4, t5),
+		    quotient = force_operand (gen_rtx_PLUS (int_mode, t4, t5),
 					      tquotient);
 		  }
 	      }
@@ -4655,31 +4651,31 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 	  {
 	    if (op1_is_constant
 		&& EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
-		&& (size <= HOST_BITS_PER_WIDE_INT
+		&& (HWI_COMPUTABLE_MODE_P (compute_mode)
 		    || INTVAL (op1) >= 0))
 	      {
+		scalar_int_mode int_mode
+		  = as_a <scalar_int_mode> (compute_mode);
 		rtx t1, t2, t3;
 		unsigned HOST_WIDE_INT d = INTVAL (op1);
-		t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
+		t1 = expand_shift (RSHIFT_EXPR, int_mode, op0,
 				   floor_log2 (d), tquotient, 1);
-		t2 = expand_binop (compute_mode, and_optab, op0,
-				   gen_int_mode (d - 1, compute_mode),
+		t2 = expand_binop (int_mode, and_optab, op0,
+				   gen_int_mode (d - 1, int_mode),
 				   NULL_RTX, 1, OPTAB_LIB_WIDEN);
-		t3 = gen_reg_rtx (compute_mode);
-		t3 = emit_store_flag (t3, NE, t2, const0_rtx,
-				      compute_mode, 1, 1);
+		t3 = gen_reg_rtx (int_mode);
+		t3 = emit_store_flag (t3, NE, t2, const0_rtx, int_mode, 1, 1);
 		if (t3 == 0)
 		  {
 		    rtx_code_label *lab;
 		    lab = gen_label_rtx ();
-		    do_cmp_and_jump (t2, const0_rtx, EQ, compute_mode, lab);
+		    do_cmp_and_jump (t2, const0_rtx, EQ, int_mode, lab);
 		    expand_inc (t1, const1_rtx);
 		    emit_label (lab);
 		    quotient = t1;
 		  }
 		else
-		  quotient = force_operand (gen_rtx_PLUS (compute_mode,
-							  t1, t3),
+		  quotient = force_operand (gen_rtx_PLUS (int_mode, t1, t3),
 					    tquotient);
 		break;
 	      }
@@ -4869,8 +4865,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 	break;
 
       case EXACT_DIV_EXPR:
-	if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
+	if (op1_is_constant && HWI_COMPUTABLE_MODE_P (compute_mode))
 	  {
+	    scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode);
+	    int size = GET_MODE_BITSIZE (int_mode);
 	    HOST_WIDE_INT d = INTVAL (op1);
 	    unsigned HOST_WIDE_INT ml;
 	    int pre_shift;
@@ -4878,16 +4876,16 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
 
 	    pre_shift = ctz_or_zero (d);
 	    ml = invert_mod2n (d >> pre_shift, size);
-	    t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
+	    t1 = expand_shift (RSHIFT_EXPR, int_mode, op0,
 			       pre_shift, NULL_RTX, unsignedp);
-	    quotient = expand_mult (compute_mode, t1,
-				    gen_int_mode (ml, compute_mode),
+	    quotient = expand_mult (int_mode, t1,
+				    gen_int_mode (ml, int_mode),
 				    NULL_RTX, 1);
 
 	    insn = get_last_insn ();
 	    set_dst_reg_note (insn, REG_EQUAL,
 			      gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
-					      compute_mode, op0, op1),
+					      int_mode, op0, op1),
 			      quotient);
 	  }
 	break;
@@ -4896,60 +4894,63 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
       case ROUND_MOD_EXPR:
 	if (unsignedp)
 	  {
+	    scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode);
 	    rtx tem;
 	    rtx_code_label *label;
 	    label = gen_label_rtx ();
-	    quotient = gen_reg_rtx (compute_mode);
-	    remainder = gen_reg_rtx (compute_mode);
+	    quotient = gen_reg_rtx (int_mode);
+	    remainder = gen_reg_rtx (int_mode);
 	    if (expand_twoval_binop (udivmod_optab, op0, op1, quotient, remainder, 1) == 0)
 	      {
 		rtx tem;
-		quotient = expand_binop (compute_mode, udiv_optab, op0, op1,
+		quotient = expand_binop (int_mode, udiv_optab, op0, op1,
 					 quotient, 1, OPTAB_LIB_WIDEN);
-		tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 1);
-		remainder = expand_binop (compute_mode, sub_optab, op0, tem,
+		tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 1);
+		remainder = expand_binop (int_mode, sub_optab, op0, tem,
 					  remainder, 1, OPTAB_LIB_WIDEN);
 	      }
-	    tem = plus_constant (compute_mode, op1, -1);
-	    tem = expand_shift (RSHIFT_EXPR, compute_mode, tem, 1, NULL_RTX, 1);
-	    do_cmp_and_jump (remainder, tem, LEU, compute_mode, label);
+	    tem = plus_constant (int_mode, op1, -1);
+	    tem = expand_shift (RSHIFT_EXPR, int_mode, tem, 1, NULL_RTX, 1);
+	    do_cmp_and_jump (remainder, tem, LEU, int_mode, label);
 	    expand_inc (quotient, const1_rtx);
 	    expand_dec (remainder, op1);
 	    emit_label (label);
 	  }
 	else
 	  {
+	    scalar_int_mode int_mode = as_a <scalar_int_mode> (compute_mode);
+	    int size = GET_MODE_BITSIZE (int_mode);
 	    rtx abs_rem, abs_op1, tem, mask;
 	    rtx_code_label *label;
 	    label = gen_label_rtx ();
-	    quotient = gen_reg_rtx (compute_mode);
-	    remainder = gen_reg_rtx (compute_mode);
+	    quotient = gen_reg_rtx (int_mode);
+	    remainder = gen_reg_rtx (int_mode);
 	    if (expand_twoval_binop (sdivmod_optab, op0, op1, quotient, remainder, 0) == 0)
 	      {
 		rtx tem;
-		quotient = expand_binop (compute_mode, sdiv_optab, op0, op1,
+		quotient = expand_binop (int_mode, sdiv_optab, op0, op1,
 					 quotient, 0, OPTAB_LIB_WIDEN);
-		tem = expand_mult (compute_mode, quotient, op1, NULL_RTX, 0);
-		remainder = expand_binop (compute_mode, sub_optab, op0, tem,
+		tem = expand_mult (int_mode, quotient, op1, NULL_RTX, 0);
+		remainder = expand_binop (int_mode, sub_optab, op0, tem,
 					  remainder, 0, OPTAB_LIB_WIDEN);
 	      }
-	    abs_rem = expand_abs (compute_mode, remainder, NULL_RTX, 1, 0);
-	    abs_op1 = expand_abs (compute_mode, op1, NULL_RTX, 1, 0);
-	    tem = expand_shift (LSHIFT_EXPR, compute_mode, abs_rem,
+	    abs_rem = expand_abs (int_mode, remainder, NULL_RTX, 1, 0);
+	    abs_op1 = expand_abs (int_mode, op1, NULL_RTX, 1, 0);
+	    tem = expand_shift (LSHIFT_EXPR, int_mode, abs_rem,
 				1, NULL_RTX, 1);
-	    do_cmp_and_jump (tem, abs_op1, LTU, compute_mode, label);
-	    tem = expand_binop (compute_mode, xor_optab, op0, op1,
+	    do_cmp_and_jump (tem, abs_op1, LTU, int_mode, label);
+	    tem = expand_binop (int_mode, xor_optab, op0, op1,
 				NULL_RTX, 0, OPTAB_WIDEN);
-	    mask = expand_shift (RSHIFT_EXPR, compute_mode, tem,
+	    mask = expand_shift (RSHIFT_EXPR, int_mode, tem,
 				 size - 1, NULL_RTX, 0);
-	    tem = expand_binop (compute_mode, xor_optab, mask, const1_rtx,
+	    tem = expand_binop (int_mode, xor_optab, mask, const1_rtx,
 				NULL_RTX, 0, OPTAB_WIDEN);
-	    tem = expand_binop (compute_mode, sub_optab, tem, mask,
+	    tem = expand_binop (int_mode, sub_optab, tem, mask,
 				NULL_RTX, 0, OPTAB_WIDEN);
 	    expand_inc (quotient, tem);
-	    tem = expand_binop (compute_mode, xor_optab, mask, op1,
+	    tem = expand_binop (int_mode, xor_optab, mask, op1,
 				NULL_RTX, 0, OPTAB_WIDEN);
-	    tem = expand_binop (compute_mode, sub_optab, tem, mask,
+	    tem = expand_binop (int_mode, sub_optab, tem, mask,
 				NULL_RTX, 0, OPTAB_WIDEN);
 	    expand_dec (remainder, tem);
 	    emit_label (label);
@@ -5443,25 +5444,29 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
       && (normalizep || STORE_FLAG_VALUE == 1
 	  || val_signbit_p (int_mode, STORE_FLAG_VALUE)))
     {
+      scalar_int_mode int_target_mode;
       subtarget = target;
 
       if (!target)
-	target_mode = int_mode;
-
-      /* If the result is to be wider than OP0, it is best to convert it
-	 first.  If it is to be narrower, it is *incorrect* to convert it
-	 first.  */
-      else if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (int_mode))
+	int_target_mode = int_mode;
+      else
 	{
-	  op0 = convert_modes (target_mode, int_mode, op0, 0);
-	  mode = target_mode;
+	  /* If the result is to be wider than OP0, it is best to convert it
+	     first.  If it is to be narrower, it is *incorrect* to convert it
+	     first.  */
+	  int_target_mode = as_a <scalar_int_mode> (target_mode);
+	  if (GET_MODE_SIZE (int_target_mode) > GET_MODE_SIZE (int_mode))
+	    {
+	      op0 = convert_modes (int_target_mode, int_mode, op0, 0);
+	      int_mode = int_target_mode;
+	    }
 	}
 
-      if (target_mode != mode)
+      if (int_target_mode != int_mode)
 	subtarget = 0;
 
       if (code == GE)
-	op0 = expand_unop (mode, one_cmpl_optab, op0,
+	op0 = expand_unop (int_mode, one_cmpl_optab, op0,
 			   ((STORE_FLAG_VALUE == 1 || normalizep)
 			    ? 0 : subtarget), 0);
 
@@ -5469,12 +5474,12 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
 	/* If we are supposed to produce a 0/1 value, we want to do
 	   a logical shift from the sign bit to the low-order bit; for
 	   a -1/0 value, we do an arithmetic shift.  */
-	op0 = expand_shift (RSHIFT_EXPR, mode, op0,
-			    GET_MODE_BITSIZE (mode) - 1,
+	op0 = expand_shift (RSHIFT_EXPR, int_mode, op0,
+			    GET_MODE_BITSIZE (int_mode) - 1,
 			    subtarget, normalizep != -1);
 
-      if (mode != target_mode)
-	op0 = convert_modes (target_mode, mode, op0, 0);
+      if (int_mode != int_target_mode)
+	op0 = convert_modes (int_target_mode, int_mode, op0, 0);
 
       return op0;
     }
diff --git a/gcc/expr.c b/gcc/expr.c
index fb7709a..2e7bff5 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5236,8 +5236,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
 	{
 	  if (POINTER_TYPE_P (TREE_TYPE (to)))
 	    value = convert_memory_address_addr_space
-		      (GET_MODE (to_rtx), value,
-		       TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (to))));
+	      (as_a <scalar_int_mode> (GET_MODE (to_rtx)), value,
+	       TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (to))));
 
 	  emit_move_insn (to_rtx, value);
 	}
@@ -11068,7 +11068,8 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 }
 \f
 /* Subroutine of above: reduce EXP to the precision of TYPE (in the
-   signedness of TYPE), possibly returning the result in TARGET.  */
+   signedness of TYPE), possibly returning the result in TARGET.
+   TYPE is known to be a partial integer type.  */
 static rtx
 reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
 {
@@ -11084,18 +11085,17 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
     }
   else if (TYPE_UNSIGNED (type))
     {
-      machine_mode mode = GET_MODE (exp);
+      scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (exp));
       rtx mask = immed_wide_int_const
 	(wi::mask (prec, false, GET_MODE_PRECISION (mode)), mode);
       return expand_and (mode, exp, mask, target);
     }
   else
     {
-      int count = GET_MODE_PRECISION (GET_MODE (exp)) - prec;
-      exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp),
-			  exp, count, target, 0);
-      return expand_shift (RSHIFT_EXPR, GET_MODE (exp),
-			   exp, count, target, 0);
+      scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (exp));
+      int count = GET_MODE_PRECISION (mode) - prec;
+      exp = expand_shift (LSHIFT_EXPR, mode, exp, count, target, 0);
+      return expand_shift (RSHIFT_EXPR, mode, exp, count, target, 0);
     }
 }
 \f
diff --git a/gcc/function.c b/gcc/function.c
index 0829fbe..8a887e4 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5600,8 +5600,8 @@ expand_function_end (void)
       REG_FUNCTION_VALUE_P (outgoing) = 1;
 
       /* The address may be ptr_mode and OUTGOING may be Pmode.  */
-      value_address = convert_memory_address (GET_MODE (outgoing),
-					      value_address);
+      scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (outgoing));
+      value_address = convert_memory_address (mode, value_address);
 
       emit_move_insn (outgoing, value_address);
 
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 3b06dc2..61e844f 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -582,7 +582,8 @@ static void
 expand_arith_overflow_result_store (tree lhs, rtx target,
 				    machine_mode mode, rtx res)
 {
-  machine_mode tgtmode = GET_MODE_INNER (GET_MODE (target));
+  scalar_int_mode tgtmode
+    = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
   rtx lres = res;
   if (tgtmode != mode)
     {
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index 1dff2ff..b032534 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -436,7 +436,8 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
   counter_reg = XEXP (condition, 0);
   if (GET_CODE (counter_reg) == PLUS)
     counter_reg = XEXP (counter_reg, 0);
-  mode = GET_MODE (counter_reg);
+  /* These patterns must operate on integer counters.  */
+  mode = as_a <scalar_int_mode> (GET_MODE (counter_reg));
 
   increment_count = false;
   switch (GET_CODE (condition))
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 58f6e0c..724b03b 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -973,15 +973,15 @@ lto_type_for_mode (machine_mode mode, int unsigned_p)
   if (mode == TYPE_MODE (void_type_node))
     return void_type_node;
 
-  if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
-    return (unsigned_p
-	    ? make_unsigned_type (GET_MODE_PRECISION (mode))
-	    : make_signed_type (GET_MODE_PRECISION (mode)));
-
-  if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
-    return (unsigned_p
-	    ? make_unsigned_type (GET_MODE_PRECISION (mode))
-	    : make_signed_type (GET_MODE_PRECISION (mode)));
+  if (mode == TYPE_MODE (build_pointer_type (char_type_node))
+      || mode == TYPE_MODE (build_pointer_type (integer_type_node)))
+    {
+      unsigned int precision
+	= GET_MODE_PRECISION (as_a <scalar_int_mode> (mode));
+      return (unsigned_p
+	      ? make_unsigned_type (precision)
+	      : make_signed_type (precision));
+    }
 
   if (COMPLEX_MODE_P (mode))
     {
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 77ca419..054457a 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1230,8 +1230,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	     it back to the proper size to fit in the broadcast vector.  */
 	  machine_mode inner_mode = GET_MODE_INNER (mode);
 	  if (!CONST_INT_P (op1)
-	      && (GET_MODE_BITSIZE (inner_mode)
-		  < GET_MODE_BITSIZE (GET_MODE (op1))))
+	      && (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
+		  > GET_MODE_BITSIZE (inner_mode)))
 	    op1 = force_reg (inner_mode,
 			     simplify_gen_unary (TRUNCATE, inner_mode, op1,
 						 GET_MODE (op1)));
@@ -1376,11 +1376,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing)
     {
       unsigned HOST_WIDE_INT shift_mask, double_shift_mask;
-      machine_mode op1_mode;
+      scalar_int_mode op1_mode;
 
       double_shift_mask = targetm.shift_truncation_mask (int_mode);
       shift_mask = targetm.shift_truncation_mask (word_mode);
-      op1_mode = GET_MODE (op1) != VOIDmode ? GET_MODE (op1) : word_mode;
+      op1_mode = (GET_MODE (op1) != VOIDmode
+		  ? as_a <scalar_int_mode> (GET_MODE (op1))
+		  : word_mode);
 
       /* Apply the truncation to constant shifts.  */
       if (double_shift_mask > 0 && CONST_INT_P (op1))
@@ -3009,24 +3011,32 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 		 result.  Similarly for clrsb.  */
 	      if ((unoptab == clz_optab || unoptab == clrsb_optab)
 		  && temp != 0)
-		temp = expand_binop
-		  (wider_mode, sub_optab, temp,
-		   gen_int_mode (GET_MODE_PRECISION (wider_mode)
-				 - GET_MODE_PRECISION (mode),
-				 wider_mode),
-		   target, true, OPTAB_DIRECT);
+		{
+		  scalar_int_mode wider_int_mode
+		    = as_a <scalar_int_mode> (wider_mode);
+		  int_mode = as_a <scalar_int_mode> (mode);
+		  temp = expand_binop
+		    (wider_mode, sub_optab, temp,
+		     gen_int_mode (GET_MODE_PRECISION (wider_int_mode)
+				   - GET_MODE_PRECISION (int_mode),
+				   wider_int_mode),
+		     target, true, OPTAB_DIRECT);
+		}
 
 	      /* Likewise for bswap.  */
 	      if (unoptab == bswap_optab && temp != 0)
 		{
-		  gcc_assert (GET_MODE_PRECISION (wider_mode)
-			      == GET_MODE_BITSIZE (wider_mode)
-			      && GET_MODE_PRECISION (mode)
-				 == GET_MODE_BITSIZE (mode));
-
-		  temp = expand_shift (RSHIFT_EXPR, wider_mode, temp,
-				       GET_MODE_BITSIZE (wider_mode)
-				       - GET_MODE_BITSIZE (mode),
+		  scalar_int_mode wider_int_mode
+		    = as_a <scalar_int_mode> (wider_mode);
+		  int_mode = as_a <scalar_int_mode> (mode);
+		  gcc_assert (GET_MODE_PRECISION (wider_int_mode)
+			      == GET_MODE_BITSIZE (wider_int_mode)
+			      && GET_MODE_PRECISION (int_mode)
+				 == GET_MODE_BITSIZE (int_mode));
+
+		  temp = expand_shift (RSHIFT_EXPR, wider_int_mode, temp,
+				       GET_MODE_BITSIZE (wider_int_mode)
+				       - GET_MODE_BITSIZE (int_mode),
 				       NULL_RTX, true);
 		}
 
@@ -3253,7 +3263,7 @@ static rtx
 expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
 		        int bitpos, bool op0_is_abs)
 {
-  machine_mode imode;
+  scalar_int_mode imode;
   enum insn_code icode;
   rtx sign;
   rtx_code_label *label;
@@ -3266,7 +3276,7 @@ expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
   icode = optab_handler (signbit_optab, mode);
   if (icode != CODE_FOR_nothing)
     {
-      imode = insn_data[(int) icode].operand[0].mode;
+      imode = as_a <scalar_int_mode> (insn_data[(int) icode].operand[0].mode);
       sign = gen_reg_rtx (imode);
       emit_unop_insn (icode, sign, op1, UNKNOWN);
     }
@@ -3798,10 +3808,10 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
 	    continue;
 
 	  /* Must make sure the size fits the insn's mode.  */
-	  if ((CONST_INT_P (size)
-	       && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
-	      || (GET_MODE_BITSIZE (GET_MODE (size))
-		  > GET_MODE_BITSIZE (cmp_mode)))
+	  if (CONST_INT_P (size)
+	      ? INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode))
+	      : (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (size)))
+		 > GET_MODE_BITSIZE (cmp_mode)))
 	    continue;
 
 	  result_mode = insn_data[cmp_code].operand[0].mode;
@@ -6930,8 +6940,8 @@ maybe_legitimize_operand (enum insn_code icode, unsigned int opno,
       goto input;
 
     case EXPAND_ADDRESS:
-      gcc_assert (mode != VOIDmode);
-      op->value = convert_memory_address (mode, op->value);
+      op->value = convert_memory_address (as_a <scalar_int_mode> (mode),
+					  op->value);
       goto input;
 
     case EXPAND_INTEGER:
diff --git a/gcc/recog.c b/gcc/recog.c
index 3a17de2..317ec29 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1189,8 +1189,9 @@ const_scalar_int_operand (rtx op, machine_mode mode)
 
   if (mode != VOIDmode)
     {
-      int prec = GET_MODE_PRECISION (mode);
-      int bitsize = GET_MODE_BITSIZE (mode);
+      scalar_int_mode int_mode = as_a <scalar_int_mode> (mode);
+      int prec = GET_MODE_PRECISION (int_mode);
+      int bitsize = GET_MODE_BITSIZE (int_mode);
 
       if (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT > bitsize)
 	return 0;
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 129f69f..a7fb5cf 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5741,7 +5741,7 @@ get_address_mode (rtx mem)
   gcc_assert (MEM_P (mem));
   mode = GET_MODE (XEXP (mem, 0));
   if (mode != VOIDmode)
-    return mode;
+    return as_a <scalar_int_mode> (mode);
   return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
 }
 \f
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index ac7cb24..f4997bf 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -917,7 +917,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 {
   enum rtx_code reversed;
   rtx temp;
-  scalar_int_mode inner, int_mode, op0_mode;
+  scalar_int_mode inner, int_mode, op_mode, op0_mode;
 
   switch (code)
     {
@@ -1151,26 +1151,27 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	  && XEXP (op, 1) == const0_rtx
 	  && is_a <scalar_int_mode> (GET_MODE (XEXP (op, 0)), &inner))
 	{
+	  int_mode = as_a <scalar_int_mode> (mode);
 	  int isize = GET_MODE_PRECISION (inner);
 	  if (STORE_FLAG_VALUE == 1)
 	    {
 	      temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0),
 					  GEN_INT (isize - 1));
-	      if (mode == inner)
+	      if (int_mode == inner)
 		return temp;
-	      if (GET_MODE_PRECISION (mode) > isize)
-		return simplify_gen_unary (SIGN_EXTEND, mode, temp, inner);
-	      return simplify_gen_unary (TRUNCATE, mode, temp, inner);
+	      if (GET_MODE_PRECISION (int_mode) > isize)
+		return simplify_gen_unary (SIGN_EXTEND, int_mode, temp, inner);
+	      return simplify_gen_unary (TRUNCATE, int_mode, temp, inner);
 	    }
 	  else if (STORE_FLAG_VALUE == -1)
 	    {
 	      temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0),
 					  GEN_INT (isize - 1));
-	      if (mode == inner)
+	      if (int_mode == inner)
 		return temp;
-	      if (GET_MODE_PRECISION (mode) > isize)
-		return simplify_gen_unary (ZERO_EXTEND, mode, temp, inner);
-	      return simplify_gen_unary (TRUNCATE, mode, temp, inner);
+	      if (GET_MODE_PRECISION (int_mode) > isize)
+		return simplify_gen_unary (ZERO_EXTEND, int_mode, temp, inner);
+	      return simplify_gen_unary (TRUNCATE, int_mode, temp, inner);
 	    }
 	}
       break;
@@ -1490,12 +1491,13 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && CONST_INT_P (XEXP (op, 1))
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
-	  && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
+	  && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)),
+	      GET_MODE_BITSIZE (op_mode) > INTVAL (XEXP (op, 1))))
 	{
 	  scalar_int_mode tmode;
 	  gcc_assert (GET_MODE_BITSIZE (int_mode)
-		      > GET_MODE_BITSIZE (GET_MODE (op)));
-	  if (int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
+		      > GET_MODE_BITSIZE (op_mode));
+	  if (int_mode_for_size (GET_MODE_BITSIZE (op_mode)
 				 - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
 	    {
 	      rtx inner =
@@ -1607,10 +1609,11 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
 	  && is_a <scalar_int_mode> (mode, &int_mode)
 	  && CONST_INT_P (XEXP (op, 1))
 	  && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
-	  && GET_MODE_PRECISION (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
+	  && (op_mode = as_a <scalar_int_mode> (GET_MODE (op)),
+	      GET_MODE_PRECISION (op_mode) > INTVAL (XEXP (op, 1))))
 	{
 	  scalar_int_mode tmode;
-	  if (int_mode_for_size (GET_MODE_PRECISION (GET_MODE (op))
+	  if (int_mode_for_size (GET_MODE_PRECISION (op_mode)
 				 - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
 	    {
 	      rtx inner =
@@ -5400,10 +5403,10 @@ simplify_cond_clz_ctz (rtx x, rtx_code cmp_code, rtx true_val, rtx false_val)
     return NULL_RTX;
 
   HOST_WIDE_INT op_val;
-  if (((op_code == CLZ
-	&& CLZ_DEFINED_VALUE_AT_ZERO (GET_MODE (on_nonzero), op_val))
-      || (op_code == CTZ
-	  && CTZ_DEFINED_VALUE_AT_ZERO (GET_MODE (on_nonzero), op_val)))
+  scalar_int_mode mode ATTRIBUTE_UNUSED
+    = as_a <scalar_int_mode> (GET_MODE (XEXP (on_nonzero, 0)));
+  if (((op_code == CLZ && CLZ_DEFINED_VALUE_AT_ZERO (mode, op_val))
+       || (op_code == CTZ && CTZ_DEFINED_VALUE_AT_ZERO (mode, op_val)))
       && op_val == INTVAL (on_zero))
     return on_nonzero;
 
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 0c8bc64..df60852 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -621,7 +621,9 @@ get_nl_goto_field (struct nesting_info *info)
       else
 	type = lang_hooks.types.type_for_mode (Pmode, 1);
 
-      size = GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
+      scalar_int_mode mode
+	= as_a <scalar_int_mode> (STACK_SAVEAREA_MODE (SAVE_NONLOCAL));
+      size = GET_MODE_SIZE (mode);
       size = size / GET_MODE_SIZE (Pmode);
       size = size + 1;
 
diff --git a/gcc/tree.c b/gcc/tree.c
index b58f503..d7bbcb3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10936,6 +10936,7 @@ tree
 build_vector_type_for_mode (tree innertype, machine_mode mode)
 {
   int nunits;
+  unsigned int bitsize;
 
   switch (GET_MODE_CLASS (mode))
     {
@@ -10950,11 +10951,9 @@ build_vector_type_for_mode (tree innertype, machine_mode mode)
 
     case MODE_INT:
       /* Check that there are no leftover bits.  */
-      gcc_assert (GET_MODE_BITSIZE (mode)
-		  % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0);
-
-      nunits = GET_MODE_BITSIZE (mode)
-	       / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
+      bitsize = GET_MODE_BITSIZE (as_a <scalar_int_mode> (mode));
+      gcc_assert (bitsize % TREE_INT_CST_LOW (TYPE_SIZE (innertype)) == 0);
+      nunits = bitsize / TREE_INT_CST_LOW (TYPE_SIZE (innertype));
       break;
 
     default:
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 31f7a31..bec9195 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -991,7 +991,8 @@ use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
       /* Ensure shift amount is not wider than mode.  */
       if (GET_MODE (op1) == VOIDmode)
 	op1 = lowpart_subreg (mode, op1, wmode);
-      else if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (op1)))
+      else if (GET_MODE_PRECISION (mode)
+	       < GET_MODE_PRECISION (as_a <scalar_int_mode> (GET_MODE (op1))))
 	op1 = lowpart_subreg (mode, op1, GET_MODE (op1));
       return simplify_gen_binary (ASHIFT, mode, op0, op1);
     default:

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [36/67] Use scalar_int_mode in the RTL iv routines
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (35 preceding siblings ...)
  2016-12-09 13:16 ` [35/67] Add uses of as_a <scalar_int_mode> Richard Sandiford
@ 2016-12-09 13:16 ` Richard Sandiford
  2016-12-09 13:17 ` [37/67] Use scalar_int_mode when emitting cstores Richard Sandiford
                   ` (32 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:16 UTC (permalink / raw)
  To: gcc-patches

This patch changes the iv modes in rtx_iv from machine_mode
to scalar_int_mode.  It also passes the mode of the iv down
to subroutines; this avoids the previous situation in which
the mode information was sometimes lost and had to be added
by the caller on return.

Some routines already took a mode argument, but the patch
tries to standardise on passing it immediately before the
argument it describes.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* cfgloop.h (rtx_iv): Change type of extend_mode and mode to
	scalar_int_mode.
	(niter_desc): Likewise mode.
	(iv_analyze): Add a mode parameter.
	(biv_p): Likewise.
	(iv_analyze_expr): Pass the mode paraeter before the rtx it describes
	and change its type to scalar_int_mode.
	* loop-iv.c: Update commentary at head of file.
	(iv_constant): Pass the mode paraeter before the rtx it describes
	and change its type to scalar_int_mode.  Remove VOIDmode handling.
	(iv_subreg): Change the type of the mode parameter to scalar_int_mode.
	(iv_extend): Likewise.
	(shorten_into_mode): Likewise.
	(iv_add): Use scalar_int_mode.
	(iv_mult): Likewise.
	(iv_shift): Likewise.
	(canonicalize_iv_subregs): Likewise.
	(get_biv_step_1): Pass the outer_mode parameter before the rx
	it describes and change its to scalar_int_mode.   Also change
	the type of the returned inner_mode to scalar_int_mode.
	(get_biv_step): Likewise, turning outer_mode from a pointer
	into a direct parameter.  Update call to get_biv_step_1.
	(iv_analyze_biv): Add an outer_mode parameter.  Update calls to
	iv_constant and get_biv_step.
	(iv_analyze_expr): Pass the mode paraeter before the rtx it describes
	and change its type to scalar_int_mode.  Don't initialise iv->mode
	to VOIDmode and remove later checks for it still being VOIDmode.
	Update calls to iv_analyze_op and iv_analyze_expr.  Check
	is_a <scalar_int_mode> when changing the mode under consideration.
	(iv_analyze_def): Ignore registers that don't have a scalar_int_mode.
	Update call to iv_analyze_expr.
	(iv_analyze_op): Add a mode parameter.  Reject subregs whose
	inner register is not also a scalar_int_mode.  Update call to
	iv_analyze_biv.
	(iv_analyze): Add a mode parameter.  Update call to iv_analyze_op.
	(biv_p): Add a mode parameter.  Update call to iv_analyze_biv.
	(iv_number_of_iterations): Use is_a <scalar_int_mode> instead of
	separate mode class checks.  Update calls to iv_analyze.  Remove
	fix-up of VOIDmodes after iv_analyze_biv.
	* loop-unroll.c (analyze_iv_to_split_insn): Reject registers that
	don't have a scalar_int_mode.  Update call to biv_p.

diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 0448a61..84809c9 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -410,10 +410,10 @@ struct rtx_iv
   rtx delta, mult;
 
   /* The mode it is extended to.  */
-  machine_mode extend_mode;
+  scalar_int_mode extend_mode;
 
   /* The mode the variable iterates in.  */
-  machine_mode mode;
+  scalar_int_mode mode;
 
   /* Whether the first iteration needs to be handled specially.  */
   unsigned first_special : 1;
@@ -454,19 +454,19 @@ struct GTY(()) niter_desc
   bool signed_p;
 
   /* The mode in that niter_expr should be computed.  */
-  machine_mode mode;
+  scalar_int_mode mode;
 
   /* The number of iterations of the loop.  */
   rtx niter_expr;
 };
 
 extern void iv_analysis_loop_init (struct loop *);
-extern bool iv_analyze (rtx_insn *, rtx, struct rtx_iv *);
+extern bool iv_analyze (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *);
 extern bool iv_analyze_result (rtx_insn *, rtx, struct rtx_iv *);
-extern bool iv_analyze_expr (rtx_insn *, rtx, machine_mode,
+extern bool iv_analyze_expr (rtx_insn *, scalar_int_mode, rtx,
 			     struct rtx_iv *);
 extern rtx get_iv_value (struct rtx_iv *, rtx);
-extern bool biv_p (rtx_insn *, rtx);
+extern bool biv_p (rtx_insn *, scalar_int_mode, rtx);
 extern void find_simple_exit (struct loop *, struct niter_desc *);
 extern void iv_analysis_done (void);
 
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index f684da2..662b7a1 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -35,16 +35,17 @@ along with GCC; see the file COPYING3.  If not see
 
    The available functions are:
 
-   iv_analyze (insn, reg, iv): Stores the description of the induction variable
-     corresponding to the use of register REG in INSN to IV.  Returns true if
-     REG is an induction variable in INSN. false otherwise.
-     If use of REG is not found in INSN, following insns are scanned (so that
-     we may call this function on insn returned by get_condition).
+   iv_analyze (insn, mode, reg, iv): Stores the description of the induction
+     variable corresponding to the use of register REG (of mode MODE) in INSN
+     to IV.  Returns true if REG is an induction variable in INSN. false
+     otherwise.  If use of REG is not found in INSN, following insns are
+     scanned (so that we may call this function on insn returned by
+     get_condition).
    iv_analyze_result (insn, def, iv):  Stores to IV the description of the iv
      corresponding to DEF, which is a register defined in INSN.
-   iv_analyze_expr (insn, rhs, mode, iv):  Stores to IV the description of iv
+   iv_analyze_expr (insn, mode, expr, iv):  Stores to IV the description of iv
      corresponding to expression EXPR evaluated at INSN.  All registers used bu
-     EXPR must also be used in INSN.
+     EXPR must also be used in INSN.  MODE is the mode of EXPR.
 */
 
 #include "config.h"
@@ -133,7 +134,7 @@ biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r)
 
 static hash_table<biv_entry_hasher> *bivs;
 
-static bool iv_analyze_op (rtx_insn *, rtx, struct rtx_iv *);
+static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *);
 
 /* Return the RTX code corresponding to the IV extend code EXTEND.  */
 static inline enum rtx_code
@@ -383,11 +384,8 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def)
    consistency with other iv manipulation functions that may fail).  */
 
 static bool
-iv_constant (struct rtx_iv *iv, rtx cst, machine_mode mode)
+iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst)
 {
-  if (mode == VOIDmode)
-    mode = GET_MODE (cst);
-
   iv->mode = mode;
   iv->base = cst;
   iv->step = const0_rtx;
@@ -403,7 +401,7 @@ iv_constant (struct rtx_iv *iv, rtx cst, machine_mode mode)
 /* Evaluates application of subreg to MODE on IV.  */
 
 static bool
-iv_subreg (struct rtx_iv *iv, machine_mode mode)
+iv_subreg (struct rtx_iv *iv, scalar_int_mode mode)
 {
   /* If iv is invariant, just calculate the new value.  */
   if (iv->step == const0_rtx
@@ -445,7 +443,7 @@ iv_subreg (struct rtx_iv *iv, machine_mode mode)
 /* Evaluates application of EXTEND to MODE on IV.  */
 
 static bool
-iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, machine_mode mode)
+iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode)
 {
   /* If iv is invariant, just calculate the new value.  */
   if (iv->step == const0_rtx
@@ -508,7 +506,7 @@ iv_neg (struct rtx_iv *iv)
 static bool
 iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
 {
-  machine_mode mode;
+  scalar_int_mode mode;
   rtx arg;
 
   /* Extend the constant to extend_mode of the other operand if necessary.  */
@@ -578,7 +576,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
 static bool
 iv_mult (struct rtx_iv *iv, rtx mby)
 {
-  machine_mode mode = iv->extend_mode;
+  scalar_int_mode mode = iv->extend_mode;
 
   if (GET_MODE (mby) != VOIDmode
       && GET_MODE (mby) != mode)
@@ -603,7 +601,7 @@ iv_mult (struct rtx_iv *iv, rtx mby)
 static bool
 iv_shift (struct rtx_iv *iv, rtx mby)
 {
-  machine_mode mode = iv->extend_mode;
+  scalar_int_mode mode = iv->extend_mode;
 
   if (GET_MODE (mby) != VOIDmode
       && GET_MODE (mby) != mode)
@@ -628,9 +626,9 @@ iv_shift (struct rtx_iv *iv, rtx mby)
    at get_biv_step.  */
 
 static bool
-get_biv_step_1 (df_ref def, rtx reg,
-		rtx *inner_step, machine_mode *inner_mode,
-		enum iv_extend_code *extend, machine_mode outer_mode,
+get_biv_step_1 (df_ref def, scalar_int_mode outer_mode, rtx reg,
+		rtx *inner_step, scalar_int_mode *inner_mode,
+		enum iv_extend_code *extend,
 		rtx *outer_step)
 {
   rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
@@ -732,8 +730,8 @@ get_biv_step_1 (df_ref def, rtx reg,
       *inner_mode = outer_mode;
       *outer_step = const0_rtx;
     }
-  else if (!get_biv_step_1 (next_def, reg,
-			    inner_step, inner_mode, extend, outer_mode,
+  else if (!get_biv_step_1 (next_def, outer_mode, reg,
+			    inner_step, inner_mode, extend,
 			    outer_step))
     return false;
 
@@ -793,19 +791,17 @@ get_biv_step_1 (df_ref def, rtx reg,
    LAST_DEF is the definition of REG that dominates loop latch.  */
 
 static bool
-get_biv_step (df_ref last_def, rtx reg, rtx *inner_step,
-	      machine_mode *inner_mode, enum iv_extend_code *extend,
-	      machine_mode *outer_mode, rtx *outer_step)
+get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg,
+	      rtx *inner_step, scalar_int_mode *inner_mode,
+	      enum iv_extend_code *extend, rtx *outer_step)
 {
-  *outer_mode = GET_MODE (reg);
-
-  if (!get_biv_step_1 (last_def, reg,
-		       inner_step, inner_mode, extend, *outer_mode,
+  if (!get_biv_step_1 (last_def, outer_mode, reg,
+		       inner_step, inner_mode, extend,
 		       outer_step))
     return false;
 
-  gcc_assert ((*inner_mode == *outer_mode) != (*extend != IV_UNKNOWN_EXTEND));
-  gcc_assert (*inner_mode != *outer_mode || *outer_step == const0_rtx);
+  gcc_assert ((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND));
+  gcc_assert (*inner_mode != outer_mode || *outer_step == const0_rtx);
 
   return true;
 }
@@ -850,13 +846,13 @@ record_biv (rtx def, struct rtx_iv *iv)
 }
 
 /* Determines whether DEF is a biv and if so, stores its description
-   to *IV.  */
+   to *IV.  OUTER_MODE is the mode of DEF.  */
 
 static bool
-iv_analyze_biv (rtx def, struct rtx_iv *iv)
+iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv)
 {
   rtx inner_step, outer_step;
-  machine_mode inner_mode, outer_mode;
+  scalar_int_mode inner_mode;
   enum iv_extend_code extend;
   df_ref last_def;
 
@@ -872,7 +868,7 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv)
       if (!CONSTANT_P (def))
 	return false;
 
-      return iv_constant (iv, def, VOIDmode);
+      return iv_constant (iv, outer_mode, def);
     }
 
   if (!latch_dominating_def (def, &last_def))
@@ -883,7 +879,7 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv)
     }
 
   if (!last_def)
-    return iv_constant (iv, def, VOIDmode);
+    return iv_constant (iv, outer_mode, def);
 
   if (analyzed_for_bivness_p (def, iv))
     {
@@ -892,8 +888,8 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv)
       return iv->base != NULL_RTX;
     }
 
-  if (!get_biv_step (last_def, def, &inner_step, &inner_mode, &extend,
-		     &outer_mode, &outer_step))
+  if (!get_biv_step (last_def, outer_mode, def, &inner_step, &inner_mode,
+		     &extend, &outer_step))
     {
       iv->base = NULL_RTX;
       goto end;
@@ -930,16 +926,15 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv)
    The mode of the induction variable is MODE.  */
 
 bool
-iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
+iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs,
 		 struct rtx_iv *iv)
 {
   rtx mby = NULL_RTX;
   rtx op0 = NULL_RTX, op1 = NULL_RTX;
   struct rtx_iv iv0, iv1;
   enum rtx_code code = GET_CODE (rhs);
-  machine_mode omode = mode;
+  scalar_int_mode omode = mode;
 
-  iv->mode = VOIDmode;
   iv->base = NULL_RTX;
   iv->step = NULL_RTX;
 
@@ -948,18 +943,7 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
   if (CONSTANT_P (rhs)
       || REG_P (rhs)
       || code == SUBREG)
-    {
-      if (!iv_analyze_op (insn, rhs, iv))
-	return false;
-
-      if (iv->mode == VOIDmode)
-	{
-	  iv->mode = mode;
-	  iv->extend_mode = mode;
-	}
-
-      return true;
-    }
+    return iv_analyze_op (insn, mode, rhs, iv);
 
   switch (code)
     {
@@ -971,7 +955,9 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
     case ZERO_EXTEND:
     case NEG:
       op0 = XEXP (rhs, 0);
-      omode = GET_MODE (op0);
+      /* We don't know how many bits there are in a sign-extended constant.  */
+      if (!is_a <scalar_int_mode> (GET_MODE (op0), &omode))
+	return false;
       break;
 
     case PLUS:
@@ -1001,11 +987,11 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
     }
 
   if (op0
-      && !iv_analyze_expr (insn, op0, omode, &iv0))
+      && !iv_analyze_expr (insn, omode, op0, &iv0))
     return false;
 
   if (op1
-      && !iv_analyze_expr (insn, op1, omode, &iv1))
+      && !iv_analyze_expr (insn, omode, op1, &iv1))
     return false;
 
   switch (code)
@@ -1075,11 +1061,11 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
       return iv->base != NULL_RTX;
     }
 
-  iv->mode = VOIDmode;
   iv->base = NULL_RTX;
   iv->step = NULL_RTX;
 
-  if (!REG_P (reg))
+  scalar_int_mode mode;
+  if (!REG_P (reg) || !is_a <scalar_int_mode> (GET_MODE (reg), &mode))
     return false;
 
   set = single_set (insn);
@@ -1096,7 +1082,7 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
   else
     rhs = SET_SRC (set);
 
-  iv_analyze_expr (insn, rhs, GET_MODE (reg), iv);
+  iv_analyze_expr (insn, mode, rhs, iv);
   record_iv (def, iv);
 
   if (dump_file)
@@ -1112,10 +1098,11 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
   return iv->base != NULL_RTX;
 }
 
-/* Analyzes operand OP of INSN and stores the result to *IV.  */
+/* Analyzes operand OP of INSN and stores the result to *IV.  MODE is the
+   mode of OP.  */
 
 static bool
-iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv)
+iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv)
 {
   df_ref def = NULL;
   enum iv_grd_result res;
@@ -1132,13 +1119,15 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv)
     res = GRD_INVARIANT;
   else if (GET_CODE (op) == SUBREG)
     {
-      if (!subreg_lowpart_p (op))
+      scalar_int_mode inner_mode;
+      if (!subreg_lowpart_p (op)
+	  || !is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &inner_mode))
 	return false;
 
-      if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
+      if (!iv_analyze_op (insn, inner_mode, SUBREG_REG (op), iv))
 	return false;
 
-      return iv_subreg (iv, GET_MODE (op));
+      return iv_subreg (iv, mode);
     }
   else
     {
@@ -1153,7 +1142,7 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv)
 
   if (res == GRD_INVARIANT)
     {
-      iv_constant (iv, op, VOIDmode);
+      iv_constant (iv, mode, op);
 
       if (dump_file)
 	{
@@ -1165,15 +1154,16 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv)
     }
 
   if (res == GRD_MAYBE_BIV)
-    return iv_analyze_biv (op, iv);
+    return iv_analyze_biv (mode, op, iv);
 
   return iv_analyze_def (def, iv);
 }
 
-/* Analyzes value VAL at INSN and stores the result to *IV.  */
+/* Analyzes value VAL at INSN and stores the result to *IV.  MODE is the
+   mode of VAL.  */
 
 bool
-iv_analyze (rtx_insn *insn, rtx val, struct rtx_iv *iv)
+iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv)
 {
   rtx reg;
 
@@ -1192,7 +1182,7 @@ iv_analyze (rtx_insn *insn, rtx val, struct rtx_iv *iv)
 	insn = NEXT_INSN (insn);
     }
 
-  return iv_analyze_op (insn, val, iv);
+  return iv_analyze_op (insn, mode, val, iv);
 }
 
 /* Analyzes definition of DEF in INSN and stores the result to IV.  */
@@ -1210,11 +1200,13 @@ iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv)
 }
 
 /* Checks whether definition of register REG in INSN is a basic induction
-   variable.  IV analysis must have been initialized (via a call to
+   variable.  MODE is the mode of REG.
+
+   IV analysis must have been initialized (via a call to
    iv_analysis_loop_init) for this function to produce a result.  */
 
 bool
-biv_p (rtx_insn *insn, rtx reg)
+biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg)
 {
   struct rtx_iv iv;
   df_ref def, last_def;
@@ -1229,7 +1221,7 @@ biv_p (rtx_insn *insn, rtx reg)
   if (last_def != def)
     return false;
 
-  if (!iv_analyze_biv (reg, &iv))
+  if (!iv_analyze_biv (mode, reg, &iv))
     return false;
 
   return iv.step != const0_rtx;
@@ -2078,7 +2070,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
    is SIGNED_P to DESC.  */
 
 static void
-shorten_into_mode (struct rtx_iv *iv, machine_mode mode,
+shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode,
 		   enum rtx_code cond, bool signed_p, struct niter_desc *desc)
 {
   rtx mmin, mmax, cond_over, cond_under;
@@ -2140,7 +2132,7 @@ static bool
 canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
 			 enum rtx_code cond, struct niter_desc *desc)
 {
-  machine_mode comp_mode;
+  scalar_int_mode comp_mode;
   bool signed_p;
 
   /* If the ivs behave specially in the first iteration, or are
@@ -2318,7 +2310,8 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
   struct rtx_iv iv0, iv1;
   rtx assumption, may_not_xform;
   enum rtx_code cond;
-  machine_mode mode, comp_mode;
+  machine_mode nonvoid_mode;
+  scalar_int_mode comp_mode;
   rtx mmin, mmax, mode_mmin, mode_mmax;
   uint64_t s, size, d, inv, max, up, down;
   int64_t inc, step_val;
@@ -2343,28 +2336,24 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
   cond = GET_CODE (condition);
   gcc_assert (COMPARISON_P (condition));
 
-  mode = GET_MODE (XEXP (condition, 0));
-  if (mode == VOIDmode)
-    mode = GET_MODE (XEXP (condition, 1));
+  nonvoid_mode = GET_MODE (XEXP (condition, 0));
+  if (nonvoid_mode == VOIDmode)
+    nonvoid_mode = GET_MODE (XEXP (condition, 1));
   /* The constant comparisons should be folded.  */
-  gcc_assert (mode != VOIDmode);
+  gcc_assert (nonvoid_mode != VOIDmode);
 
   /* We only handle integers or pointers.  */
-  if (GET_MODE_CLASS (mode) != MODE_INT
-      && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
+  scalar_int_mode mode;
+  if (!is_a <scalar_int_mode> (nonvoid_mode, &mode))
     goto fail;
 
   op0 = XEXP (condition, 0);
-  if (!iv_analyze (insn, op0, &iv0))
+  if (!iv_analyze (insn, mode, op0, &iv0))
     goto fail;
-  if (iv0.extend_mode == VOIDmode)
-    iv0.mode = iv0.extend_mode = mode;
 
   op1 = XEXP (condition, 1);
-  if (!iv_analyze (insn, op1, &iv1))
+  if (!iv_analyze (insn, mode, op1, &iv1))
     goto fail;
-  if (iv1.extend_mode == VOIDmode)
-    iv1.mode = iv1.extend_mode = mode;
 
   if (GET_MODE_BITSIZE (iv0.extend_mode) > HOST_BITS_PER_WIDE_INT
       || GET_MODE_BITSIZE (iv1.extend_mode) > HOST_BITS_PER_WIDE_INT)
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 760445e..123398a3 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -1505,6 +1505,7 @@ analyze_iv_to_split_insn (rtx_insn *insn)
   rtx set, dest;
   struct rtx_iv iv;
   struct iv_to_split *ivts;
+  scalar_int_mode mode;
   bool ok;
 
   /* For now we just split the basic induction variables.  Later this may be
@@ -1514,10 +1515,10 @@ analyze_iv_to_split_insn (rtx_insn *insn)
     return NULL;
 
   dest = SET_DEST (set);
-  if (!REG_P (dest))
+  if (!REG_P (dest) || !is_a <scalar_int_mode> (GET_MODE (dest), &mode))
     return NULL;
 
-  if (!biv_p (insn, dest))
+  if (!biv_p (insn, mode, dest))
     return NULL;
 
   ok = iv_analyze_result (insn, dest, &iv);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [37/67] Use scalar_int_mode when emitting cstores
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (36 preceding siblings ...)
  2016-12-09 13:16 ` [36/67] Use scalar_int_mode in the RTL iv routines Richard Sandiford
@ 2016-12-09 13:17 ` Richard Sandiford
  2016-12-09 13:17 ` [38/67] Move SCALAR_INT_MODE_P out of strict_volatile_bitfield_p Richard Sandiford
                   ` (31 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:17 UTC (permalink / raw)
  To: gcc-patches

cstore patterns always have a scalar integer result, which has the
value 0 for "false" and STORE_FLAG_VALUE for "true".  This patch
makes that explicit using scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* target.def (cstore_mode): Return a scalar_int_mode.
	* doc/tm.texi: Regenerate.
	* config/sparc/sparc.c (sparc_cstore_mode): Return a scalar_int_mode.
	* targhooks.h (default_cstore_mode): Likewise.
	* targhooks.c (default_cstore_mode): Likewise, using a forced
	conversion.
	* expmed.c (emit_cstore): Expect the target of the cstore to be
	a scalar_int_mode.

diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 28bb0c5..e152d62 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -646,7 +646,7 @@ static void sparc_print_operand_address (FILE *, machine_mode, rtx);
 static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
 					   machine_mode,
 					   secondary_reload_info *);
-static machine_mode sparc_cstore_mode (enum insn_code icode);
+static scalar_int_mode sparc_cstore_mode (enum insn_code icode);
 static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
 static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
 static unsigned int sparc_min_arithmetic_precision (void);
@@ -12788,7 +12788,7 @@ sparc_modes_tieable_p (machine_mode mode1, machine_mode mode2)
 
 /* Implement TARGET_CSTORE_MODE.  */
 
-static machine_mode
+static scalar_int_mode
 sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED)
 {
   return (TARGET_ARCH64 ? DImode : SImode);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4993817..05f0719 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2900,7 +2900,7 @@ This hook defines a class of registers which could be used for spilling  pseudos
 This hook should return @code{true} if given class of registers should  be an allocno class in any way.  Usually RA uses only one register  class from all classes containing the same register set.  In some  complicated cases, you need to have two or more such classes as  allocno ones for RA correct work.  Not defining this hook is  equivalent to returning @code{false} for all inputs.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_CSTORE_MODE (enum insn_code @var{icode})
+@deftypefn {Target Hook} scalar_int_mode TARGET_CSTORE_MODE (enum insn_code @var{icode})
 This hook defines the machine mode to use for the boolean result of  conditional store patterns.  The ICODE argument is the instruction code  for the cstore being performed.  Not definiting this hook is the same  as accepting the mode encoded into operand 0 of the cstore expander  patterns.
 @end deftypefn
 
diff --git a/gcc/expmed.c b/gcc/expmed.c
index dea4923..3939c3d 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -5228,7 +5228,8 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
   struct expand_operand ops[4];
   rtx op0, comparison, subtarget;
   rtx_insn *last;
-  machine_mode result_mode = targetm.cstore_mode (icode);
+  scalar_int_mode result_mode = targetm.cstore_mode (icode);
+  scalar_int_mode int_target_mode;
 
   last = get_last_insn ();
   x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp);
@@ -5240,9 +5241,11 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
     }
 
   if (target_mode == VOIDmode)
-    target_mode = result_mode;
+    int_target_mode = result_mode;
+  else
+    int_target_mode = as_a <scalar_int_mode> (target_mode);
   if (!target)
-    target = gen_reg_rtx (target_mode);
+    target = gen_reg_rtx (int_target_mode);
 
   comparison = gen_rtx_fmt_ee (code, result_mode, x, y);
 
@@ -5258,20 +5261,20 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
   subtarget = ops[0].value;
 
   /* If we are converting to a wider mode, first convert to
-     TARGET_MODE, then normalize.  This produces better combining
+     INT_TARGET_MODE, then normalize.  This produces better combining
      opportunities on machines that have a SIGN_EXTRACT when we are
      testing a single bit.  This mostly benefits the 68k.
 
      If STORE_FLAG_VALUE does not have the sign bit set when
      interpreted in MODE, we can do this conversion as unsigned, which
      is usually more efficient.  */
-  if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (result_mode))
+  if (GET_MODE_SIZE (int_target_mode) > GET_MODE_SIZE (result_mode))
     {
       convert_move (target, subtarget,
 		    val_signbit_known_clear_p (result_mode,
 					       STORE_FLAG_VALUE));
       op0 = target;
-      result_mode = target_mode;
+      result_mode = int_target_mode;
     }
   else
     op0 = subtarget;
@@ -5307,7 +5310,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
     }
 
   /* If we were converting to a smaller mode, do the conversion now.  */
-  if (target_mode != result_mode)
+  if (int_target_mode != result_mode)
     {
       convert_move (target, op0, 0);
       return target;
diff --git a/gcc/target.def b/gcc/target.def
index fa765de..c450a1d 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5063,7 +5063,7 @@ DEFHOOK
   for the cstore being performed.  Not definiting this hook is the same\
   as accepting the mode encoded into operand 0 of the cstore expander\
   patterns.",
-  machine_mode, (enum insn_code icode),
+  scalar_int_mode, (enum insn_code icode),
   default_cstore_mode)
 
 /* This target hook allows the backend to compute the register pressure
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 4f7744f..8951bc3 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1838,10 +1838,10 @@ default_pch_valid_p (const void *data_p, size_t len)
 
 /* Default version of cstore_mode.  */
 
-machine_mode
+scalar_int_mode
 default_cstore_mode (enum insn_code icode)
 {
-  return insn_data[(int) icode].operand[0].mode;
+  return as_a <scalar_int_mode> (insn_data[(int) icode].operand[0].mode);
 }
 
 /* Default version of member_type_forces_blk.  */
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 1a56ec7..151c0f0 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -229,7 +229,7 @@ extern const char *default_pch_valid_p (const void *, size_t);
 
 extern void default_asm_output_ident_directive (const char*);
 
-extern machine_mode default_cstore_mode (enum insn_code);
+extern scalar_int_mode default_cstore_mode (enum insn_code);
 extern bool default_member_type_forces_blk (const_tree, machine_mode);
 extern void default_atomic_assign_expand_fenv (tree *, tree *, tree *);
 extern tree build_va_arg_indirect_ref (tree);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [38/67] Move SCALAR_INT_MODE_P out of strict_volatile_bitfield_p
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (37 preceding siblings ...)
  2016-12-09 13:17 ` [37/67] Use scalar_int_mode when emitting cstores Richard Sandiford
@ 2016-12-09 13:17 ` Richard Sandiford
  2016-12-09 13:18 ` [39/67] Two changes to the get_best_mode interface Richard Sandiford
                   ` (30 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:17 UTC (permalink / raw)
  To: gcc-patches

strict_volatile_bitfield_p returns false for any mode that isn't
a scalar integer.  This patch moves the check to the caller and
makes strict_volatile_bitfield_p take the mode as a scalar_int_mode.
The handling of a true return can then also use the mode as a
scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* expmed.c (strict_volatile_bitfield_p): Change the type of fieldmode
	to scalar_int_mode.  Remove check for SCALAR_INT_MODE_P.
	(store_bit_field): Check is_a <scalar_int_mode> before calling
	strict_volatile_bitfield_p.
	(extract_bit_field): Likewise.

diff --git a/gcc/expmed.c b/gcc/expmed.c
index 3939c3d..f9cdcda 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -514,7 +514,7 @@ lowpart_bit_field_p (unsigned HOST_WIDE_INT bitnum,
 static bool
 strict_volatile_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize,
 			    unsigned HOST_WIDE_INT bitnum,
-			    machine_mode fieldmode,
+			    scalar_int_mode fieldmode,
 			    unsigned HOST_WIDE_INT bitregion_start,
 			    unsigned HOST_WIDE_INT bitregion_end)
 {
@@ -527,11 +527,6 @@ strict_volatile_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize,
       || flag_strict_volatile_bitfields <= 0)
     return false;
 
-  /* Non-integral modes likely only happen with packed structures.
-     Punt.  */
-  if (!SCALAR_INT_MODE_P (fieldmode))
-    return false;
-
   /* The bit size must not be larger than the field mode, and
      the field mode must not be larger than a word.  */
   if (bitsize > modesize || modesize > BITS_PER_WORD)
@@ -1050,19 +1045,21 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 		 rtx value, bool reverse)
 {
   /* Handle -fstrict-volatile-bitfields in the cases where it applies.  */
-  if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, fieldmode,
-				  bitregion_start, bitregion_end))
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (fieldmode, &int_mode)
+      && strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, int_mode,
+				     bitregion_start, bitregion_end))
     {
       /* Storing of a full word can be done with a simple store.
 	 We know here that the field can be accessed with one single
 	 instruction.  For targets that support unaligned memory,
 	 an unaligned access may be necessary.  */
-      if (bitsize == GET_MODE_BITSIZE (fieldmode))
+      if (bitsize == GET_MODE_BITSIZE (int_mode))
 	{
-	  str_rtx = adjust_bitfield_address (str_rtx, fieldmode,
+	  str_rtx = adjust_bitfield_address (str_rtx, int_mode,
 					     bitnum / BITS_PER_UNIT);
 	  if (reverse)
-	    value = flip_storage_order (fieldmode, value);
+	    value = flip_storage_order (int_mode, value);
 	  gcc_assert (bitnum % BITS_PER_UNIT == 0);
 	  emit_move_insn (str_rtx, value);
 	}
@@ -1070,12 +1067,12 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 	{
 	  rtx temp;
 
-	  str_rtx = narrow_bit_field_mem (str_rtx, fieldmode, bitsize, bitnum,
+	  str_rtx = narrow_bit_field_mem (str_rtx, int_mode, bitsize, bitnum,
 					  &bitnum);
-	  gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (fieldmode));
+	  gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (int_mode));
 	  temp = copy_to_reg (str_rtx);
 	  if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0,
-				  fieldmode, value, reverse, true))
+				  int_mode, value, reverse, true))
 	    gcc_unreachable ();
 
 	  emit_move_insn (str_rtx, temp);
@@ -1889,25 +1886,27 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
   else
     mode1 = tmode;
 
-  if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, mode1, 0, 0))
+  scalar_int_mode int_mode;
+  if (is_a <scalar_int_mode> (mode1, &int_mode)
+      && strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, int_mode, 0, 0))
     {
-      /* Extraction of a full MODE1 value can be done with a simple load.
+      /* Extraction of a full INT_MODE value can be done with a simple load.
 	 We know here that the field can be accessed with one single
 	 instruction.  For targets that support unaligned memory,
 	 an unaligned access may be necessary.  */
-      if (bitsize == GET_MODE_BITSIZE (mode1))
+      if (bitsize == GET_MODE_BITSIZE (int_mode))
 	{
-	  rtx result = adjust_bitfield_address (str_rtx, mode1,
+	  rtx result = adjust_bitfield_address (str_rtx, int_mode,
 						bitnum / BITS_PER_UNIT);
 	  if (reverse)
-	    result = flip_storage_order (mode1, result);
+	    result = flip_storage_order (int_mode, result);
 	  gcc_assert (bitnum % BITS_PER_UNIT == 0);
 	  return convert_extracted_bit_field (result, mode, tmode, unsignedp);
 	}
 
-      str_rtx = narrow_bit_field_mem (str_rtx, mode1, bitsize, bitnum,
+      str_rtx = narrow_bit_field_mem (str_rtx, int_mode, bitsize, bitnum,
 				      &bitnum);
-      gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (mode1));
+      gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (int_mode));
       str_rtx = copy_to_reg (str_rtx);
     }
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [39/67] Two changes to the get_best_mode interface
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (38 preceding siblings ...)
  2016-12-09 13:17 ` [38/67] Move SCALAR_INT_MODE_P out of strict_volatile_bitfield_p Richard Sandiford
@ 2016-12-09 13:18 ` Richard Sandiford
  2016-12-09 13:19 ` [40/67] Use scalar_int_mode for extraction_insn fields Richard Sandiford
                   ` (29 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:18 UTC (permalink / raw)
  To: gcc-patches

get_best_mode always returns a scalar_int_mode on success,
so this patch makes that explicit in the type system.  Also,
the "largest_mode" argument is used simply to provide a maximum
size, and in practice that size is always a compile-time constant,
even when the concept of variable-sized modes is added later.
The patch therefore passes the size directly.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* machmode.h (bit_field_mode_iterator::next_mode): Take a pointer
	to a scalar_int_mode instead of a machine_mode.
	(bit_field_mode_iterator::m_mode): Change type to opt_scalar_int_mode.
	(get_best_mode): Return a boolean and use a pointer argument to store
	the selected mode.  Replace the limit mode parameter with a bit limit.
	* expmed.c (adjust_bit_field_mem_for_reg): Use scalar_int_mode
	for the values returned by bit_field_mode_iterator::next_mode.
	(store_bit_field): Update call to get_best_mode.
	(store_fixed_bit_field): Likewise.
	(extract_fixed_bit_field): Likewise.
	* expr.c (optimize_bitfield_assignment_op): Likewise.
	* fold-const.c (optimize_bit_field_compare): Likewise.
	(fold_truth_andor_1): Likewise.
	* stor-layout.c (bit_field_mode_iterator::next_mode): As above.
	Update for new type of m_mode.
	(get_mode): As above.

diff --git a/gcc/expmed.c b/gcc/expmed.c
index f9cdcda..0b2e61a 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -459,7 +459,7 @@ adjust_bit_field_mem_for_reg (enum extraction_pattern pattern,
   bit_field_mode_iterator iter (bitsize, bitnum, bitregion_start,
 				bitregion_end, MEM_ALIGN (op0),
 				MEM_VOLATILE_P (op0));
-  machine_mode best_mode;
+  scalar_int_mode best_mode;
   if (iter.next_mode (&best_mode))
     {
       /* We can use a memory in BEST_MODE.  See whether this is true for
@@ -477,7 +477,7 @@ adjust_bit_field_mem_for_reg (enum extraction_pattern pattern,
 					    fieldmode))
 	    limit_mode = insn.field_mode;
 
-	  machine_mode wider_mode;
+	  scalar_int_mode wider_mode;
 	  while (iter.next_mode (&wider_mode)
 		 && GET_MODE_SIZE (wider_mode) <= GET_MODE_SIZE (limit_mode))
 	    best_mode = wider_mode;
@@ -1086,7 +1086,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
      bit region.  */
   if (MEM_P (str_rtx) && bitregion_start > 0)
     {
-      machine_mode bestmode;
+      scalar_int_mode best_mode;
+      machine_mode addr_mode = VOIDmode;
       HOST_WIDE_INT offset, size;
 
       gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0);
@@ -1096,11 +1097,13 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       size = (bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
       bitregion_end -= bitregion_start;
       bitregion_start = 0;
-      bestmode = get_best_mode (bitsize, bitnum,
-				bitregion_start, bitregion_end,
-				MEM_ALIGN (str_rtx), VOIDmode,
-				MEM_VOLATILE_P (str_rtx));
-      str_rtx = adjust_bitfield_address_size (str_rtx, bestmode, offset, size);
+      if (get_best_mode (bitsize, bitnum,
+			 bitregion_start, bitregion_end,
+			 MEM_ALIGN (str_rtx), 0,
+			 MEM_VOLATILE_P (str_rtx), &best_mode))
+	addr_mode = best_mode;
+      str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode,
+					      offset, size);
     }
 
   if (!store_bit_field_1 (str_rtx, bitsize, bitnum,
@@ -1134,10 +1137,10 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
       if (GET_MODE_BITSIZE (mode) == 0
 	  || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
 	mode = word_mode;
-      mode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end,
-			    MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0));
-
-      if (mode == VOIDmode)
+      scalar_int_mode best_mode;
+      if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end,
+			  MEM_ALIGN (op0), GET_MODE_BITSIZE (mode),
+			  MEM_VOLATILE_P (op0), &best_mode))
 	{
 	  /* The only way this should occur is if the field spans word
 	     boundaries.  */
@@ -1146,7 +1149,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
 	  return;
 	}
 
-      op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
+      op0 = narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, &bitnum);
     }
 
   store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse);
@@ -1932,11 +1935,9 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0,
 {
   if (MEM_P (op0))
     {
-      machine_mode mode
-	= get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), word_mode,
-			 MEM_VOLATILE_P (op0));
-
-      if (mode == VOIDmode)
+      scalar_int_mode mode;
+      if (!get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0),
+			  BITS_PER_WORD, MEM_VOLATILE_P (op0), &mode))
 	/* The only way this should occur is if the field spans word
 	   boundaries.  */
 	return extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
diff --git a/gcc/expr.c b/gcc/expr.c
index 2e7bff5..d54cc65 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4675,13 +4675,14 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
       unsigned HOST_WIDE_INT offset1;
 
       if (str_bitsize == 0 || str_bitsize > BITS_PER_WORD)
-	str_mode = word_mode;
-      str_mode = get_best_mode (bitsize, bitpos,
-				bitregion_start, bitregion_end,
-				MEM_ALIGN (str_rtx), str_mode, 0);
-      if (str_mode == VOIDmode)
+	str_bitsize = BITS_PER_WORD;
+
+      scalar_int_mode best_mode;
+      if (!get_best_mode (bitsize, bitpos, bitregion_start, bitregion_end,
+			  MEM_ALIGN (str_rtx), str_bitsize, false, &best_mode))
 	return false;
-      str_bitsize = GET_MODE_BITSIZE (str_mode);
+      str_mode = best_mode;
+      str_bitsize = GET_MODE_BITSIZE (best_mode);
 
       offset1 = bitpos;
       bitpos %= str_bitsize;
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 088751f..902e22b 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3857,7 +3857,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
   tree type = TREE_TYPE (lhs);
   tree unsigned_type;
   int const_p = TREE_CODE (rhs) == INTEGER_CST;
-  machine_mode lmode, rmode, nmode;
+  machine_mode lmode, rmode;
+  scalar_int_mode nmode;
   int lunsignedp, runsignedp;
   int lreversep, rreversep;
   int lvolatilep = 0, rvolatilep = 0;
@@ -3904,12 +3905,11 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
 
   /* See if we can find a mode to refer to this field.  We should be able to,
      but fail if we can't.  */
-  nmode = get_best_mode (lbitsize, lbitpos, bitstart, bitend,
-			 const_p ? TYPE_ALIGN (TREE_TYPE (linner))
-			 : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
-				TYPE_ALIGN (TREE_TYPE (rinner))),
-			 word_mode, false);
-  if (nmode == VOIDmode)
+  if (!get_best_mode (lbitsize, lbitpos, bitstart, bitend,
+		      const_p ? TYPE_ALIGN (TREE_TYPE (linner))
+		      : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
+			     TYPE_ALIGN (TREE_TYPE (rinner))),
+		      BITS_PER_WORD, false, &nmode))
     return 0;
 
   /* Set signed and unsigned types of the precision of this mode for the
@@ -5467,7 +5467,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
   int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp;
   int ll_reversep, lr_reversep, rl_reversep, rr_reversep;
   machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
-  machine_mode lnmode, rnmode;
+  scalar_int_mode lnmode, rnmode;
   tree ll_mask, lr_mask, rl_mask, rr_mask;
   tree ll_and_mask, lr_and_mask, rl_and_mask, rr_and_mask;
   tree l_const, r_const;
@@ -5653,10 +5653,9 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
      to be relative to a field of that size.  */
   first_bit = MIN (ll_bitpos, rl_bitpos);
   end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize);
-  lnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
-			  TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode,
-			  volatilep);
-  if (lnmode == VOIDmode)
+  if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0,
+		      TYPE_ALIGN (TREE_TYPE (ll_inner)), BITS_PER_WORD,
+		      volatilep, &lnmode))
     return 0;
 
   lnbitsize = GET_MODE_BITSIZE (lnmode);
@@ -5718,10 +5717,9 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
 
       first_bit = MIN (lr_bitpos, rr_bitpos);
       end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize);
-      rnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0,
-			      TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode,
-			      volatilep);
-      if (rnmode == VOIDmode)
+      if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0,
+			  TYPE_ALIGN (TREE_TYPE (lr_inner)), BITS_PER_WORD,
+			  volatilep, &rnmode))
 	return 0;
 
       rnbitsize = GET_MODE_BITSIZE (rnmode);
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 75184b5..696f3c9 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -618,11 +618,11 @@ public:
   bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT,
 			   HOST_WIDE_INT, HOST_WIDE_INT,
 			   unsigned int, bool);
-  bool next_mode (machine_mode *);
+  bool next_mode (scalar_int_mode *);
   bool prefer_smaller_modes ();
 
 private:
-  machine_mode m_mode;
+  opt_scalar_int_mode m_mode;
   /* We use signed values here because the bit position can be negative
      for invalid input such as gcc.dg/pr48335-8.c.  */
   HOST_WIDE_INT m_bitsize;
@@ -636,11 +636,9 @@ private:
 
 /* Find the best mode to use to access a bit field.  */
 
-extern machine_mode get_best_mode (int, int,
-					unsigned HOST_WIDE_INT,
-					unsigned HOST_WIDE_INT,
-					unsigned int,
-					machine_mode, bool);
+extern bool get_best_mode (int, int, unsigned HOST_WIDE_INT,
+			   unsigned HOST_WIDE_INT, unsigned int,
+			   unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
 
 /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT.  */
 
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 9acd90e..d872dae 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2712,15 +2712,15 @@ bit_field_mode_iterator
    available, storing it in *OUT_MODE if so.  */
 
 bool
-bit_field_mode_iterator::next_mode (machine_mode *out_mode)
+bit_field_mode_iterator::next_mode (scalar_int_mode *out_mode)
 {
-  for (; m_mode != VOIDmode;
-       m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ())
+  for (; m_mode.exists (); m_mode = GET_MODE_WIDER_MODE (*m_mode))
     {
-      unsigned int unit = GET_MODE_BITSIZE (m_mode);
+      scalar_int_mode mode = *m_mode;
+      unsigned int unit = GET_MODE_BITSIZE (mode);
 
       /* Skip modes that don't have full precision.  */
-      if (unit != GET_MODE_PRECISION (m_mode))
+      if (unit != GET_MODE_PRECISION (mode))
 	continue;
 
       /* Stop if the mode is too wide to handle efficiently.  */
@@ -2747,12 +2747,12 @@ bit_field_mode_iterator::next_mode (machine_mode *out_mode)
 	break;
 
       /* Stop if the mode requires too much alignment.  */
-      if (GET_MODE_ALIGNMENT (m_mode) > m_align
-	  && SLOW_UNALIGNED_ACCESS (m_mode, m_align))
+      if (GET_MODE_ALIGNMENT (mode) > m_align
+	  && SLOW_UNALIGNED_ACCESS (mode, m_align))
 	break;
 
-      *out_mode = m_mode;
-      m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ();
+      *out_mode = mode;
+      m_mode = GET_MODE_WIDER_MODE (mode);
       m_count++;
       return true;
     }
@@ -2780,8 +2780,8 @@ bit_field_mode_iterator::prefer_smaller_modes ()
    any adjacent non bit-fields.
 
    The underlying object is known to be aligned to a boundary of ALIGN bits.
-   If LARGEST_MODE is not VOIDmode, it means that we should not use a mode
-   larger than LARGEST_MODE (usually SImode).
+   If LARGEST_MODE_BITSIZE is not 0, it means that we should not use a mode
+   larger than LARGEST_MODE_BITSIZE bits.
 
    If no mode meets all these conditions, we return VOIDmode.
 
@@ -2795,17 +2795,18 @@ bit_field_mode_iterator::prefer_smaller_modes ()
    If VOLATILEP is true the narrow_volatile_bitfields target hook is used to
    decide which of the above modes should be used.  */
 
-machine_mode
+bool
 get_best_mode (int bitsize, int bitpos,
 	       unsigned HOST_WIDE_INT bitregion_start,
 	       unsigned HOST_WIDE_INT bitregion_end,
 	       unsigned int align,
-	       machine_mode largest_mode, bool volatilep)
+	       unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep,
+	       scalar_int_mode *best_mode)
 {
   bit_field_mode_iterator iter (bitsize, bitpos, bitregion_start,
 				bitregion_end, align, volatilep);
-  machine_mode widest_mode = VOIDmode;
-  machine_mode mode;
+  scalar_int_mode mode;
+  bool found = false;
   while (iter.next_mode (&mode)
 	 /* ??? For historical reasons, reject modes that would normally
 	    receive greater alignment, even if unaligned accesses are
@@ -2864,14 +2865,16 @@ get_best_mode (int bitsize, int bitpos,
 	    so that the final bitfield reference still has a MEM_EXPR
 	    and MEM_OFFSET.  */
 	 && GET_MODE_ALIGNMENT (mode) <= align
-	 && (largest_mode == VOIDmode
-	     || GET_MODE_SIZE (mode) <= GET_MODE_SIZE (largest_mode)))
+	 && (largest_mode_bitsize == 0
+	     || GET_MODE_BITSIZE (mode) <= largest_mode_bitsize))
     {
-      widest_mode = mode;
+      *best_mode = mode;
+      found = true;
       if (iter.prefer_smaller_modes ())
 	break;
     }
-  return widest_mode;
+
+  return found;
 }
 
 /* Gets minimal and maximal values for MODE (signed or unsigned depending on

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [40/67] Use scalar_int_mode for extraction_insn fields
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (39 preceding siblings ...)
  2016-12-09 13:18 ` [39/67] Two changes to the get_best_mode interface Richard Sandiford
@ 2016-12-09 13:19 ` Richard Sandiford
  2016-12-09 13:20 ` [42/67] Use scalar_int_mode in simplify_shift_const_1 Richard Sandiford
                   ` (28 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:19 UTC (permalink / raw)
  To: gcc-patches

insv, extv and eztzv modify or read a field in a register or
memory.  The field always has a scalar integer mode, while the
register or memory either has a scalar integer mode or BLKmode.
The mode of the bit position is also a scalar integer.

This patch uses the type system to make that explicit.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* optabs-query.h (extraction_insn::struct_mode): Change type to
	opt_scalar_int_mode and update comment.
	(extraction_insn::field_mode): Change type to scalar_int_mode.
	(extraction_insn::pos_mode): Likewise.
	* combine.c (make_extraction): Update accordingly.
	* optabs-query.c (get_traditional_extraction_insn): Likewise.
	(get_optab_extraction_insn): Likewise.
	* recog.c (simplify_while_replacing): Likewise.
	* expmed.c (narrow_bit_field_mem): Chane the type of the mode
	parameter to opt_scalar_int_mode.

diff --git a/gcc/combine.c b/gcc/combine.c
index 0f25782..449f371 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7608,7 +7608,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   if (get_best_reg_extraction_insn (&insn, pattern,
 				    GET_MODE_BITSIZE (inner_mode), mode))
     {
-      wanted_inner_reg_mode = insn.struct_mode;
+      wanted_inner_reg_mode = *insn.struct_mode;
       pos_mode = insn.pos_mode;
       extraction_mode = insn.field_mode;
     }
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 0b2e61a..71e1fa8 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -409,31 +409,32 @@ flip_storage_order (machine_mode mode, rtx x)
   return result;
 }
 
-/* Adjust bitfield memory MEM so that it points to the first unit of mode
-   MODE that contains a bitfield of size BITSIZE at bit position BITNUM.
-   If MODE is BLKmode, return a reference to every byte in the bitfield.
-   Set *NEW_BITNUM to the bit position of the field within the new memory.  */
+/* If MODE is set, adjust bitfield memory MEM so that it points to the
+   first unit of mode MODE that contains a bitfield of size BITSIZE at
+   bit position BITNUM.  If MODE is not set, return a BLKmode reference
+   to every byte in the bitfield.  Set *NEW_BITNUM to the bit position
+   of the field within the new memory.  */
 
 static rtx
-narrow_bit_field_mem (rtx mem, machine_mode mode,
+narrow_bit_field_mem (rtx mem, opt_scalar_int_mode mode,
 		      unsigned HOST_WIDE_INT bitsize,
 		      unsigned HOST_WIDE_INT bitnum,
 		      unsigned HOST_WIDE_INT *new_bitnum)
 {
-  if (mode == BLKmode)
+  if (mode.exists ())
+    {
+      unsigned int unit = GET_MODE_BITSIZE (*mode);
+      *new_bitnum = bitnum % unit;
+      HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT;
+      return adjust_bitfield_address (mem, *mode, offset);
+    }
+  else
     {
       *new_bitnum = bitnum % BITS_PER_UNIT;
       HOST_WIDE_INT offset = bitnum / BITS_PER_UNIT;
       HOST_WIDE_INT size = ((*new_bitnum + bitsize + BITS_PER_UNIT - 1)
 			    / BITS_PER_UNIT);
-      return adjust_bitfield_address_size (mem, mode, offset, size);
-    }
-  else
-    {
-      unsigned int unit = GET_MODE_BITSIZE (mode);
-      *new_bitnum = bitnum % unit;
-      HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT;
-      return adjust_bitfield_address (mem, mode, offset);
+      return adjust_bitfield_address_size (mem, BLKmode, offset, size);
     }
 }
 
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index e664587..6541f07 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -100,9 +100,14 @@ get_traditional_extraction_insn (extraction_insn *insn,
     pos_mode = word_mode;
 
   insn->icode = icode;
-  insn->field_mode = field_mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
-  insn->pos_mode = pos_mode;
+  insn->field_mode = as_a <scalar_int_mode> (field_mode);
+  if (type == ET_unaligned_mem)
+    insn->struct_mode = byte_mode;
+  else if (struct_mode == BLKmode)
+    insn->struct_mode = opt_scalar_int_mode ();
+  else
+    insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
+  insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
   return true;
 }
 
@@ -126,12 +131,17 @@ get_optab_extraction_insn (struct extraction_insn *insn,
 
   const struct insn_data_d *data = &insn_data[icode];
 
+  machine_mode pos_mode = data->operand[pos_op].mode;
+  if (pos_mode == VOIDmode)
+    pos_mode = word_mode;
+
   insn->icode = icode;
-  insn->field_mode = mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
-  insn->pos_mode = data->operand[pos_op].mode;
-  if (insn->pos_mode == VOIDmode)
-    insn->pos_mode = word_mode;
+  insn->field_mode = as_a <scalar_int_mode> (mode);
+  if (type == ET_unaligned_mem)
+    insn->struct_mode = opt_scalar_int_mode ();
+  else
+    insn->struct_mode = insn->field_mode;
+  insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
   return true;
 }
 
diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h
index 840dc79..58fbf13 100644
--- a/gcc/optabs-query.h
+++ b/gcc/optabs-query.h
@@ -141,16 +141,17 @@ struct extraction_insn
   enum insn_code icode;
 
   /* The mode that the structure operand should have.  This is byte_mode
-     when using the legacy insv, extv and extzv patterns to access memory.  */
-  machine_mode struct_mode;
+     when using the legacy insv, extv and extzv patterns to access memory.
+     If no mode is given, the structure is a BLKmode memory.  */
+  opt_scalar_int_mode struct_mode;
 
   /* The mode of the field to be inserted or extracted, and by extension
      the mode of the insertion or extraction itself.  */
-  machine_mode field_mode;
+  scalar_int_mode field_mode;
 
   /* The mode of the field's bit position.  This is only important
      when the position is variable rather than constant.  */
-  machine_mode pos_mode;
+  scalar_int_mode pos_mode;
 };
 
 bool get_best_reg_extraction_insn (extraction_insn *,
diff --git a/gcc/recog.c b/gcc/recog.c
index 317ec29..906a5b0 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -663,25 +663,18 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
 					MEM_ADDR_SPACE (XEXP (x, 0)))
 	  && !MEM_VOLATILE_P (XEXP (x, 0)))
 	{
-	  machine_mode wanted_mode = VOIDmode;
 	  int pos = INTVAL (XEXP (x, 2));
-
+	  machine_mode new_mode = is_mode;
 	  if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ())
-	    {
-	      wanted_mode = insn_data[targetm.code_for_extzv].operand[1].mode;
-	      if (wanted_mode == VOIDmode)
-		wanted_mode = word_mode;
-	    }
+	    new_mode = insn_data[targetm.code_for_extzv].operand[1].mode;
 	  else if (GET_CODE (x) == SIGN_EXTRACT && targetm.have_extv ())
-	    {
-	      wanted_mode = insn_data[targetm.code_for_extv].operand[1].mode;
-	      if (wanted_mode == VOIDmode)
-		wanted_mode = word_mode;
-	    }
+	    new_mode = insn_data[targetm.code_for_extv].operand[1].mode;
+	  scalar_int_mode wanted_mode = (new_mode == VOIDmode
+					 ? word_mode
+					 : as_a <scalar_int_mode> (new_mode));
 
 	  /* If we have a narrower mode, we can do something.  */
-	  if (wanted_mode != VOIDmode
-	      && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
+	  if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
 	    {
 	      int offset = pos / BITS_PER_UNIT;
 	      rtx newmem;

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [42/67] Use scalar_int_mode in simplify_shift_const_1
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (40 preceding siblings ...)
  2016-12-09 13:19 ` [40/67] Use scalar_int_mode for extraction_insn fields Richard Sandiford
@ 2016-12-09 13:20 ` Richard Sandiford
  2016-12-09 13:20 ` [41/67] Split scalar integer handling out of force_to_mode Richard Sandiford
                   ` (27 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:20 UTC (permalink / raw)
  To: gcc-patches

This patch makes simplify_shift_const_1 use scalar_int_modes
for all code that is specific to scalars rather than vectors.
This includes situations in which the new shift mode is different
from the original one, since the function never changes the mode
of vector shifts.  That in turn makes it more natural to test
for equal modes in simplify_shift_const_1 rather than
try_widen_shift_mode (which only applies to scalars).

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (try_widen_shift_mode): Move check for equal modes to...
	(simplify_shift_const_1): ...here.  Use scalar_int_mode for
	shift_unit_mode and for modes involved in scalar shifts.

diff --git a/gcc/combine.c b/gcc/combine.c
index 0fcd428..3cb92a4 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -10296,8 +10296,6 @@ try_widen_shift_mode (enum rtx_code code, rtx op, int count,
 		      machine_mode orig_mode, machine_mode mode,
 		      enum rtx_code outer_code, HOST_WIDE_INT outer_const)
 {
-  if (orig_mode == mode)
-    return mode;
   gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode));
 
   /* In general we can't perform in wider mode for right shift and rotate.  */
@@ -10358,7 +10356,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
   int count;
   machine_mode mode = result_mode;
   machine_mode shift_mode;
-  scalar_int_mode tmode, inner_mode;
+  scalar_int_mode tmode, inner_mode, int_mode, int_varop_mode, int_result_mode;
   unsigned int mode_words
     = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
   /* We form (outer_op (code varop count) (outer_const)).  */
@@ -10398,9 +10396,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  count = bitsize - count;
 	}
 
-      shift_mode = try_widen_shift_mode (code, varop, count, result_mode,
-					 mode, outer_op, outer_const);
-      machine_mode shift_unit_mode = GET_MODE_INNER (shift_mode);
+      shift_mode = result_mode;
+      if (shift_mode != mode)
+	{
+	  /* We only change the modes of scalar shifts.  */
+	  int_mode = as_a <scalar_int_mode> (mode);
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
+	  shift_mode = try_widen_shift_mode (code, varop, count,
+					     int_result_mode, int_mode,
+					     outer_op, outer_const);
+	}
+
+      scalar_int_mode shift_unit_mode
+	= as_a <scalar_int_mode> (GET_MODE_INNER (shift_mode));
 
       /* Handle cases where the count is greater than the size of the mode
 	 minus 1.  For ASHIFT, use the size minus one as the count (this can
@@ -10495,6 +10503,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_mode = as_a <scalar_int_mode> (mode);
 
 	  /* If we have (xshiftrt (mem ...) C) and C is MODE_WIDTH
 	     minus the width of a smaller mode, we can do this with a
@@ -10503,15 +10512,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	      && ! mode_dependent_address_p (XEXP (varop, 0),
 					     MEM_ADDR_SPACE (varop))
 	      && ! MEM_VOLATILE_P (varop)
-	      && (int_mode_for_size (GET_MODE_BITSIZE (mode) - count, 1)
+	      && (int_mode_for_size (GET_MODE_BITSIZE (int_mode) - count, 1)
 		  .exists (&tmode)))
 	    {
 	      new_rtx = adjust_address_nv (varop, tmode,
-				       BYTES_BIG_ENDIAN ? 0
-				       : count / BITS_PER_UNIT);
+					   BYTES_BIG_ENDIAN ? 0
+					   : count / BITS_PER_UNIT);
 
 	      varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
-				     : ZERO_EXTEND, mode, new_rtx);
+				     : ZERO_EXTEND, int_mode, new_rtx);
 	      count = 0;
 	      continue;
 	    }
@@ -10521,20 +10530,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_mode = as_a <scalar_int_mode> (mode);
+	  int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
 
 	  /* If VAROP is a SUBREG, strip it as long as the inner operand has
 	     the same number of words as what we've seen so far.  Then store
 	     the widest mode in MODE.  */
 	  if (subreg_lowpart_p (varop)
 	      && is_int_mode (GET_MODE (SUBREG_REG (varop)), &inner_mode)
-	      && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (GET_MODE (varop))
+	      && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (int_varop_mode)
 	      && (unsigned int) ((GET_MODE_SIZE (inner_mode)
 				  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
 		 == mode_words
-	      && GET_MODE_CLASS (GET_MODE (varop)) == MODE_INT)
+	      && GET_MODE_CLASS (int_varop_mode) == MODE_INT)
 	    {
 	      varop = SUBREG_REG (varop);
-	      if (GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (mode))
+	      if (GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (int_mode))
 		mode = inner_mode;
 	      continue;
 	    }
@@ -10593,14 +10604,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_mode = as_a <scalar_int_mode> (mode);
+	  int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
 
 	  /* Here we have two nested shifts.  The result is usually the
 	     AND of a new shift with a mask.  We compute the result below.  */
 	  if (CONST_INT_P (XEXP (varop, 1))
 	      && INTVAL (XEXP (varop, 1)) >= 0
-	      && INTVAL (XEXP (varop, 1)) < GET_MODE_PRECISION (GET_MODE (varop))
-	      && HWI_COMPUTABLE_MODE_P (result_mode)
-	      && HWI_COMPUTABLE_MODE_P (mode))
+	      && INTVAL (XEXP (varop, 1)) < GET_MODE_PRECISION (int_varop_mode)
+	      && HWI_COMPUTABLE_MODE_P (int_result_mode)
+	      && HWI_COMPUTABLE_MODE_P (int_mode))
 	    {
 	      enum rtx_code first_code = GET_CODE (varop);
 	      unsigned int first_count = INTVAL (XEXP (varop, 1));
@@ -10615,18 +10629,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 		 (ashiftrt:M1 (ashift:M1 (and:M1 (subreg:M1 FOO 0) C3) C2) C1).
 		 This simplifies certain SIGN_EXTEND operations.  */
 	      if (code == ASHIFT && first_code == ASHIFTRT
-		  && count == (GET_MODE_PRECISION (result_mode)
-			       - GET_MODE_PRECISION (GET_MODE (varop))))
+		  && count == (GET_MODE_PRECISION (int_result_mode)
+			       - GET_MODE_PRECISION (int_varop_mode)))
 		{
 		  /* C3 has the low-order C1 bits zero.  */
 
-		  mask = GET_MODE_MASK (mode)
+		  mask = GET_MODE_MASK (int_mode)
 			 & ~((HOST_WIDE_INT_1U << first_count) - 1);
 
-		  varop = simplify_and_const_int (NULL_RTX, result_mode,
+		  varop = simplify_and_const_int (NULL_RTX, int_result_mode,
 						  XEXP (varop, 0), mask);
-		  varop = simplify_shift_const (NULL_RTX, ASHIFT, result_mode,
-						varop, count);
+		  varop = simplify_shift_const (NULL_RTX, ASHIFT,
+						int_result_mode, varop, count);
 		  count = first_count;
 		  code = ASHIFTRT;
 		  continue;
@@ -10637,11 +10651,11 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 		 this to either an ASHIFT or an ASHIFTRT depending on the
 		 two counts.
 
-		 We cannot do this if VAROP's mode is not SHIFT_MODE.  */
+		 We cannot do this if VAROP's mode is not SHIFT_UNIT_MODE.  */
 
 	      if (code == ASHIFTRT && first_code == ASHIFT
-		  && GET_MODE (varop) == shift_mode
-		  && (num_sign_bit_copies (XEXP (varop, 0), shift_mode)
+		  && int_varop_mode == shift_unit_mode
+		  && (num_sign_bit_copies (XEXP (varop, 0), shift_unit_mode)
 		      > first_count))
 		{
 		  varop = XEXP (varop, 0);
@@ -10672,7 +10686,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
 	      if (code == first_code)
 		{
-		  if (GET_MODE (varop) != result_mode
+		  if (int_varop_mode != int_result_mode
 		      && (code == ASHIFTRT || code == LSHIFTRT
 			  || code == ROTATE))
 		    break;
@@ -10684,8 +10698,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
 	      if (code == ASHIFTRT
 		  || (code == ROTATE && first_code == ASHIFTRT)
-		  || GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
-		  || (GET_MODE (varop) != result_mode
+		  || GET_MODE_PRECISION (int_mode) > HOST_BITS_PER_WIDE_INT
+		  || (int_varop_mode != int_result_mode
 		      && (first_code == ASHIFTRT || first_code == LSHIFTRT
 			  || first_code == ROTATE
 			  || code == ROTATE)))
@@ -10695,19 +10709,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 		 nonzero bits of the inner shift the same way the
 		 outer shift will.  */
 
-	      mask_rtx = gen_int_mode (nonzero_bits (varop, GET_MODE (varop)),
-				       result_mode);
+	      mask_rtx = gen_int_mode (nonzero_bits (varop, int_varop_mode),
+				       int_result_mode);
 
 	      mask_rtx
-		= simplify_const_binary_operation (code, result_mode, mask_rtx,
-						   GEN_INT (count));
+		= simplify_const_binary_operation (code, int_result_mode,
+						   mask_rtx, GEN_INT (count));
 
 	      /* Give up if we can't compute an outer operation to use.  */
 	      if (mask_rtx == 0
 		  || !CONST_INT_P (mask_rtx)
 		  || ! merge_outer_ops (&outer_op, &outer_const, AND,
 					INTVAL (mask_rtx),
-					result_mode, &complement_p))
+					int_result_mode, &complement_p))
 		break;
 
 	      /* If the shifts are in the same direction, we add the
@@ -10744,22 +10758,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	      /* For ((unsigned) (cstULL >> count)) >> cst2 we have to make
 		 sure the result will be masked.  See PR70222.  */
 	      if (code == LSHIFTRT
-		  && mode != result_mode
+		  && int_mode != int_result_mode
 		  && !merge_outer_ops (&outer_op, &outer_const, AND,
-				       GET_MODE_MASK (result_mode)
-				       >> orig_count, result_mode,
+				       GET_MODE_MASK (int_result_mode)
+				       >> orig_count, int_result_mode,
 				       &complement_p))
 		break;
 	      /* For ((int) (cstLL >> count)) >> cst2 just give up.  Queuing
 		 up outer sign extension (often left and right shift) is
 		 hardly more efficient than the original.  See PR70429.  */
-	      if (code == ASHIFTRT && mode != result_mode)
+	      if (code == ASHIFTRT && int_mode != int_result_mode)
 		break;
 
-	      rtx new_rtx = simplify_const_binary_operation (code, mode,
+	      rtx new_rtx = simplify_const_binary_operation (code, int_mode,
 							     XEXP (varop, 0),
 							     GEN_INT (count));
-	      varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1));
+	      varop = gen_rtx_fmt_ee (code, int_mode, new_rtx, XEXP (varop, 1));
 	      count = 0;
 	      continue;
 	    }
@@ -10780,6 +10794,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
 
 	  /* If we have (xshiftrt (ior (plus X (const_int -1)) X) C)
 	     with C the size of VAROP - 1 and the shift is logical if
@@ -10792,15 +10808,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	      && XEXP (XEXP (varop, 0), 1) == constm1_rtx
 	      && (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
 	      && (code == LSHIFTRT || code == ASHIFTRT)
-	      && count == (GET_MODE_PRECISION (GET_MODE (varop)) - 1)
+	      && count == (GET_MODE_PRECISION (int_varop_mode) - 1)
 	      && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
 	    {
 	      count = 0;
-	      varop = gen_rtx_LE (GET_MODE (varop), XEXP (varop, 1),
+	      varop = gen_rtx_LE (int_varop_mode, XEXP (varop, 1),
 				  const0_rtx);
 
 	      if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
-		varop = gen_rtx_NEG (GET_MODE (varop), varop);
+		varop = gen_rtx_NEG (int_varop_mode, varop);
 
 	      continue;
 	    }
@@ -10813,19 +10829,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
 	  if (CONST_INT_P (XEXP (varop, 1))
 	      /* We can't do this if we have (ashiftrt (xor))  and the
-		 constant has its sign bit set in shift_mode with shift_mode
-		 wider than result_mode.  */
+		 constant has its sign bit set in shift_unit_mode with
+		 shift_unit_mode wider than result_mode.  */
 	      && !(code == ASHIFTRT && GET_CODE (varop) == XOR
-		   && result_mode != shift_mode
+		   && int_result_mode != shift_unit_mode
 		   && 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
-					      shift_mode))
+					      shift_unit_mode))
 	      && (new_rtx = simplify_const_binary_operation
-		  (code, result_mode,
-		   gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode),
+		  (code, int_result_mode,
+		   gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
 		   GEN_INT (count))) != 0
 	      && CONST_INT_P (new_rtx)
 	      && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop),
-				  INTVAL (new_rtx), result_mode, &complement_p))
+				  INTVAL (new_rtx), int_result_mode,
+				  &complement_p))
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;
@@ -10838,16 +10855,16 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	     changes the sign bit.  */
 	  if (CONST_INT_P (XEXP (varop, 1))
 	     && !(code == ASHIFTRT && GET_CODE (varop) == XOR
-		  && result_mode != shift_mode
+		  && int_result_mode != shift_unit_mode
 		  && 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
-					     shift_mode)))
+					     shift_unit_mode)))
 	    {
-	      rtx lhs = simplify_shift_const (NULL_RTX, code, shift_mode,
+	      rtx lhs = simplify_shift_const (NULL_RTX, code, shift_unit_mode,
 					      XEXP (varop, 0), count);
-	      rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
+	      rtx rhs = simplify_shift_const (NULL_RTX, code, shift_unit_mode,
 					      XEXP (varop, 1), count);
 
-	      varop = simplify_gen_binary (GET_CODE (varop), shift_mode,
+	      varop = simplify_gen_binary (GET_CODE (varop), shift_unit_mode,
 					   lhs, rhs);
 	      varop = apply_distributive_law (varop);
 
@@ -10860,6 +10877,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
 
 	  /* Convert (lshiftrt (eq FOO 0) C) to (xor FOO 1) if STORE_FLAG_VALUE
 	     says that the sign bit can be tested, FOO has mode MODE, C is
@@ -10867,13 +10885,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	     that may be nonzero.  */
 	  if (code == LSHIFTRT
 	      && XEXP (varop, 1) == const0_rtx
-	      && GET_MODE (XEXP (varop, 0)) == result_mode
-	      && count == (GET_MODE_PRECISION (result_mode) - 1)
-	      && HWI_COMPUTABLE_MODE_P (result_mode)
+	      && GET_MODE (XEXP (varop, 0)) == int_result_mode
+	      && count == (GET_MODE_PRECISION (int_result_mode) - 1)
+	      && HWI_COMPUTABLE_MODE_P (int_result_mode)
 	      && STORE_FLAG_VALUE == -1
-	      && nonzero_bits (XEXP (varop, 0), result_mode) == 1
-	      && merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode,
-				  &complement_p))
+	      && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1
+	      && merge_outer_ops (&outer_op, &outer_const, XOR, 1,
+				  int_result_mode, &complement_p))
 	    {
 	      varop = XEXP (varop, 0);
 	      count = 0;
@@ -10885,12 +10903,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
 
 	  /* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less
 	     than the number of bits in the mode is equivalent to A.  */
 	  if (code == LSHIFTRT
-	      && count == (GET_MODE_PRECISION (result_mode) - 1)
-	      && nonzero_bits (XEXP (varop, 0), result_mode) == 1)
+	      && count == (GET_MODE_PRECISION (int_result_mode) - 1)
+	      && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1)
 	    {
 	      varop = XEXP (varop, 0);
 	      count = 0;
@@ -10900,8 +10919,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* NEG commutes with ASHIFT since it is multiplication.  Move the
 	     NEG outside to allow shifts to combine.  */
 	  if (code == ASHIFT
-	      && merge_outer_ops (&outer_op, &outer_const, NEG, 0, result_mode,
-				  &complement_p))
+	      && merge_outer_ops (&outer_op, &outer_const, NEG, 0,
+				  int_result_mode, &complement_p))
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;
@@ -10912,16 +10931,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_result_mode = as_a <scalar_int_mode> (result_mode);
 
 	  /* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C
 	     is one less than the number of bits in the mode is
 	     equivalent to (xor A 1).  */
 	  if (code == LSHIFTRT
-	      && count == (GET_MODE_PRECISION (result_mode) - 1)
+	      && count == (GET_MODE_PRECISION (int_result_mode) - 1)
 	      && XEXP (varop, 1) == constm1_rtx
-	      && nonzero_bits (XEXP (varop, 0), result_mode) == 1
-	      && merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode,
-				  &complement_p))
+	      && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1
+	      && merge_outer_ops (&outer_op, &outer_const, XOR, 1,
+				  int_result_mode, &complement_p))
 	    {
 	      count = 0;
 	      varop = XEXP (varop, 0);
@@ -10936,21 +10956,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
 	  if ((code == ASHIFTRT || code == LSHIFTRT)
 	      && count < HOST_BITS_PER_WIDE_INT
-	      && nonzero_bits (XEXP (varop, 1), result_mode) >> count == 0
-	      && (nonzero_bits (XEXP (varop, 1), result_mode)
-		  & nonzero_bits (XEXP (varop, 0), result_mode)) == 0)
+	      && nonzero_bits (XEXP (varop, 1), int_result_mode) >> count == 0
+	      && (nonzero_bits (XEXP (varop, 1), int_result_mode)
+		  & nonzero_bits (XEXP (varop, 0), int_result_mode)) == 0)
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;
 	    }
 	  else if ((code == ASHIFTRT || code == LSHIFTRT)
 		   && count < HOST_BITS_PER_WIDE_INT
-		   && HWI_COMPUTABLE_MODE_P (result_mode)
-		   && 0 == (nonzero_bits (XEXP (varop, 0), result_mode)
+		   && HWI_COMPUTABLE_MODE_P (int_result_mode)
+		   && 0 == (nonzero_bits (XEXP (varop, 0), int_result_mode)
 			    >> count)
-		   && 0 == (nonzero_bits (XEXP (varop, 0), result_mode)
-			    & nonzero_bits (XEXP (varop, 1),
-						 result_mode)))
+		   && 0 == (nonzero_bits (XEXP (varop, 0), int_result_mode)
+			    & nonzero_bits (XEXP (varop, 1), int_result_mode)))
 	    {
 	      varop = XEXP (varop, 1);
 	      continue;
@@ -10960,12 +10979,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  if (code == ASHIFT
 	      && CONST_INT_P (XEXP (varop, 1))
 	      && (new_rtx = simplify_const_binary_operation
-		  (ASHIFT, result_mode,
-		   gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode),
+		  (ASHIFT, int_result_mode,
+		   gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
 		   GEN_INT (count))) != 0
 	      && CONST_INT_P (new_rtx)
 	      && merge_outer_ops (&outer_op, &outer_const, PLUS,
-				  INTVAL (new_rtx), result_mode, &complement_p))
+				  INTVAL (new_rtx), int_result_mode,
+				  &complement_p))
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;
@@ -10978,14 +10998,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	     for reasoning in doing so.  */
 	  if (code == LSHIFTRT
 	      && CONST_INT_P (XEXP (varop, 1))
-	      && mode_signbit_p (result_mode, XEXP (varop, 1))
+	      && mode_signbit_p (int_result_mode, XEXP (varop, 1))
 	      && (new_rtx = simplify_const_binary_operation
-		  (code, result_mode,
-		   gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode),
+		  (code, int_result_mode,
+		   gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
 		   GEN_INT (count))) != 0
 	      && CONST_INT_P (new_rtx)
 	      && merge_outer_ops (&outer_op, &outer_const, XOR,
-				  INTVAL (new_rtx), result_mode, &complement_p))
+				  INTVAL (new_rtx), int_result_mode,
+				  &complement_p))
 	    {
 	      varop = XEXP (varop, 0);
 	      continue;
@@ -10997,6 +11018,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	  /* The following rules apply only to scalars.  */
 	  if (shift_mode != shift_unit_mode)
 	    break;
+	  int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
 
 	  /* If we have (xshiftrt (minus (ashiftrt X C)) X) C)
 	     with C the size of VAROP - 1 and the shift is logical if
@@ -11007,18 +11029,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
 	  if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
 	      && GET_CODE (XEXP (varop, 0)) == ASHIFTRT
-	      && count == (GET_MODE_PRECISION (GET_MODE (varop)) - 1)
+	      && count == (GET_MODE_PRECISION (int_varop_mode) - 1)
 	      && (code == LSHIFTRT || code == ASHIFTRT)
 	      && CONST_INT_P (XEXP (XEXP (varop, 0), 1))
 	      && INTVAL (XEXP (XEXP (varop, 0), 1)) == count
 	      && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
 	    {
 	      count = 0;
-	      varop = gen_rtx_GT (GET_MODE (varop), XEXP (varop, 1),
+	      varop = gen_rtx_GT (int_varop_mode, XEXP (varop, 1),
 				  const0_rtx);
 
 	      if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
-		varop = gen_rtx_NEG (GET_MODE (varop), varop);
+		varop = gen_rtx_NEG (int_varop_mode, varop);
 
 	      continue;
 	    }
@@ -11054,8 +11076,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
       break;
     }
 
-  shift_mode = try_widen_shift_mode (code, varop, count, result_mode, mode,
-				     outer_op, outer_const);
+  shift_mode = result_mode;
+  if (shift_mode != mode)
+    {
+      /* We only change the modes of scalar shifts.  */
+      int_mode = as_a <scalar_int_mode> (mode);
+      int_result_mode = as_a <scalar_int_mode> (result_mode);
+      shift_mode = try_widen_shift_mode (code, varop, count, int_result_mode,
+					 int_mode, outer_op, outer_const);
+    }
 
   /* We have now finished analyzing the shift.  The result should be
      a shift of type CODE with SHIFT_MODE shifting VAROP COUNT places.  If
@@ -11090,8 +11119,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
   /* If we were doing an LSHIFTRT in a wider mode than it was originally,
      turn off all the bits that the shift would have turned off.  */
   if (orig_code == LSHIFTRT && result_mode != shift_mode)
-    x = simplify_and_const_int (NULL_RTX, shift_mode, x,
-				GET_MODE_MASK (result_mode) >> orig_count);
+    /* We only change the modes of scalar shifts.  */
+    x = simplify_and_const_int (NULL_RTX, as_a <scalar_int_mode> (shift_mode),
+				x, GET_MODE_MASK (result_mode) >> orig_count);
 
   /* Do the remainder of the processing in RESULT_MODE.  */
   x = gen_lowpart_or_truncate (result_mode, x);
@@ -11103,12 +11133,14 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 
   if (outer_op != UNKNOWN)
     {
+      int_result_mode = as_a <scalar_int_mode> (result_mode);
+
       if (GET_RTX_CLASS (outer_op) != RTX_UNARY
-	  && GET_MODE_PRECISION (result_mode) < HOST_BITS_PER_WIDE_INT)
-	outer_const = trunc_int_for_mode (outer_const, result_mode);
+	  && GET_MODE_PRECISION (int_result_mode) < HOST_BITS_PER_WIDE_INT)
+	outer_const = trunc_int_for_mode (outer_const, int_result_mode);
 
       if (outer_op == AND)
-	x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const);
+	x = simplify_and_const_int (NULL_RTX, int_result_mode, x, outer_const);
       else if (outer_op == SET)
 	{
 	  /* This means that we have determined that the result is
@@ -11117,9 +11149,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
 	    x = GEN_INT (outer_const);
 	}
       else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
-	x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
+	x = simplify_gen_unary (outer_op, int_result_mode, x, int_result_mode);
       else
-	x = simplify_gen_binary (outer_op, result_mode, x,
+	x = simplify_gen_binary (outer_op, int_result_mode, x,
 				 GEN_INT (outer_const));
     }
 

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [41/67] Split scalar integer handling out of force_to_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (41 preceding siblings ...)
  2016-12-09 13:20 ` [42/67] Use scalar_int_mode in simplify_shift_const_1 Richard Sandiford
@ 2016-12-09 13:20 ` Richard Sandiford
  2016-12-09 13:22 ` [43/67] Use scalar_int_mode in simplify_comparison Richard Sandiford
                   ` (26 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:20 UTC (permalink / raw)
  To: gcc-patches

force_to_mode exits partway through for modes that aren't scalar
integers.  This patch splits the remainder of the function out
into a subroutine, force_int_to_mode, so that the modes from that
point on can have type scalar_int_mode.

The patch also makes sure that xmode is kept up-to-date with x
and uses xmode instead of GET_MODE (x) throughout.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (force_int_to_mode): New function, split out from...
	(force_to_here): ...here.  Keep xmode up-to-date and use it
	instead of GET_MODE (x).

diff --git a/gcc/combine.c b/gcc/combine.c
index 449f371..0fcd428 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -446,6 +446,8 @@ static rtx extract_left_shift (rtx, int);
 static int get_pos_from_mask (unsigned HOST_WIDE_INT,
 			      unsigned HOST_WIDE_INT *);
 static rtx canon_reg_for_combine (rtx, rtx);
+static rtx force_int_to_mode (rtx, scalar_int_mode, scalar_int_mode,
+			      scalar_int_mode, unsigned HOST_WIDE_INT, int);
 static rtx force_to_mode (rtx, machine_mode,
 			  unsigned HOST_WIDE_INT, int);
 static rtx if_then_else_cond (rtx, rtx *, rtx *);
@@ -8490,8 +8492,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
   enum rtx_code code = GET_CODE (x);
   int next_select = just_select || code == XOR || code == NOT || code == NEG;
   machine_mode op_mode;
-  unsigned HOST_WIDE_INT fuller_mask, nonzero;
-  rtx op0, op1, temp;
+  unsigned HOST_WIDE_INT nonzero;
 
   /* If this is a CALL or ASM_OPERANDS, don't do anything.  Some of the
      code below will do the wrong thing since the mode of such an
@@ -8519,15 +8520,6 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
   if (op_mode)
     mask &= GET_MODE_MASK (op_mode);
 
-  /* When we have an arithmetic operation, or a shift whose count we
-     do not know, we need to assume that all bits up to the highest-order
-     bit in MASK will be needed.  This is how we form such a mask.  */
-  if (mask & (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1)))
-    fuller_mask = HOST_WIDE_INT_M1U;
-  else
-    fuller_mask = ((HOST_WIDE_INT_1U << (floor_log2 (mask) + 1))
-		   - 1);
-
   /* Determine what bits of X are guaranteed to be (non)zero.  */
   nonzero = nonzero_bits (x, mode);
 
@@ -8565,9 +8557,42 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 		    & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))))))
     return force_to_mode (SUBREG_REG (x), mode, mask, next_select);
 
-  /* The arithmetic simplifications here only work for scalar integer modes.  */
-  if (!SCALAR_INT_MODE_P (mode) || !SCALAR_INT_MODE_P (GET_MODE (x)))
-    return gen_lowpart_or_truncate (mode, x);
+  scalar_int_mode int_mode, xmode;
+  if (is_a <scalar_int_mode> (mode, &int_mode)
+      && is_a <scalar_int_mode> (GET_MODE (x), &xmode))
+    /* OP_MODE is either MODE or XMODE, so it must be a scalar
+       integer too.  */
+    return force_int_to_mode (x, int_mode, xmode,
+			      as_a <scalar_int_mode> (op_mode),
+			      mask, just_select);
+
+  return gen_lowpart_or_truncate (mode, x);
+}
+
+/* Subroutine of force_to_mode that handles cases where both X and
+   the result are scalar integers.  MODE is the mode of the result,
+   XMODE is the mode of X, and OP_MODE says which of MODE or XMODE
+   is preferred for simplified versions of X.  The other arguments
+   are as for force_to_mode.  */
+
+static rtx
+force_int_to_mode (rtx x, scalar_int_mode mode, scalar_int_mode xmode,
+		   scalar_int_mode op_mode, unsigned HOST_WIDE_INT mask,
+		   int just_select)
+{
+  enum rtx_code code = GET_CODE (x);
+  int next_select = just_select || code == XOR || code == NOT || code == NEG;
+  unsigned HOST_WIDE_INT fuller_mask;
+  rtx op0, op1, temp;
+
+  /* When we have an arithmetic operation, or a shift whose count we
+     do not know, we need to assume that all bits up to the highest-order
+     bit in MASK will be needed.  This is how we form such a mask.  */
+  if (mask & (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1)))
+    fuller_mask = HOST_WIDE_INT_M1U;
+  else
+    fuller_mask = ((HOST_WIDE_INT_1U << (floor_log2 (mask) + 1))
+		   - 1);
 
   switch (code)
     {
@@ -8598,14 +8623,14 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	{
 	  x = simplify_and_const_int (x, op_mode, XEXP (x, 0),
 				      mask & INTVAL (XEXP (x, 1)));
+	  xmode = op_mode;
 
 	  /* If X is still an AND, see if it is an AND with a mask that
 	     is just some low-order bits.  If so, and it is MASK, we don't
 	     need it.  */
 
 	  if (GET_CODE (x) == AND && CONST_INT_P (XEXP (x, 1))
-	      && ((INTVAL (XEXP (x, 1)) & GET_MODE_MASK (GET_MODE (x)))
-		  == mask))
+	      && (INTVAL (XEXP (x, 1)) & GET_MODE_MASK (xmode)) == mask)
 	    x = XEXP (x, 0);
 
 	  /* If it remains an AND, try making another AND with the bits
@@ -8614,18 +8639,17 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	     cheaper constant.  */
 
 	  if (GET_CODE (x) == AND && CONST_INT_P (XEXP (x, 1))
-	      && GET_MODE_MASK (GET_MODE (x)) != mask
-	      && HWI_COMPUTABLE_MODE_P (GET_MODE (x)))
+	      && GET_MODE_MASK (xmode) != mask
+	      && HWI_COMPUTABLE_MODE_P (xmode))
 	    {
 	      unsigned HOST_WIDE_INT cval
-		= UINTVAL (XEXP (x, 1))
-		  | (GET_MODE_MASK (GET_MODE (x)) & ~mask);
+		= UINTVAL (XEXP (x, 1)) | (GET_MODE_MASK (xmode) & ~mask);
 	      rtx y;
 
-	      y = simplify_gen_binary (AND, GET_MODE (x), XEXP (x, 0),
-				       gen_int_mode (cval, GET_MODE (x)));
-	      if (set_src_cost (y, GET_MODE (x), optimize_this_for_speed_p)
-	          < set_src_cost (x, GET_MODE (x), optimize_this_for_speed_p))
+	      y = simplify_gen_binary (AND, xmode, XEXP (x, 0),
+				       gen_int_mode (cval, xmode));
+	      if (set_src_cost (y, xmode, optimize_this_for_speed_p)
+		  < set_src_cost (x, xmode, optimize_this_for_speed_p))
 		x = y;
 	    }
 
@@ -8655,7 +8679,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	    && pow2p_hwi (- smask)
 	    && (nonzero_bits (XEXP (x, 0), mode) & ~smask) == 0
 	    && (INTVAL (XEXP (x, 1)) & ~smask) != 0)
-	  return force_to_mode (plus_constant (GET_MODE (x), XEXP (x, 0),
+	  return force_to_mode (plus_constant (xmode, XEXP (x, 0),
 					       (INTVAL (XEXP (x, 1)) & smask)),
 				mode, smask, next_select);
       }
@@ -8686,8 +8710,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       if (CONST_INT_P (XEXP (x, 0))
 	  && least_bit_hwi (UINTVAL (XEXP (x, 0))) > mask)
 	{
-	  x = simplify_gen_unary (NEG, GET_MODE (x), XEXP (x, 1),
-				  GET_MODE (x));
+	  x = simplify_gen_unary (NEG, xmode, XEXP (x, 1), xmode);
 	  return force_to_mode (x, mode, mask, next_select);
 	}
 
@@ -8696,8 +8719,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       if (CONST_INT_P (XEXP (x, 0))
 	  && ((UINTVAL (XEXP (x, 0)) | fuller_mask) == UINTVAL (XEXP (x, 0))))
 	{
-	  x = simplify_gen_unary (NOT, GET_MODE (x),
-				  XEXP (x, 1), GET_MODE (x));
+	  x = simplify_gen_unary (NOT, xmode, XEXP (x, 1), xmode);
 	  return force_to_mode (x, mode, mask, next_select);
 	}
 
@@ -8718,16 +8740,16 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  && CONST_INT_P (XEXP (x, 1))
 	  && ((INTVAL (XEXP (XEXP (x, 0), 1))
 	       + floor_log2 (INTVAL (XEXP (x, 1))))
-	      < GET_MODE_PRECISION (GET_MODE (x)))
+	      < GET_MODE_PRECISION (xmode))
 	  && (UINTVAL (XEXP (x, 1))
-	      & ~nonzero_bits (XEXP (x, 0), GET_MODE (x))) == 0)
+	      & ~nonzero_bits (XEXP (x, 0), xmode)) == 0)
 	{
 	  temp = gen_int_mode ((INTVAL (XEXP (x, 1)) & mask)
 			       << INTVAL (XEXP (XEXP (x, 0), 1)),
-			       GET_MODE (x));
-	  temp = simplify_gen_binary (GET_CODE (x), GET_MODE (x),
+			       xmode);
+	  temp = simplify_gen_binary (GET_CODE (x), xmode,
 				      XEXP (XEXP (x, 0), 0), temp);
-	  x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), temp,
+	  x = simplify_gen_binary (LSHIFTRT, xmode, temp,
 				   XEXP (XEXP (x, 0), 1));
 	  return force_to_mode (x, mode, mask, next_select);
 	}
@@ -8751,8 +8773,11 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       op0 = gen_lowpart_or_truncate (op_mode, op0);
       op1 = gen_lowpart_or_truncate (op_mode, op1);
 
-      if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-	x = simplify_gen_binary (code, op_mode, op0, op1);
+      if (op_mode != xmode || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
+	{
+	  x = simplify_gen_binary (code, op_mode, op0, op1);
+	  xmode = op_mode;
+	}
       break;
 
     case ASHIFT:
@@ -8785,8 +8810,11 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 				     force_to_mode (XEXP (x, 0), op_mode,
 						    mask, next_select));
 
-      if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
-	x = simplify_gen_binary (code, op_mode, op0, XEXP (x, 1));
+      if (op_mode != xmode || op0 != XEXP (x, 0))
+	{
+	  x = simplify_gen_binary (code, op_mode, op0, XEXP (x, 1));
+	  xmode = op_mode;
+	}
       break;
 
     case LSHIFTRT:
@@ -8808,13 +8836,16 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  /* We can only change the mode of the shift if we can do arithmetic
 	     in the mode of the shift and INNER_MASK is no wider than the
 	     width of X's mode.  */
-	  if ((inner_mask & ~GET_MODE_MASK (GET_MODE (x))) != 0)
-	    op_mode = GET_MODE (x);
+	  if ((inner_mask & ~GET_MODE_MASK (xmode)) != 0)
+	    op_mode = xmode;
 
 	  inner = force_to_mode (inner, op_mode, inner_mask, next_select);
 
-	  if (GET_MODE (x) != op_mode || inner != XEXP (x, 0))
-	    x = simplify_gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
+	  if (xmode != op_mode || inner != XEXP (x, 0))
+	    {
+	      x = simplify_gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
+	      xmode = op_mode;
+	    }
 	}
 
       /* If we have (and (lshiftrt FOO C1) C2) where the combination of the
@@ -8827,17 +8858,17 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	     bit.  */
 	  && ((INTVAL (XEXP (x, 1))
 	       + num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0))))
-	      >= GET_MODE_PRECISION (GET_MODE (x)))
+	      >= GET_MODE_PRECISION (xmode))
 	  && pow2p_hwi (mask + 1)
 	  /* Number of bits left after the shift must be more than the mask
 	     needs.  */
 	  && ((INTVAL (XEXP (x, 1)) + exact_log2 (mask + 1))
-	      <= GET_MODE_PRECISION (GET_MODE (x)))
+	      <= GET_MODE_PRECISION (xmode))
 	  /* Must be more sign bit copies than the mask needs.  */
 	  && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
 	      >= exact_log2 (mask + 1)))
-	x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0),
-				 GEN_INT (GET_MODE_PRECISION (GET_MODE (x))
+	x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0),
+				 GEN_INT (GET_MODE_PRECISION (xmode)
 					  - exact_log2 (mask + 1)));
 
       goto shiftrt;
@@ -8845,7 +8876,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
     case ASHIFTRT:
       /* If we are just looking for the sign bit, we don't need this shift at
 	 all, even if it has a variable count.  */
-      if (val_signbit_p (GET_MODE (x), mask))
+      if (val_signbit_p (xmode, mask))
 	return force_to_mode (XEXP (x, 0), mode, mask, next_select);
 
       /* If this is a shift by a constant, get a mask that contains those bits
@@ -8858,13 +8889,14 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0
 	  && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT)
 	{
+	  unsigned HOST_WIDE_INT nonzero;
 	  int i;
 
 	  /* If the considered data is wider than HOST_WIDE_INT, we can't
 	     represent a mask for all its bits in a single scalar.
 	     But we only care about the lower bits, so calculate these.  */
 
-	  if (GET_MODE_PRECISION (GET_MODE (x)) > HOST_BITS_PER_WIDE_INT)
+	  if (GET_MODE_PRECISION (xmode) > HOST_BITS_PER_WIDE_INT)
 	    {
 	      nonzero = HOST_WIDE_INT_M1U;
 
@@ -8873,21 +8905,21 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 		 We need only shift if these are fewer than nonzero can
 		 hold.  If not, we must keep all bits set in nonzero.  */
 
-	      if (GET_MODE_PRECISION (GET_MODE (x)) - INTVAL (XEXP (x, 1))
+	      if (GET_MODE_PRECISION (xmode) - INTVAL (XEXP (x, 1))
 		  < HOST_BITS_PER_WIDE_INT)
 		nonzero >>= INTVAL (XEXP (x, 1))
 			    + HOST_BITS_PER_WIDE_INT
-			    - GET_MODE_PRECISION (GET_MODE (x)) ;
+			    - GET_MODE_PRECISION (xmode);
 	    }
 	  else
 	    {
-	      nonzero = GET_MODE_MASK (GET_MODE (x));
+	      nonzero = GET_MODE_MASK (xmode);
 	      nonzero >>= INTVAL (XEXP (x, 1));
 	    }
 
 	  if ((mask & ~nonzero) == 0)
 	    {
-	      x = simplify_shift_const (NULL_RTX, LSHIFTRT, GET_MODE (x),
+	      x = simplify_shift_const (NULL_RTX, LSHIFTRT, xmode,
 					XEXP (x, 0), INTVAL (XEXP (x, 1)));
 	      if (GET_CODE (x) != ASHIFTRT)
 		return force_to_mode (x, mode, mask, next_select);
@@ -8896,8 +8928,8 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  else if ((i = exact_log2 (mask)) >= 0)
 	    {
 	      x = simplify_shift_const
-		  (NULL_RTX, LSHIFTRT, GET_MODE (x), XEXP (x, 0),
-		   GET_MODE_PRECISION (GET_MODE (x)) - 1 - i);
+		  (NULL_RTX, LSHIFTRT, xmode, XEXP (x, 0),
+		   GET_MODE_PRECISION (xmode) - 1 - i);
 
 	      if (GET_CODE (x) != ASHIFTRT)
 		return force_to_mode (x, mode, mask, next_select);
@@ -8907,8 +8939,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       /* If MASK is 1, convert this to an LSHIFTRT.  This can be done
 	 even if the shift count isn't a constant.  */
       if (mask == 1)
-	x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
-				 XEXP (x, 0), XEXP (x, 1));
+	x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0), XEXP (x, 1));
 
     shiftrt:
 
@@ -8920,7 +8951,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  && CONST_INT_P (XEXP (x, 1))
 	  && INTVAL (XEXP (x, 1)) >= 0
 	  && (INTVAL (XEXP (x, 1))
-	      <= GET_MODE_PRECISION (GET_MODE (x)) - (floor_log2 (mask) + 1))
+	      <= GET_MODE_PRECISION (xmode) - (floor_log2 (mask) + 1))
 	  && GET_CODE (XEXP (x, 0)) == ASHIFT
 	  && XEXP (XEXP (x, 0), 1) == XEXP (x, 1))
 	return force_to_mode (XEXP (XEXP (x, 0), 0), mode, mask,
@@ -8938,12 +8969,11 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  && INTVAL (XEXP (x, 1)) >= 0)
 	{
 	  temp = simplify_binary_operation (code == ROTATE ? ROTATERT : ROTATE,
-					    GET_MODE (x),
-					    gen_int_mode (mask, GET_MODE (x)),
+					    xmode, gen_int_mode (mask, xmode),
 					    XEXP (x, 1));
 	  if (temp && CONST_INT_P (temp))
-	    x = simplify_gen_binary (code, GET_MODE (x),
-				     force_to_mode (XEXP (x, 0), GET_MODE (x),
+	    x = simplify_gen_binary (code, xmode,
+				     force_to_mode (XEXP (x, 0), xmode,
 						    INTVAL (temp), next_select),
 				     XEXP (x, 1));
 	}
@@ -8970,14 +9000,12 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
 	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
 	  && INTVAL (XEXP (XEXP (x, 0), 1)) >= 0
 	  && (INTVAL (XEXP (XEXP (x, 0), 1)) + floor_log2 (mask)
-	      < GET_MODE_PRECISION (GET_MODE (x)))
+	      < GET_MODE_PRECISION (xmode))
 	  && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT)
 	{
-	  temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
-			       GET_MODE (x));
-	  temp = simplify_gen_binary (XOR, GET_MODE (x),
-				      XEXP (XEXP (x, 0), 0), temp);
-	  x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
+	  temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)), xmode);
+	  temp = simplify_gen_binary (XOR, xmode, XEXP (XEXP (x, 0), 0), temp);
+	  x = simplify_gen_binary (LSHIFTRT, xmode,
 				   temp, XEXP (XEXP (x, 0), 1));
 
 	  return force_to_mode (x, mode, mask, next_select);
@@ -8991,8 +9019,11 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       op0 = gen_lowpart_or_truncate (op_mode,
 				     force_to_mode (XEXP (x, 0), mode, mask,
 						    next_select));
-      if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
-	x = simplify_gen_unary (code, op_mode, op0, op_mode);
+      if (op_mode != xmode || op0 != XEXP (x, 0))
+	{
+	  x = simplify_gen_unary (code, op_mode, op0, op_mode);
+	  xmode = op_mode;
+	}
       break;
 
     case NE:
@@ -9013,14 +9044,14 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
       /* We have no way of knowing if the IF_THEN_ELSE can itself be
 	 written in a narrower mode.  We play it safe and do not do so.  */
 
-      op0 = gen_lowpart_or_truncate (GET_MODE (x),
+      op0 = gen_lowpart_or_truncate (xmode,
 				     force_to_mode (XEXP (x, 1), mode,
 						    mask, next_select));
-      op1 = gen_lowpart_or_truncate (GET_MODE (x),
+      op1 = gen_lowpart_or_truncate (xmode,
 				     force_to_mode (XEXP (x, 2), mode,
 						    mask, next_select));
       if (op0 != XEXP (x, 1) || op1 != XEXP (x, 2))
-	x = simplify_gen_ternary (IF_THEN_ELSE, GET_MODE (x),
+	x = simplify_gen_ternary (IF_THEN_ELSE, xmode,
 				  GET_MODE (XEXP (x, 0)), XEXP (x, 0),
 				  op0, op1);
       break;

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [44/67] Make simplify_and_const_int take a scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (43 preceding siblings ...)
  2016-12-09 13:22 ` [43/67] Use scalar_int_mode in simplify_comparison Richard Sandiford
@ 2016-12-09 13:22 ` Richard Sandiford
  2016-12-09 13:23 ` [45/67] Make extract_left_shift " Richard Sandiford
                   ` (24 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:22 UTC (permalink / raw)
  To: gcc-patches

After previous patches, top-level calls to simplify_and_const_int
always pass a scalar_int_mode.  The only call site that needs to
be updated is the recursive one in simplify_and_const_int_1,
at which point we know "varop" has a scalar integer mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (simplify_and_const_int): Change the type of the mode
	parameter to scalar_int_mode.
	(simplify_and_const_int_1): Likewise.  Update recursive call.

diff --git a/gcc/combine.c b/gcc/combine.c
index 58a8d7d..5262bf9 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -456,9 +456,9 @@ static int rtx_equal_for_field_assignment_p (rtx, rtx, bool = false);
 static rtx make_field_assignment (rtx);
 static rtx apply_distributive_law (rtx);
 static rtx distribute_and_simplify_rtx (rtx, int);
-static rtx simplify_and_const_int_1 (machine_mode, rtx,
+static rtx simplify_and_const_int_1 (scalar_int_mode, rtx,
 				     unsigned HOST_WIDE_INT);
-static rtx simplify_and_const_int (rtx, machine_mode, rtx,
+static rtx simplify_and_const_int (rtx, scalar_int_mode, rtx,
 				   unsigned HOST_WIDE_INT);
 static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code,
 			    HOST_WIDE_INT, machine_mode, int *);
@@ -9880,7 +9880,7 @@ distribute_and_simplify_rtx (rtx x, int n)
    (const_int CONSTOP)).  Otherwise, return NULL_RTX.  */
 
 static rtx
-simplify_and_const_int_1 (machine_mode mode, rtx varop,
+simplify_and_const_int_1 (scalar_int_mode mode, rtx varop,
 			  unsigned HOST_WIDE_INT constop)
 {
   unsigned HOST_WIDE_INT nonzero;
@@ -9940,19 +9940,20 @@ simplify_and_const_int_1 (machine_mode mode, rtx varop,
      won't match a pattern either with or without this.  */
 
   if (GET_CODE (varop) == IOR || GET_CODE (varop) == XOR)
-    return
-      gen_lowpart
-	(mode,
-	 apply_distributive_law
-	 (simplify_gen_binary (GET_CODE (varop), GET_MODE (varop),
-			       simplify_and_const_int (NULL_RTX,
-						       GET_MODE (varop),
-						       XEXP (varop, 0),
-						       constop),
-			       simplify_and_const_int (NULL_RTX,
-						       GET_MODE (varop),
-						       XEXP (varop, 1),
-						       constop))));
+    {
+      scalar_int_mode varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
+      return
+	gen_lowpart
+	  (mode,
+	   apply_distributive_law
+	   (simplify_gen_binary (GET_CODE (varop), varop_mode,
+				 simplify_and_const_int (NULL_RTX, varop_mode,
+							 XEXP (varop, 0),
+							 constop),
+				 simplify_and_const_int (NULL_RTX, varop_mode,
+							 XEXP (varop, 1),
+							 constop))));
+    }
 
   /* If VAROP is PLUS, and the constant is a mask of low bits, distribute
      the AND and see if one of the operands simplifies to zero.  If so, we
@@ -9995,7 +9996,7 @@ simplify_and_const_int_1 (machine_mode mode, rtx varop,
    X is zero, we are to always construct the equivalent form.  */
 
 static rtx
-simplify_and_const_int (rtx x, machine_mode mode, rtx varop,
+simplify_and_const_int (rtx x, scalar_int_mode mode, rtx varop,
 			unsigned HOST_WIDE_INT constop)
 {
   rtx tem = simplify_and_const_int_1 (mode, varop, constop);

^ permalink raw reply	[flat|nested] 79+ messages in thread

* Re: [24/67] Replace a != BLKmode check with is_a <scalar_int_mode>
  2016-12-09 13:08 ` [24/67] Replace a != BLKmode check " Richard Sandiford
@ 2016-12-09 13:22   ` Richard Biener
  2016-12-09 14:42     ` Richard Sandiford
  0 siblings, 1 reply; 79+ messages in thread
From: Richard Biener @ 2016-12-09 13:22 UTC (permalink / raw)
  To: GCC Patches, richard.sandiford

On Fri, Dec 9, 2016 at 2:08 PM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> This patch replaces a check against BLKmode with a check
> of is_a <scalar_int_mode>, in a case where scalar integer
> modes were the only useful alternatives left.

So why's BLKmode no longer sth valid to check against?  The check is only there
to guard GET_MODE_ALIGNMENT / SLOW_UNALIGNED_ACCESS.

Richard.

> gcc/
> 2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
>             Alan Hayward  <alan.hayward@arm.com>
>             David Sherwood  <david.sherwood@arm.com>
>
>         * gimple-fold.c (gimple_fold_builtin_memory_op): Use
>         is_a <scalar_int_mode> instead of != BLKmode.
>
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index d00625b..c6b5411 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
> @@ -713,31 +713,29 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
>           unsigned ilen = tree_to_uhwi (len);
>           if (pow2p_hwi (ilen))
>             {
> +             scalar_int_mode mode;
>               tree type = lang_hooks.types.type_for_size (ilen * 8, 1);
>               if (type
> -                 && TYPE_MODE (type) != BLKmode
> -                 && (GET_MODE_SIZE (TYPE_MODE (type)) * BITS_PER_UNIT
> -                     == ilen * 8)
> +                 && is_a <scalar_int_mode> (TYPE_MODE (type), &mode)
> +                 && GET_MODE_SIZE (mode) * BITS_PER_UNIT == ilen * 8
>                   /* If the destination pointer is not aligned we must be able
>                      to emit an unaligned store.  */
> -                 && (dest_align >= GET_MODE_ALIGNMENT (TYPE_MODE (type))
> -                     || !SLOW_UNALIGNED_ACCESS (TYPE_MODE (type), dest_align)
> -                     || (optab_handler (movmisalign_optab, TYPE_MODE (type))
> +                 && (dest_align >= GET_MODE_ALIGNMENT (mode)
> +                     || !SLOW_UNALIGNED_ACCESS (mode, dest_align)
> +                     || (optab_handler (movmisalign_optab, mode)
>                           != CODE_FOR_nothing)))
>                 {
>                   tree srctype = type;
>                   tree desttype = type;
> -                 if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
> +                 if (src_align < GET_MODE_ALIGNMENT (mode))
>                     srctype = build_aligned_type (type, src_align);
>                   tree srcmem = fold_build2 (MEM_REF, srctype, src, off0);
>                   tree tem = fold_const_aggregate_ref (srcmem);
>                   if (tem)
>                     srcmem = tem;
> -                 else if (src_align < GET_MODE_ALIGNMENT (TYPE_MODE (type))
> -                          && SLOW_UNALIGNED_ACCESS (TYPE_MODE (type),
> -                                                    src_align)
> -                          && (optab_handler (movmisalign_optab,
> -                                             TYPE_MODE (type))
> +                 else if (src_align < GET_MODE_ALIGNMENT (mode)
> +                          && SLOW_UNALIGNED_ACCESS (mode, src_align)
> +                          && (optab_handler (movmisalign_optab, mode)
>                                == CODE_FOR_nothing))
>                     srcmem = NULL_TREE;
>                   if (srcmem)
> @@ -753,7 +751,7 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
>                           gimple_set_vuse (new_stmt, gimple_vuse (stmt));
>                           gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
>                         }
> -                     if (dest_align < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
> +                     if (dest_align < GET_MODE_ALIGNMENT (mode))
>                         desttype = build_aligned_type (type, dest_align);
>                       new_stmt
>                         = gimple_build_assign (fold_build2 (MEM_REF, desttype,
>

^ permalink raw reply	[flat|nested] 79+ messages in thread

* [43/67] Use scalar_int_mode in simplify_comparison
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (42 preceding siblings ...)
  2016-12-09 13:20 ` [41/67] Split scalar integer handling out of force_to_mode Richard Sandiford
@ 2016-12-09 13:22 ` Richard Sandiford
  2016-12-09 13:22 ` [44/67] Make simplify_and_const_int take a scalar_int_mode Richard Sandiford
                   ` (25 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:22 UTC (permalink / raw)
  To: gcc-patches

The main loop of simplify_comparison starts with:

      if (GET_MODE_CLASS (mode) != MODE_INT
          && ! (mode == VOIDmode
                && (GET_CODE (op0) == COMPARE || COMPARISON_P (op0))))
        break;

So VOIDmode is only acceptable when comparing a COMPARE,
EQ, NE, etc. operand against a constant.  After this, the loop
calls simplify_compare_const to:

  (a) bring the constant op1 closer to 0 where possible and
  (b) use nonzero_bits and num_sign_bit_copies to get a simpler
      constant.

(a) works for both integer and VOID modes, (b) is specific
to integer modes.

The loop then has a big switch statement that handles further
simplifications.  This switch statement checks for COMPARISON_P
codes but not for COMPARE.

This patch uses scalar_int_mode to make the split between
(a) and (b) more explicit.  It also takes the COMPARISON_P
handling out of the switch statement and does it first,
so that the rest of the loop can treat the mode as a
scalar_int_mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* combine.c (simplify_compare_const): Check that the mode is a
	scalar_int_mode (rather than VOIDmode) before testing its
	precision.
	(simplify_comparison): Move COMPARISON_P handling out of the
	loop and restrict the latter part of the loop to scalar_int_modes.
	Check is_a <scalar_int_mode> before call to HWI_COMPUTABLE_MODE_P
	and when considering SUBREG_REGs.  Use is_int_mode instead of
	checking GET_MODE_CLASS against MODE_INT.

diff --git a/gcc/combine.c b/gcc/combine.c
index 3cb92a4..58a8d7d 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -11608,7 +11608,7 @@ static enum rtx_code
 simplify_compare_const (enum rtx_code code, machine_mode mode,
 			rtx op0, rtx *pop1)
 {
-  unsigned int mode_width = GET_MODE_PRECISION (mode);
+  scalar_int_mode int_mode;
   HOST_WIDE_INT const_op = INTVAL (*pop1);
 
   /* Get the constant we are comparing against and turn off all bits
@@ -11623,10 +11623,11 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
   if (const_op
       && (code == EQ || code == NE || code == GE || code == GEU
 	  || code == LT || code == LTU)
-      && mode_width - 1 < HOST_BITS_PER_WIDE_INT
-      && pow2p_hwi (const_op & GET_MODE_MASK (mode))
-      && (nonzero_bits (op0, mode)
-	  == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (mode))))
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+      && pow2p_hwi (const_op & GET_MODE_MASK (int_mode))
+      && (nonzero_bits (op0, int_mode)
+	  == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (int_mode))))
     {
       code = (code == EQ || code == GE || code == GEU ? NE : EQ);
       const_op = 0;
@@ -11637,7 +11638,8 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
   if (const_op == -1
       && (code == EQ || code == NE || code == GT || code == LE
 	  || code == GEU || code == LTU)
-      && num_sign_bit_copies (op0, mode) == mode_width)
+      && is_a <scalar_int_mode> (mode, &int_mode)
+      && num_sign_bit_copies (op0, int_mode) == GET_MODE_PRECISION (int_mode))
     {
       code = (code == EQ || code == LE || code == GEU ? NE : EQ);
       const_op = 0;
@@ -11671,9 +11673,10 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
       /* If we are doing a <= 0 comparison on a value known to have
 	 a zero sign bit, we can replace this with == 0.  */
       else if (const_op == 0
-	       && mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (nonzero_bits (op0, mode)
-		   & (HOST_WIDE_INT_1U << (mode_width - 1)))
+	       && is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && (nonzero_bits (op0, int_mode)
+		   & (HOST_WIDE_INT_1U << (GET_MODE_PRECISION (int_mode) - 1)))
 	       == 0)
 	code = EQ;
       break;
@@ -11701,9 +11704,10 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
       /* If we are doing a > 0 comparison on a value known to have
 	 a zero sign bit, we can replace this with != 0.  */
       else if (const_op == 0
-	       && mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (nonzero_bits (op0, mode)
-		   & (HOST_WIDE_INT_1U << (mode_width - 1)))
+	       && is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && (nonzero_bits (op0, int_mode)
+		   & (HOST_WIDE_INT_1U << (GET_MODE_PRECISION (int_mode) - 1)))
 	       == 0)
 	code = NE;
       break;
@@ -11717,9 +11721,10 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
 	  /* ... fall through ...  */
 	}
       /* (unsigned) < 0x80000000 is equivalent to >= 0.  */
-      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (unsigned HOST_WIDE_INT) const_op
-	       == HOST_WIDE_INT_1U << (mode_width - 1))
+      else if (is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && ((unsigned HOST_WIDE_INT) const_op
+		   == HOST_WIDE_INT_1U << (GET_MODE_PRECISION (int_mode) - 1)))
 	{
 	  const_op = 0;
 	  code = GE;
@@ -11733,9 +11738,11 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
       if (const_op == 0)
 	code = EQ;
       /* (unsigned) <= 0x7fffffff is equivalent to >= 0.  */
-      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (unsigned HOST_WIDE_INT) const_op
-	       == (HOST_WIDE_INT_1U << (mode_width - 1)) - 1)
+      else if (is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && ((unsigned HOST_WIDE_INT) const_op
+		   == ((HOST_WIDE_INT_1U
+			<< (GET_MODE_PRECISION (int_mode) - 1)) - 1)))
 	{
 	  const_op = 0;
 	  code = GE;
@@ -11752,9 +11759,10 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
 	}
 
       /* (unsigned) >= 0x80000000 is equivalent to < 0.  */
-      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (unsigned HOST_WIDE_INT) const_op
-	       == HOST_WIDE_INT_1U << (mode_width - 1))
+      else if (is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && ((unsigned HOST_WIDE_INT) const_op
+		   == HOST_WIDE_INT_1U << (GET_MODE_PRECISION (int_mode) - 1)))
 	{
 	  const_op = 0;
 	  code = LT;
@@ -11768,9 +11776,11 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
       if (const_op == 0)
 	code = NE;
       /* (unsigned) > 0x7fffffff is equivalent to < 0.  */
-      else if (mode_width - 1 < HOST_BITS_PER_WIDE_INT
-	       && (unsigned HOST_WIDE_INT) const_op
-	       == (HOST_WIDE_INT_1U << (mode_width - 1)) - 1)
+      else if (is_a <scalar_int_mode> (mode, &int_mode)
+	       && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT
+	       && ((unsigned HOST_WIDE_INT) const_op
+		   == (HOST_WIDE_INT_1U
+		       << (GET_MODE_PRECISION (int_mode) - 1)) - 1))
 	{
 	  const_op = 0;
 	  code = LT;
@@ -11955,9 +11965,8 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 
   while (CONST_INT_P (op1))
     {
-      machine_mode mode = GET_MODE (op0);
-      unsigned int mode_width = GET_MODE_PRECISION (mode);
-      unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
+      machine_mode raw_mode = GET_MODE (op0);
+      scalar_int_mode int_mode;
       int equality_comparison_p;
       int sign_bit_comparison_p;
       int unsigned_comparison_p;
@@ -11968,14 +11977,14 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	 can handle VOIDmode if OP0 is a COMPARE or a comparison
 	 operation.  */
 
-      if (GET_MODE_CLASS (mode) != MODE_INT
-	  && ! (mode == VOIDmode
+      if (GET_MODE_CLASS (raw_mode) != MODE_INT
+	  && ! (raw_mode == VOIDmode
 		&& (GET_CODE (op0) == COMPARE || COMPARISON_P (op0))))
 	break;
 
       /* Try to simplify the compare to constant, possibly changing the
 	 comparison op, and/or changing op1 to zero.  */
-      code = simplify_compare_const (code, mode, op0, &op1);
+      code = simplify_compare_const (code, raw_mode, op0, &op1);
       const_op = INTVAL (op1);
 
       /* Compute some predicates to simplify code below.  */
@@ -11987,16 +11996,62 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 
       /* If this is a sign bit comparison and we can do arithmetic in
 	 MODE, say that we will only be needing the sign bit of OP0.  */
-      if (sign_bit_comparison_p && HWI_COMPUTABLE_MODE_P (mode))
-	op0 = force_to_mode (op0, mode,
+      if (sign_bit_comparison_p
+	  && is_a <scalar_int_mode> (raw_mode, &int_mode)
+	  && HWI_COMPUTABLE_MODE_P (int_mode))
+	op0 = force_to_mode (op0, int_mode,
 			     HOST_WIDE_INT_1U
-			     << (GET_MODE_PRECISION (mode) - 1),
+			     << (GET_MODE_PRECISION (int_mode) - 1),
 			     0);
 
+      if (COMPARISON_P (op0))
+	{
+	  /* We can't do anything if OP0 is a condition code value, rather
+	     than an actual data value.  */
+	  if (const_op != 0
+	      || CC0_P (XEXP (op0, 0))
+	      || GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
+	    break;
+
+	  /* Get the two operands being compared.  */
+	  if (GET_CODE (XEXP (op0, 0)) == COMPARE)
+	    tem = XEXP (XEXP (op0, 0), 0), tem1 = XEXP (XEXP (op0, 0), 1);
+	  else
+	    tem = XEXP (op0, 0), tem1 = XEXP (op0, 1);
+
+	  /* Check for the cases where we simply want the result of the
+	     earlier test or the opposite of that result.  */
+	  if (code == NE || code == EQ
+	      || (val_signbit_known_set_p (raw_mode, STORE_FLAG_VALUE)
+		  && (code == LT || code == GE)))
+	    {
+	      enum rtx_code new_code;
+	      if (code == LT || code == NE)
+		new_code = GET_CODE (op0);
+	      else
+		new_code = reversed_comparison_code (op0, NULL);
+
+	      if (new_code != UNKNOWN)
+		{
+		  code = new_code;
+		  op0 = tem;
+		  op1 = tem1;
+		  continue;
+		}
+	    }
+	  break;
+	}
+
+      if (raw_mode == VOIDmode)
+	break;
+      scalar_int_mode mode = as_a <scalar_int_mode> (raw_mode);
+
       /* Now try cases based on the opcode of OP0.  If none of the cases
 	 does a "continue", we exit this loop immediately after the
 	 switch.  */
 
+      unsigned int mode_width = GET_MODE_PRECISION (mode);
+      unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
       switch (GET_CODE (op0))
 	{
 	case ZERO_EXTRACT:
@@ -12141,8 +12196,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	     insn of the given mode, since we'd have to revert it
 	     later on, and then we wouldn't know whether to sign- or
 	     zero-extend.  */
-	  mode = GET_MODE (XEXP (op0, 0));
-	  if (GET_MODE_CLASS (mode) == MODE_INT
+	  if (is_int_mode (GET_MODE (XEXP (op0, 0)), &mode)
 	      && ! unsigned_comparison_p
 	      && HWI_COMPUTABLE_MODE_P (mode)
 	      && trunc_int_for_mode (const_op, mode) == const_op
@@ -12176,11 +12230,12 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 
 	  if (mode_width <= HOST_BITS_PER_WIDE_INT
 	      && subreg_lowpart_p (op0)
-	      && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0))) > mode_width
+	      && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op0)),
+					 &inner_mode)
+	      && GET_MODE_PRECISION (inner_mode) > mode_width
 	      && GET_CODE (SUBREG_REG (op0)) == PLUS
 	      && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)))
 	    {
-	      machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
 	      rtx a = XEXP (SUBREG_REG (op0), 0);
 	      HOST_WIDE_INT c1 = -INTVAL (XEXP (SUBREG_REG (op0), 1));
 
@@ -12217,21 +12272,19 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	      && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0))) < mode_width)
 	    ;
 	  else if (subreg_lowpart_p (op0)
-		   && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-		   && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
+		   && GET_MODE_CLASS (mode) == MODE_INT
+		   && is_int_mode (GET_MODE (SUBREG_REG (op0)), &inner_mode)
 		   && (code == NE || code == EQ)
-		   && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0)))
-		       <= HOST_BITS_PER_WIDE_INT)
+		   && GET_MODE_PRECISION (inner_mode) <= HOST_BITS_PER_WIDE_INT
 		   && !paradoxical_subreg_p (op0)
-		   && (nonzero_bits (SUBREG_REG (op0),
-				     GET_MODE (SUBREG_REG (op0)))
-		       & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+		   && (nonzero_bits (SUBREG_REG (op0), inner_mode)
+		       & ~GET_MODE_MASK (mode)) == 0)
 	    {
 	      /* Remove outer subregs that don't do anything.  */
-	      tem = gen_lowpart (GET_MODE (SUBREG_REG (op0)), op1);
+	      tem = gen_lowpart (inner_mode, op1);
 
-	      if ((nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
-		   & ~GET_MODE_MASK (GET_MODE (op0))) == 0)
+	      if ((nonzero_bits (tem, inner_mode)
+		   & ~GET_MODE_MASK (mode)) == 0)
 		{
 		  op0 = SUBREG_REG (op0);
 		  op1 = tem;
@@ -12245,8 +12298,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	  /* FALLTHROUGH */
 
 	case ZERO_EXTEND:
-	  mode = GET_MODE (XEXP (op0, 0));
-	  if (GET_MODE_CLASS (mode) == MODE_INT
+	  if (is_int_mode (GET_MODE (XEXP (op0, 0)), &mode)
 	      && (unsigned_comparison_p || equality_comparison_p)
 	      && HWI_COMPUTABLE_MODE_P (mode)
 	      && (unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (mode)
@@ -12335,45 +12387,6 @@ simplify_comparison (e