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 ` [5/67] Small tweak to array_value_type 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
                   ` (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 ` [6/67] Make GET_MODE_WIDER return an opt_mode 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

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
                   ` (4 preceding siblings ...)
  2016-12-09 12:55 ` [5/67] Small tweak to array_value_type 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

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 ` [6/67] Make GET_MODE_WIDER return an opt_mode 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 ` [12/67] Use opt_scalar_float_mode when iterating over float modes Richard Sandiford
                   ` (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
                   ` (11 preceding siblings ...)
  2016-12-09 13:00 ` [11/67] Add a float_mode_for_size helper function Richard Sandiford
@ 2016-12-09 13:00 ` Richard Biener
  2016-12-09 13:54   ` 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, 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
                   ` (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 Sandiford
  2016-12-09 13:00 ` [11/67] Add a float_mode_for_size helper function Richard Sandiford
                   ` (58 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
                   ` (10 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:00 ` [0/67] Add wrapper classes for machine_modes Richard Biener
                   ` (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 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 ` [0/67] Add wrapper classes for machine_modes Richard Biener
@ 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 ` [15/67] Add scalar_int_mode 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
                   ` (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 ` [16/67] Add scalar_int_mode_pod 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

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
                   ` (15 preceding siblings ...)
  2016-12-09 13:03 ` [15/67] Add scalar_int_mode 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

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 ` [16/67] Add scalar_int_mode_pod Richard Sandiford
@ 2016-12-09 13:04 ` Richard Sandiford
  2016-12-09 13:05 ` [18/67] Make int_mode_for_mode return an opt_scalar_int_mode 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
                   ` (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 ` [19/67] Add a smallest_int_mode_for_size helper function 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

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
                   ` (18 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: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

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 ` [19/67] Add a smallest_int_mode_for_size helper function 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 ` [26/67] Use is_a <scalar_int_mode> in subreg/extract simplifications 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
                   ` (26 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: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 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
                   ` (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 ` [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP 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 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 ` [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP 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 ` [38/67] Move SCALAR_INT_MODE_P out of strict_volatile_bitfield_p 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
                   ` (37 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: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

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
                   ` (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 ` [37/67] Use scalar_int_mode when emitting cstores 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

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 ` [37/67] Use scalar_int_mode when emitting cstores 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 ` [44/67] Make simplify_and_const_int take a scalar_int_mode 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
                   ` (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 ` [43/67] Use scalar_int_mode in simplify_comparison 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

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
                   ` (43 preceding siblings ...)
  2016-12-09 13:22 ` [44/67] Make simplify_and_const_int take a scalar_int_mode Richard Sandiford
@ 2016-12-09 13:22 ` Richard Sandiford
  2016-12-09 13:23 ` [46/67] Make widest_int_mode_for_size return a scalar_int_mode 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

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 (enum rtx_code code, rtx *pop0, rtx *pop1)
 	    }
 	  break;
 
-	case EQ:  case NE:
-	case UNEQ:  case LTGT:
-	case LT:  case LTU:  case UNLT:  case LE:  case LEU:  case UNLE:
-	case GT:  case GTU:  case UNGT:  case GE:  case GEU:  case UNGE:
-	case UNORDERED: case ORDERED:
-	  /* 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 (GET_MODE (op0), 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;
 
 	case IOR:
 	  /* The sign bit of (ior (plus X (const_int -1)) X) is nonzero
@@ -12645,7 +12658,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
 	    {
 	      rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0);
 	      rtx add_const = XEXP (XEXP (op0, 0), 1);
-	      rtx new_const = simplify_gen_binary (ASHIFTRT, GET_MODE (op0),
+	      rtx new_const = simplify_gen_binary (ASHIFTRT, mode,
 						   add_const, XEXP (op0, 1));
 
 	      op0 = simplify_gen_binary (PLUS, tmode,

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

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

The comment for widest_int_mode said that it returns "the widest integer
mode no wider than SIZE", but it actually returns the widest integer
mode that is narrower than SIZE.  In practice SIZE is always greater
than 1, so it can always pick QImode in the worst case.  The VOIDmode
paths seem to be dead.

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

	* expr.c (widest_int_mode_for_size): Make the comment match the code.
	Return a scalar_int_mode and assert that the size is greater than
	one byte.
	(by_pieces_ninsns): Update accordingly and remove VOIDmode handling.
	(op_by_pieces_d::op_by_pieces_d): Likewise.
	(op_by_pieces_d::run): Likewise.
	(can_store_by_pieces): Likewise.

diff --git a/gcc/expr.c b/gcc/expr.c
index d54cc65..408a8bd 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -720,19 +720,21 @@ alignment_for_piecewise_move (unsigned int max_pieces, unsigned int align)
   return align;
 }
 
-/* Return the widest integer mode no wider than SIZE.  If no such mode
-   can be found, return VOIDmode.  */
+/* Return the widest integer mode that is narrower than SIZE bytes.  */
 
-static machine_mode
+static scalar_int_mode
 widest_int_mode_for_size (unsigned int size)
 {
-  machine_mode tmode, mode = VOIDmode;
+  scalar_int_mode result = NARROWEST_INT_MODE;
 
+  gcc_checking_assert (size > 1);
+
+  opt_scalar_int_mode tmode;
   FOR_EACH_MODE_IN_CLASS (tmode, MODE_INT)
-    if (GET_MODE_SIZE (tmode) < size)
-      mode = tmode;
+    if (GET_MODE_SIZE (*tmode) < size)
+      result = *tmode;
 
-  return mode;
+  return result;
 }
 
 /* Determine whether an operation OP on LEN bytes with alignment ALIGN can
@@ -769,13 +771,9 @@ by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align,
 
   while (max_size > 1 && l > 0)
     {
-      machine_mode mode;
+      scalar_int_mode mode = widest_int_mode_for_size (max_size);
       enum insn_code icode;
 
-      mode = widest_int_mode_for_size (max_size);
-
-      if (mode == VOIDmode)
-	break;
       unsigned int modesize = GET_MODE_SIZE (mode);
 
       icode = optab_handler (mov_optab, mode);
@@ -1051,7 +1049,7 @@ op_by_pieces_d::op_by_pieces_d (rtx to, bool to_load,
   if (by_pieces_ninsns (len, align, m_max_size, MOVE_BY_PIECES) > 2)
     {
       /* Find the mode of the largest comparison.  */
-      machine_mode mode = widest_int_mode_for_size (m_max_size);
+      scalar_int_mode mode = widest_int_mode_for_size (m_max_size);
 
       m_from.decide_autoinc (mode, m_reverse, len);
       m_to.decide_autoinc (mode, m_reverse, len);
@@ -1071,10 +1069,7 @@ op_by_pieces_d::run ()
 {
   while (m_max_size > 1 && m_len > 0)
     {
-      machine_mode mode = widest_int_mode_for_size (m_max_size);
-
-      if (mode == VOIDmode)
-	break;
+      scalar_int_mode mode = widest_int_mode_for_size (m_max_size);
 
       if (prepare_mode (mode, m_align))
 	{
@@ -1285,7 +1280,6 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
   unsigned HOST_WIDE_INT l;
   unsigned int max_size;
   HOST_WIDE_INT offset = 0;
-  machine_mode mode;
   enum insn_code icode;
   int reverse;
   /* cst is set but not used if LEGITIMATE_CONSTANT doesn't use it.  */
@@ -1314,10 +1308,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
       max_size = STORE_MAX_PIECES + 1;
       while (max_size > 1 && l > 0)
 	{
-	  mode = widest_int_mode_for_size (max_size);
-
-	  if (mode == VOIDmode)
-	    break;
+	  scalar_int_mode mode = widest_int_mode_for_size (max_size);
 
 	  icode = optab_handler (mov_optab, mode);
 	  if (icode != CODE_FOR_nothing

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

* [45/67] Make extract_left_shift take a scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (45 preceding siblings ...)
  2016-12-09 13:23 ` [46/67] Make widest_int_mode_for_size return a scalar_int_mode Richard Sandiford
@ 2016-12-09 13:23 ` Richard Sandiford
  2016-12-09 13:24 ` [47/67] Make subroutines of nonzero_bits operate on scalar_int_mode Richard Sandiford
                   ` (22 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:23 UTC (permalink / raw)
  To: gcc-patches

This patch passes the mode of the shifted value to extract_left_shift
and updates the only caller so that the mode is 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 (extract_left_shift): Add a mode argument and update
	recursive calls.
	(make_compound_operation_int): Change the type of the mode parameter
	to scalar_int_mode and update the call to extract_left_shift.

diff --git a/gcc/combine.c b/gcc/combine.c
index 5262bf9..fac82d4 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -442,7 +442,6 @@ static rtx expand_compound_operation (rtx);
 static const_rtx expand_field_assignment (const_rtx);
 static rtx make_extraction (machine_mode, rtx, HOST_WIDE_INT,
 			    rtx, unsigned HOST_WIDE_INT, int, int, int);
-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);
@@ -7778,14 +7777,14 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
   return new_rtx;
 }
 \f
-/* See if X contains an ASHIFT of COUNT or more bits that can be commuted
-   with any other operations in X.  Return X without that shift if so.  */
+/* See if X (of mode MODE) contains an ASHIFT of COUNT or more bits that
+   can be commuted with any other operations in X.  Return X without
+   that shift if so.  */
 
 static rtx
-extract_left_shift (rtx x, int count)
+extract_left_shift (scalar_int_mode mode, rtx x, int count)
 {
   enum rtx_code code = GET_CODE (x);
-  machine_mode mode = GET_MODE (x);
   rtx tem;
 
   switch (code)
@@ -7801,7 +7800,7 @@ extract_left_shift (rtx x, int count)
       break;
 
     case NEG:  case NOT:
-      if ((tem = extract_left_shift (XEXP (x, 0), count)) != 0)
+      if ((tem = extract_left_shift (mode, XEXP (x, 0), count)) != 0)
 	return simplify_gen_unary (code, mode, tem, mode);
 
       break;
@@ -7812,7 +7811,7 @@ extract_left_shift (rtx x, int count)
       if (CONST_INT_P (XEXP (x, 1))
 	  && (UINTVAL (XEXP (x, 1))
 	      & (((HOST_WIDE_INT_1U << count)) - 1)) == 0
-	  && (tem = extract_left_shift (XEXP (x, 0), count)) != 0)
+	  && (tem = extract_left_shift (mode, XEXP (x, 0), count)) != 0)
 	{
 	  HOST_WIDE_INT val = INTVAL (XEXP (x, 1)) >> count;
 	  return simplify_gen_binary (code, mode, tem,
@@ -7840,7 +7839,7 @@ extract_left_shift (rtx x, int count)
    - Return a new rtx, which the caller returns directly.  */
 
 static rtx
-make_compound_operation_int (machine_mode mode, rtx *x_ptr,
+make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
 			     enum rtx_code in_code,
 			     enum rtx_code *next_code_ptr)
 {
@@ -8147,7 +8146,7 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
 	  && INTVAL (rhs) >= 0
 	  && INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
 	  && INTVAL (rhs) < mode_width
-	  && (new_rtx = extract_left_shift (lhs, INTVAL (rhs))) != 0)
+	  && (new_rtx = extract_left_shift (mode, lhs, INTVAL (rhs))) != 0)
 	new_rtx = make_extraction (mode, make_compound_operation (new_rtx, next_code),
 			       0, NULL_RTX, mode_width - INTVAL (rhs),
 			       code == LSHIFTRT, 0, in_code == COMPARE);

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

* [47/67] Make subroutines of nonzero_bits operate on scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (46 preceding siblings ...)
  2016-12-09 13:23 ` [45/67] Make extract_left_shift take " Richard Sandiford
@ 2016-12-09 13:24 ` Richard Sandiford
  2016-12-09 13:25 ` [48/67] Make subroutines of num_sign_bit_copies " Richard Sandiford
                   ` (21 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:24 UTC (permalink / raw)
  To: gcc-patches

nonzero_bits1 assumed that all bits of a floating-point or vector mode
were needed.  It seems likely that fixed-point modes should have been
handled in the same way.  After excluding those, the only remaining
modes that are likely to be useful are scalar integer ones.

This patch moves the mode class check to nonzero_bits itself, along
with the handling of mode == VOIDmode.  The subroutines of nonzero_bits
can then take scalar_int_modes.

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

	* rtlanal.c (nonzero_bits): Handle VOIDmode here rather than
	in subroutines.  Return the mode mask for non-integer modes.
	(cached_nonzero_bits): Change the type of the mode parameter
	to scalar_int_mode.
	(nonzero_bits1): Likewise.  Remove early exit for other mode
	classes.  Handle CONST_INT_P first and then check whether X
	also has a scalar integer mode.

diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index a7fb5cf..84e19e4 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -43,10 +43,10 @@ static bool covers_regno_no_parallel_p (const_rtx, unsigned int);
 static int computed_jump_p_1 (const_rtx);
 static void parms_set (rtx, const_rtx, void *);
 
-static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, machine_mode,
+static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, scalar_int_mode,
                                                    const_rtx, machine_mode,
                                                    unsigned HOST_WIDE_INT);
-static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, machine_mode,
+static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, scalar_int_mode,
 					     const_rtx, machine_mode,
                                              unsigned HOST_WIDE_INT);
 static unsigned int cached_num_sign_bit_copies (const_rtx, machine_mode, const_rtx,
@@ -4197,7 +4197,12 @@ default_address_cost (rtx x, machine_mode, addr_space_t, bool speed)
 unsigned HOST_WIDE_INT
 nonzero_bits (const_rtx x, machine_mode mode)
 {
-  return cached_nonzero_bits (x, mode, NULL_RTX, VOIDmode, 0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (x);
+  scalar_int_mode int_mode;
+  if (!is_a <scalar_int_mode> (mode, &int_mode))
+    return GET_MODE_MASK (mode);
+  return cached_nonzero_bits (x, int_mode, NULL_RTX, VOIDmode, 0);
 }
 
 unsigned int
@@ -4241,7 +4246,7 @@ nonzero_bits_binary_arith_p (const_rtx x)
    identical subexpressions on the first or the second level.  */
 
 static unsigned HOST_WIDE_INT
-cached_nonzero_bits (const_rtx x, machine_mode mode, const_rtx known_x,
+cached_nonzero_bits (const_rtx x, scalar_int_mode mode, const_rtx known_x,
 		     machine_mode known_mode,
 		     unsigned HOST_WIDE_INT known_ret)
 {
@@ -4294,7 +4299,7 @@ cached_nonzero_bits (const_rtx x, machine_mode mode, const_rtx known_x,
    an arithmetic operation, we can do better.  */
 
 static unsigned HOST_WIDE_INT
-nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
+nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
 	       machine_mode known_mode,
 	       unsigned HOST_WIDE_INT known_ret)
 {
@@ -4302,19 +4307,31 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
   unsigned HOST_WIDE_INT inner_nz;
   enum rtx_code code;
   machine_mode inner_mode;
+  scalar_int_mode xmode;
+
   unsigned int mode_width = GET_MODE_PRECISION (mode);
 
-  /* For floating-point and vector values, assume all bits are needed.  */
-  if (FLOAT_MODE_P (GET_MODE (x)) || FLOAT_MODE_P (mode)
-      || VECTOR_MODE_P (GET_MODE (x)) || VECTOR_MODE_P (mode))
+  if (CONST_INT_P (x))
+    {
+      if (SHORT_IMMEDIATES_SIGN_EXTEND
+	  && INTVAL (x) > 0
+	  && mode_width < BITS_PER_WORD
+	  && (UINTVAL (x) & (HOST_WIDE_INT_1U << (mode_width - 1))) != 0)
+	return UINTVAL (x) | (HOST_WIDE_INT_M1U << mode_width);
+
+      return UINTVAL (x);
+    }
+
+  if (!is_a <scalar_int_mode> (GET_MODE (x), &xmode))
     return nonzero;
+  unsigned int xmode_width = GET_MODE_PRECISION (xmode);
 
   /* If X is wider than MODE, use its mode instead.  */
-  if (GET_MODE_PRECISION (GET_MODE (x)) > mode_width)
+  if (xmode_width > mode_width)
     {
-      mode = GET_MODE (x);
+      mode = xmode;
       nonzero = GET_MODE_MASK (mode);
-      mode_width = GET_MODE_PRECISION (mode);
+      mode_width = xmode_width;
     }
 
   if (mode_width > HOST_BITS_PER_WIDE_INT)
@@ -4330,15 +4347,13 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
      not known to be zero.  */
 
   if (!WORD_REGISTER_OPERATIONS
-      && GET_MODE (x) != VOIDmode
-      && GET_MODE (x) != mode
-      && GET_MODE_PRECISION (GET_MODE (x)) <= BITS_PER_WORD
-      && GET_MODE_PRECISION (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
-      && GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (GET_MODE (x)))
+      && mode_width > xmode_width
+      && xmode_width <= BITS_PER_WORD
+      && xmode_width <= HOST_BITS_PER_WIDE_INT)
     {
-      nonzero &= cached_nonzero_bits (x, GET_MODE (x),
+      nonzero &= cached_nonzero_bits (x, xmode,
 				      known_x, known_mode, known_ret);
-      nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
+      nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (xmode);
       return nonzero;
     }
 
@@ -4355,7 +4370,8 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	 we can do this only if the target does not support different pointer
 	 or address modes depending on the address space.  */
       if (target_default_pointer_address_modes_p ()
-	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+	  && POINTERS_EXTEND_UNSIGNED
+	  && xmode == Pmode
 	  && REG_POINTER (x)
 	  && !targetm.have_ptr_extend ())
 	nonzero &= GET_MODE_MASK (ptr_mode);
@@ -4398,22 +4414,12 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	return nonzero_for_hook;
       }
 
-    case CONST_INT:
-      /* If X is negative in MODE, sign-extend the value.  */
-      if (SHORT_IMMEDIATES_SIGN_EXTEND && INTVAL (x) > 0
-	  && mode_width < BITS_PER_WORD
-	  && (UINTVAL (x) & (HOST_WIDE_INT_1U << (mode_width - 1)))
-	     != 0)
-	return UINTVAL (x) | (HOST_WIDE_INT_M1U << mode_width);
-
-      return UINTVAL (x);
-
     case MEM:
       /* In many, if not most, RISC machines, reading a byte from memory
 	 zeros the rest of the register.  Noticing that fact saves a lot
 	 of extra zero-extends.  */
-      if (load_extend_op (GET_MODE (x)) == ZERO_EXTEND)
-	nonzero &= GET_MODE_MASK (GET_MODE (x));
+      if (load_extend_op (xmode) == ZERO_EXTEND)
+	nonzero &= GET_MODE_MASK (xmode);
       break;
 
     case EQ:  case NE:
@@ -4430,7 +4436,7 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	 operation in, and not the actual operation mode.  We can wind
 	 up with (subreg:DI (gt:V4HI x y)), and we don't have anything
 	 that describes the results of a vector compare.  */
-      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+      if (GET_MODE_CLASS (xmode) == MODE_INT
 	  && mode_width <= HOST_BITS_PER_WIDE_INT)
 	nonzero = STORE_FLAG_VALUE;
       break;
@@ -4439,21 +4445,19 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 #if 0
       /* Disabled to avoid exponential mutual recursion between nonzero_bits
 	 and num_sign_bit_copies.  */
-      if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
-	  == GET_MODE_PRECISION (GET_MODE (x)))
+      if (num_sign_bit_copies (XEXP (x, 0), xmode) == xmode_width)
 	nonzero = 1;
 #endif
 
-      if (GET_MODE_PRECISION (GET_MODE (x)) < mode_width)
-	nonzero |= (GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x)));
+      if (xmode_width < mode_width)
+	nonzero |= (GET_MODE_MASK (mode) & ~GET_MODE_MASK (xmode));
       break;
 
     case ABS:
 #if 0
       /* Disabled to avoid exponential mutual recursion between nonzero_bits
 	 and num_sign_bit_copies.  */
-      if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
-	  == GET_MODE_PRECISION (GET_MODE (x)))
+      if (num_sign_bit_copies (XEXP (x, 0), xmode) == xmode_width)
 	nonzero = 1;
 #endif
       break;
@@ -4526,7 +4530,7 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	unsigned HOST_WIDE_INT nz1
 	  = cached_nonzero_bits (XEXP (x, 1), mode,
 				 known_x, known_mode, known_ret);
-	int sign_index = GET_MODE_PRECISION (GET_MODE (x)) - 1;
+	int sign_index = xmode_width - 1;
 	int width0 = floor_log2 (nz0) + 1;
 	int width1 = floor_log2 (nz1) + 1;
 	int low0 = ctz_or_zero (nz0);
@@ -4598,8 +4602,8 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	 been zero-extended, we know that at least the high-order bits
 	 are zero, though others might be too.  */
       if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x))
-	nonzero = GET_MODE_MASK (GET_MODE (x))
-		  & cached_nonzero_bits (SUBREG_REG (x), GET_MODE (x),
+	nonzero = GET_MODE_MASK (xmode)
+		  & cached_nonzero_bits (SUBREG_REG (x), xmode,
 					 known_x, known_mode, known_ret);
 
       /* If the inner mode is a single word for both the host and target
@@ -4623,10 +4627,8 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 		   ? val_signbit_known_set_p (inner_mode, nonzero)
 		   : extend_op != ZERO_EXTEND)
 	       || (!MEM_P (SUBREG_REG (x)) && !REG_P (SUBREG_REG (x))))
-	      && GET_MODE_PRECISION (GET_MODE (x))
-		  > GET_MODE_PRECISION (inner_mode))
-	    nonzero
-	      |= (GET_MODE_MASK (GET_MODE (x)) & ~GET_MODE_MASK (inner_mode));
+	      && xmode_width > GET_MODE_PRECISION (inner_mode))
+	    nonzero |= (GET_MODE_MASK (xmode) & ~GET_MODE_MASK (inner_mode));
 	}
       break;
 
@@ -4635,7 +4637,7 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
     case ASHIFT:
     case ROTATE:
       /* The nonzero bits are in two classes: any bits within MODE
-	 that aren't in GET_MODE (x) are always significant.  The rest of the
+	 that aren't in xmode are always significant.  The rest of the
 	 nonzero bits are those that are significant in the operand of
 	 the shift when shifted the appropriate number of bits.  This
 	 shows that high-order bits are cleared by the right shift and
@@ -4643,19 +4645,17 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
       if (CONST_INT_P (XEXP (x, 1))
 	  && INTVAL (XEXP (x, 1)) >= 0
 	  && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT
-	  && INTVAL (XEXP (x, 1)) < GET_MODE_PRECISION (GET_MODE (x)))
+	  && INTVAL (XEXP (x, 1)) < xmode_width)
 	{
-	  machine_mode inner_mode = GET_MODE (x);
-	  unsigned int width = GET_MODE_PRECISION (inner_mode);
 	  int count = INTVAL (XEXP (x, 1));
-	  unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
+	  unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (xmode);
 	  unsigned HOST_WIDE_INT op_nonzero
 	    = cached_nonzero_bits (XEXP (x, 0), mode,
 				   known_x, known_mode, known_ret);
 	  unsigned HOST_WIDE_INT inner = op_nonzero & mode_mask;
 	  unsigned HOST_WIDE_INT outer = 0;
 
-	  if (mode_width > width)
+	  if (mode_width > xmode_width)
 	    outer = (op_nonzero & nonzero & ~mode_mask);
 
 	  if (code == LSHIFTRT)
@@ -4667,15 +4667,16 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	      /* If the sign bit may have been nonzero before the shift, we
 		 need to mark all the places it could have been copied to
 		 by the shift as possibly nonzero.  */
-	      if (inner & (HOST_WIDE_INT_1U << (width - 1 - count)))
-		inner |= ((HOST_WIDE_INT_1U << count) - 1)
-			   << (width - count);
+	      if (inner & (HOST_WIDE_INT_1U << (xmode_width - 1 - count)))
+		inner |= (((HOST_WIDE_INT_1U << count) - 1)
+			  << (xmode_width - count));
 	    }
 	  else if (code == ASHIFT)
 	    inner <<= count;
 	  else
-	    inner = ((inner << (count % width)
-		      | (inner >> (width - (count % width)))) & mode_mask);
+	    inner = ((inner << (count % xmode_width)
+		      | (inner >> (xmode_width - (count % xmode_width))))
+		     & mode_mask);
 
 	  nonzero &= (outer | inner);
 	}

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

* [48/67] Make subroutines of num_sign_bit_copies operate on scalar_int_mode
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (47 preceding siblings ...)
  2016-12-09 13:24 ` [47/67] Make subroutines of nonzero_bits operate on scalar_int_mode Richard Sandiford
@ 2016-12-09 13:25 ` Richard Sandiford
  2016-12-09 13:25 ` [49/67] Simplify nonzero/num_sign_bits hooks Richard Sandiford
                   ` (20 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:25 UTC (permalink / raw)
  To: gcc-patches

Similarly to the nonzero_bits patch, this one moves the mode
class check and VOIDmode handling from num_sign_bit_copies1
to num_sign_bit_copies itself, then changes the subroutines
to operate on scalar_int_modes.

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

	* rtlanal.c (num_sign_bit_copies): Handle VOIDmode here rather
	than in subroutines.  Return 1 for non-integer modes.
	(cached_num_sign_bit_copies): Change the type of the mode parameter
	to scalar_int_mode.
	(num_sign_bit_copies1): Likewise.  Remove early exit for other mode
	classes.  Handle CONST_INT_P first and then check whether X also
	has a scalar integer mode.  Check the same thing for inner registers
	of a SUBREG and for values that are being extended or truncated.

diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 84e19e4..b70f6ce 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -49,11 +49,12 @@ static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, scalar_int_mode,
 static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, scalar_int_mode,
 					     const_rtx, machine_mode,
                                              unsigned HOST_WIDE_INT);
-static unsigned int cached_num_sign_bit_copies (const_rtx, machine_mode, const_rtx,
-                                                machine_mode,
+static unsigned int cached_num_sign_bit_copies (const_rtx, scalar_int_mode,
+						const_rtx, machine_mode,
                                                 unsigned int);
-static unsigned int num_sign_bit_copies1 (const_rtx, machine_mode, const_rtx,
-                                          machine_mode, unsigned int);
+static unsigned int num_sign_bit_copies1 (const_rtx, scalar_int_mode,
+					  const_rtx, machine_mode,
+					  unsigned int);
 
 rtx_subrtx_bound_info rtx_all_subrtx_bounds[NUM_RTX_CODE];
 rtx_subrtx_bound_info rtx_nonconst_subrtx_bounds[NUM_RTX_CODE];
@@ -4208,7 +4209,12 @@ nonzero_bits (const_rtx x, machine_mode mode)
 unsigned int
 num_sign_bit_copies (const_rtx x, machine_mode mode)
 {
-  return cached_num_sign_bit_copies (x, mode, NULL_RTX, VOIDmode, 0);
+  if (mode == VOIDmode)
+    mode = GET_MODE (x);
+  scalar_int_mode int_mode;
+  if (!is_a <scalar_int_mode> (mode, &int_mode))
+    return 1;
+  return cached_num_sign_bit_copies (x, int_mode, NULL_RTX, VOIDmode, 0);
 }
 
 /* Return true if nonzero_bits1 might recurse into both operands
@@ -4775,8 +4781,8 @@ num_sign_bit_copies_binary_arith_p (const_rtx x)
    first or the second level.  */
 
 static unsigned int
-cached_num_sign_bit_copies (const_rtx x, machine_mode mode, const_rtx known_x,
-			    machine_mode known_mode,
+cached_num_sign_bit_copies (const_rtx x, scalar_int_mode mode,
+			    const_rtx known_x, machine_mode known_mode,
 			    unsigned int known_ret)
 {
   if (x == known_x && mode == known_mode)
@@ -4821,44 +4827,48 @@ cached_num_sign_bit_copies (const_rtx x, machine_mode mode, const_rtx known_x,
 }
 
 /* Return the number of bits at the high-order end of X that are known to
-   be equal to the sign bit.  X will be used in mode MODE; if MODE is
-   VOIDmode, X will be used in its own mode.  The returned value  will always
-   be between 1 and the number of bits in MODE.  */
+   be equal to the sign bit.  X will be used in mode MODE.  The returned
+   value will always be between 1 and the number of bits in MODE.  */
 
 static unsigned int
-num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
+num_sign_bit_copies1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
 		      machine_mode known_mode,
 		      unsigned int known_ret)
 {
   enum rtx_code code = GET_CODE (x);
-  machine_mode inner_mode;
+  unsigned int bitwidth = GET_MODE_PRECISION (mode);
   int num0, num1, result;
   unsigned HOST_WIDE_INT nonzero;
 
-  /* If we weren't given a mode, use the mode of X.  If the mode is still
-     VOIDmode, we don't know anything.  Likewise if one of the modes is
-     floating-point.  */
+  if (CONST_INT_P (x))
+    {
+      /* If the constant is negative, take its 1's complement and remask.
+	 Then see how many zero bits we have.  */
+      nonzero = UINTVAL (x) & GET_MODE_MASK (mode);
+      if (bitwidth <= HOST_BITS_PER_WIDE_INT
+	  && (nonzero & (HOST_WIDE_INT_1U << (bitwidth - 1))) != 0)
+	nonzero = (~nonzero) & GET_MODE_MASK (mode);
 
-  if (mode == VOIDmode)
-    mode = GET_MODE (x);
+      return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
+    }
 
   gcc_checking_assert (mode != BLKmode);
 
-  if (mode == VOIDmode || FLOAT_MODE_P (mode) || FLOAT_MODE_P (GET_MODE (x))
-      || VECTOR_MODE_P (GET_MODE (x)) || VECTOR_MODE_P (mode))
+  scalar_int_mode xmode, inner_mode;
+  if (!is_a <scalar_int_mode> (GET_MODE (x), &xmode))
     return 1;
 
+  unsigned int xmode_width = GET_MODE_PRECISION (xmode);
+
   /* For a smaller mode, just ignore the high bits.  */
-  unsigned int bitwidth = GET_MODE_PRECISION (mode);
-  if (bitwidth < GET_MODE_PRECISION (GET_MODE (x)))
+  if (bitwidth < xmode_width)
     {
-      num0 = cached_num_sign_bit_copies (x, GET_MODE (x),
+      num0 = cached_num_sign_bit_copies (x, xmode,
 					 known_x, known_mode, known_ret);
-      return MAX (1,
-		  num0 - (int) (GET_MODE_PRECISION (GET_MODE (x)) - bitwidth));
+      return MAX (1, num0 - (int) (xmode_width - bitwidth));
     }
 
-  if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_PRECISION (GET_MODE (x)))
+  if (bitwidth > xmode_width)
     {
       /* If this machine does not do all register operations on the entire
 	 register and MODE is wider than the mode of X, we can say nothing
@@ -4869,8 +4879,8 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
       /* Likewise on machines that do, if the mode of the object is smaller
 	 than a word and loads of that size don't sign extend, we can say
 	 nothing about the high order bits.  */
-      if (GET_MODE_PRECISION (GET_MODE (x)) < BITS_PER_WORD
-	  && load_extend_op (GET_MODE (x)) != SIGN_EXTEND)
+      if (xmode_width < BITS_PER_WORD
+	  && load_extend_op (xmode) != SIGN_EXTEND)
 	return 1;
     }
 
@@ -4887,7 +4897,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	 we can do this only if the target does not support different pointer
 	 or address modes depending on the address space.  */
       if (target_default_pointer_address_modes_p ()
-	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+	  && ! POINTERS_EXTEND_UNSIGNED && xmode == Pmode
 	  && mode == Pmode && REG_POINTER (x)
 	  && !targetm.have_ptr_extend ())
 	return GET_MODE_PRECISION (Pmode) - GET_MODE_PRECISION (ptr_mode) + 1;
@@ -4912,22 +4922,14 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
 
     case MEM:
       /* Some RISC machines sign-extend all loads of smaller than a word.  */
-      if (load_extend_op (GET_MODE (x)) == SIGN_EXTEND)
-	return MAX (1, ((int) bitwidth
-			- (int) GET_MODE_PRECISION (GET_MODE (x)) + 1));
+      if (load_extend_op (xmode) == SIGN_EXTEND)
+	return MAX (1, ((int) bitwidth - (int) xmode_width + 1));
       break;
 
-    case CONST_INT:
-      /* If the constant is negative, take its 1's complement and remask.
-	 Then see how many zero bits we have.  */
-      nonzero = UINTVAL (x) & GET_MODE_MASK (mode);
-      if (bitwidth <= HOST_BITS_PER_WIDE_INT
-	  && (nonzero & (HOST_WIDE_INT_1U << (bitwidth - 1))) != 0)
-	nonzero = (~nonzero) & GET_MODE_MASK (mode);
-
-      return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
-
     case SUBREG:
+      if (!is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)), &inner_mode))
+	break;
+
       /* If this is a SUBREG for a promoted object that is sign-extended
 	 and we are looking at it in a wider mode, we know that at least the
 	 high-order bits are known to be sign bit copies.  */
@@ -4936,16 +4938,13 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
 	{
 	  num0 = cached_num_sign_bit_copies (SUBREG_REG (x), mode,
 					     known_x, known_mode, known_ret);
-	  return MAX ((int) bitwidth
-		      - (int) GET_MODE_PRECISION (GET_MODE (x)) + 1,
-		      num0);
+	  return MAX ((int) bitwidth - (int) xmode_width + 1, num0);
 	}
 
       /* For a smaller object, just ignore the high bits.  */
-      inner_mode = GET_MODE (SUBREG_REG (x));
       if (bitwidth <= GET_MODE_PRECISION (inner_mode))
 	{
-	  num0 = cached_num_sign_bit_copies (SUBREG_REG (x), VOIDmode,
+	  num0 = cached_num_sign_bit_copies (SUBREG_REG (x), inner_mode,
 					     known_x, known_mode, known_ret);
 	  return
 	    MAX (1, num0 - (int) (GET_MODE_PRECISION (inner_mode) - bitwidth));
@@ -4975,15 +4974,18 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
       break;
 
     case SIGN_EXTEND:
-      return (bitwidth - GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
-	      + cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
-					    known_x, known_mode, known_ret));
+      if (is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &inner_mode))
+	return (bitwidth - GET_MODE_PRECISION (inner_mode)
+		+ cached_num_sign_bit_copies (XEXP (x, 0), inner_mode,
+					      known_x, known_mode, known_ret));
+      break;
 
     case TRUNCATE:
       /* For a smaller object, just ignore the high bits.  */
-      num0 = cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
+      inner_mode = as_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)));
+      num0 = cached_num_sign_bit_copies (XEXP (x, 0), inner_mode,
 					 known_x, known_mode, known_ret);
-      return MAX (1, (num0 - (int) (GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
+      return MAX (1, (num0 - (int) (GET_MODE_PRECISION (inner_mode)
 				    - bitwidth)));
 
     case NOT:
@@ -5160,7 +5162,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
 					 known_x, known_mode, known_ret);
       if (CONST_INT_P (XEXP (x, 1))
 	  && INTVAL (XEXP (x, 1)) > 0
-	  && INTVAL (XEXP (x, 1)) < GET_MODE_PRECISION (GET_MODE (x)))
+	  && INTVAL (XEXP (x, 1)) < xmode_width)
 	num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
 
       return num0;
@@ -5170,7 +5172,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
       if (!CONST_INT_P (XEXP (x, 1))
 	  || INTVAL (XEXP (x, 1)) < 0
 	  || INTVAL (XEXP (x, 1)) >= (int) bitwidth
-	  || INTVAL (XEXP (x, 1)) >= GET_MODE_PRECISION (GET_MODE (x)))
+	  || INTVAL (XEXP (x, 1)) >= xmode_width)
 	return 1;
 
       num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,

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

* [49/67] Simplify nonzero/num_sign_bits hooks
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (48 preceding siblings ...)
  2016-12-09 13:25 ` [48/67] Make subroutines of num_sign_bit_copies " Richard Sandiford
@ 2016-12-09 13:25 ` Richard Sandiford
  2016-12-09 13:28 ` [50/67] Add helper routines for SUBREG_PROMOTED_VAR_P subregs Richard Sandiford
                   ` (19 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:25 UTC (permalink / raw)
  To: gcc-patches

The two implementations of the reg_nonzero_bits and reg_num_sign_bits
hooks ignored the "known_x", "known_mode" and "known_ret" arguments,
so this patch removes them.  It adds a new scalar_int_mode parameter
that specifies the mode of "x".  (This mode might be different from
"mode", which is the mode in which "x" is used.)

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

	* rtl.h (rtl_hooks::reg_nonzero_bits): Add a scalar_int_mode
	parameter for the mode of "x".  Remove the "known_x", "known_mode"
	and "known_ret" arguments.  Change the type of the mode argument
	to scalar_int_mode.
	(rtl_hooks:reg_num_sign_bit_copies): Likewise.
	* combine.c (reg_nonzero_bits_for_combine): Update accordingly.
	(reg_num_sign_bits_copies_for_combine): Likewise.
	* rtlanal.c (nonzero_bits1): Likewise.
	(num_sign_bit_copies1): Likewise.
	* rtlhooks-def.h (reg_nonzero_bits_general): Likewise.
	(reg_num_sign_bit_copies_general): Likewise.
	* rtlhooks.c (reg_num_sign_bit_copies_general): Likewise.
	(reg_nonzero_bits_general): Likewise.

diff --git a/gcc/combine.c b/gcc/combine.c
index fac82d4..6e32b37 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -411,13 +411,12 @@ static struct undobuf undobuf;
 
 static int n_occurrences;
 
-static rtx reg_nonzero_bits_for_combine (const_rtx, machine_mode, const_rtx,
-					 machine_mode,
-					 unsigned HOST_WIDE_INT,
+static rtx reg_nonzero_bits_for_combine (const_rtx, scalar_int_mode,
+					 scalar_int_mode,
 					 unsigned HOST_WIDE_INT *);
-static rtx reg_num_sign_bit_copies_for_combine (const_rtx, machine_mode, const_rtx,
-						machine_mode,
-						unsigned int, unsigned int *);
+static rtx reg_num_sign_bit_copies_for_combine (const_rtx, scalar_int_mode,
+						scalar_int_mode,
+						unsigned int *);
 static void do_SUBST (rtx *, rtx);
 static void do_SUBST_INT (int *, int);
 static void init_reg_last (void);
@@ -10010,17 +10009,15 @@ simplify_and_const_int (rtx x, scalar_int_mode mode, rtx varop,
   return x;
 }
 \f
-/* Given a REG, X, compute which bits in X can be nonzero.
+/* Given a REG X of mode XMODE, compute which bits in X can be nonzero.
    We don't care about bits outside of those defined in MODE.
 
    For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
    a shift, AND, or zero_extract, we can do better.  */
 
 static rtx
-reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
-			      const_rtx known_x ATTRIBUTE_UNUSED,
-			      machine_mode known_mode ATTRIBUTE_UNUSED,
-			      unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
+reg_nonzero_bits_for_combine (const_rtx x, scalar_int_mode xmode,
+			      scalar_int_mode mode,
 			      unsigned HOST_WIDE_INT *nonzero)
 {
   rtx tem;
@@ -10032,9 +10029,12 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
      for this register.  */
 
   rsp = &reg_stat[REGNO (x)];
+
+  scalar_int_mode last_mode;
   if (rsp->last_set_value != 0
-      && (rsp->last_set_mode == mode
-	  || (GET_MODE_CLASS (rsp->last_set_mode) == MODE_INT
+      && is_a <scalar_int_mode> (rsp->last_set_mode, &last_mode)
+      && (last_mode == mode
+	  || (GET_MODE_CLASS (last_mode) == MODE_INT
 	      && GET_MODE_CLASS (mode) == MODE_INT))
       && ((rsp->last_set_label >= label_tick_ebb_start
 	   && rsp->last_set_label < label_tick)
@@ -10061,8 +10061,7 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
   if (tem)
     {
       if (SHORT_IMMEDIATES_SIGN_EXTEND)
-	tem = sign_extend_short_imm (tem, GET_MODE (x),
-				     GET_MODE_PRECISION (mode));
+	tem = sign_extend_short_imm (tem, xmode, GET_MODE_PRECISION (mode));
 
       return tem;
     }
@@ -10071,9 +10070,9 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
     {
       unsigned HOST_WIDE_INT mask = rsp->nonzero_bits;
 
-      if (GET_MODE_PRECISION (GET_MODE (x)) < GET_MODE_PRECISION (mode))
+      if (GET_MODE_PRECISION (xmode) < GET_MODE_PRECISION (mode))
 	/* We don't know anything about the upper bits.  */
-	mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (GET_MODE (x));
+	mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (xmode);
 
       *nonzero &= mask;
     }
@@ -10081,17 +10080,14 @@ reg_nonzero_bits_for_combine (const_rtx x, machine_mode mode,
   return NULL;
 }
 
-/* Return the number of bits at the high-order end of X that are known to
-   be equal to the sign bit.  X will be used in mode MODE; if MODE is
-   VOIDmode, X will be used in its own mode.  The returned value  will always
-   be between 1 and the number of bits in MODE.  */
+/* Given a reg X of mode XMODE, return the number of bits at the high-order
+   end of X that are known to be equal to the sign bit.  X will be used
+   in mode MODE; the returned value will always be between 1 and the
+   number of bits in MODE.  */
 
 static rtx
-reg_num_sign_bit_copies_for_combine (const_rtx x, machine_mode mode,
-				     const_rtx known_x ATTRIBUTE_UNUSED,
-				     machine_mode known_mode
-				     ATTRIBUTE_UNUSED,
-				     unsigned int known_ret ATTRIBUTE_UNUSED,
+reg_num_sign_bit_copies_for_combine (const_rtx x, scalar_int_mode xmode,
+				     scalar_int_mode mode,
 				     unsigned int *result)
 {
   rtx tem;
@@ -10120,7 +10116,7 @@ reg_num_sign_bit_copies_for_combine (const_rtx x, machine_mode mode,
     return tem;
 
   if (nonzero_sign_valid && rsp->sign_bit_copies != 0
-      && GET_MODE_PRECISION (GET_MODE (x)) == GET_MODE_PRECISION (mode))
+      && GET_MODE_PRECISION (xmode) == GET_MODE_PRECISION (mode))
     *result = rsp->sign_bit_copies;
 
   return NULL;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 7d44e3f..35f61c8 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3761,10 +3761,10 @@ struct rtl_hooks
 {
   rtx (*gen_lowpart) (machine_mode, rtx);
   rtx (*gen_lowpart_no_emit) (machine_mode, rtx);
-  rtx (*reg_nonzero_bits) (const_rtx, machine_mode, const_rtx, machine_mode,
-			   unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT *);
-  rtx (*reg_num_sign_bit_copies) (const_rtx, machine_mode, const_rtx, machine_mode,
-				  unsigned int, unsigned int *);
+  rtx (*reg_nonzero_bits) (const_rtx, scalar_int_mode, scalar_int_mode,
+			   unsigned HOST_WIDE_INT *);
+  rtx (*reg_num_sign_bit_copies) (const_rtx, scalar_int_mode, scalar_int_mode,
+				  unsigned int *);
   bool (*reg_truncated_to_mode) (machine_mode, const_rtx);
 
   /* Whenever you add entries here, make sure you adjust rtlhooks-def.h.  */
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index b70f6ce..42d08a2 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -4409,9 +4409,8 @@ nonzero_bits1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
 
       {
 	unsigned HOST_WIDE_INT nonzero_for_hook = nonzero;
-	rtx new_rtx = rtl_hooks.reg_nonzero_bits (x, mode, known_x,
-					      known_mode, known_ret,
-					      &nonzero_for_hook);
+	rtx new_rtx = rtl_hooks.reg_nonzero_bits (x, xmode, mode,
+						  &nonzero_for_hook);
 
 	if (new_rtx)
 	  nonzero_for_hook &= cached_nonzero_bits (new_rtx, mode, known_x,
@@ -4905,9 +4904,8 @@ num_sign_bit_copies1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
 
       {
 	unsigned int copies_for_hook = 1, copies = 1;
-	rtx new_rtx = rtl_hooks.reg_num_sign_bit_copies (x, mode, known_x,
-						     known_mode, known_ret,
-						     &copies_for_hook);
+	rtx new_rtx = rtl_hooks.reg_num_sign_bit_copies (x, xmode, mode,
+							 &copies_for_hook);
 
 	if (new_rtx)
 	  copies = cached_num_sign_bit_copies (new_rtx, mode, known_x,
diff --git a/gcc/rtlhooks-def.h b/gcc/rtlhooks-def.h
index 5415114..f56f3d3 100644
--- a/gcc/rtlhooks-def.h
+++ b/gcc/rtlhooks-def.h
@@ -38,13 +38,11 @@ along with GCC; see the file COPYING3.  If not see
 }
 
 extern rtx gen_lowpart_general (machine_mode, rtx);
-extern rtx reg_nonzero_bits_general (const_rtx, machine_mode, const_rtx,
-				     machine_mode,
-				     unsigned HOST_WIDE_INT,
+extern rtx reg_nonzero_bits_general (const_rtx, scalar_int_mode,
+				     scalar_int_mode,
 				     unsigned HOST_WIDE_INT *);
-extern rtx reg_num_sign_bit_copies_general (const_rtx, machine_mode, const_rtx,
-					    machine_mode,
-					    unsigned int, unsigned int *);
+extern rtx reg_num_sign_bit_copies_general (const_rtx, scalar_int_mode,
+					    scalar_int_mode, unsigned int *);
 extern bool reg_truncated_to_mode_general (machine_mode, const_rtx);
 
 #endif /* GCC_RTL_HOOKS_DEF_H */
diff --git a/gcc/rtlhooks.c b/gcc/rtlhooks.c
index 6bebcd6..be50f3b 100644
--- a/gcc/rtlhooks.c
+++ b/gcc/rtlhooks.c
@@ -86,23 +86,15 @@ gen_lowpart_general (machine_mode mode, rtx x)
 }
 
 rtx
-reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED,
-				 machine_mode mode ATTRIBUTE_UNUSED,
-                                 const_rtx known_x ATTRIBUTE_UNUSED,
-				 machine_mode known_mode ATTRIBUTE_UNUSED,
-                                 unsigned int known_ret ATTRIBUTE_UNUSED,
-                                 unsigned int *result ATTRIBUTE_UNUSED)
+reg_num_sign_bit_copies_general (const_rtx, scalar_int_mode, scalar_int_mode,
+				 unsigned int *)
 {
   return NULL;
 }
 
 rtx
-reg_nonzero_bits_general (const_rtx x ATTRIBUTE_UNUSED,
-			  machine_mode mode ATTRIBUTE_UNUSED,
-			  const_rtx known_x ATTRIBUTE_UNUSED,
-                          machine_mode known_mode ATTRIBUTE_UNUSED,
-                          unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
-                          unsigned HOST_WIDE_INT *nonzero ATTRIBUTE_UNUSED)
+reg_nonzero_bits_general (const_rtx, scalar_int_mode, scalar_int_mode,
+			  unsigned HOST_WIDE_INT *)
 {
   return NULL;
 }

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

* [50/67] Add helper routines for SUBREG_PROMOTED_VAR_P subregs
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (49 preceding siblings ...)
  2016-12-09 13:25 ` [49/67] Simplify nonzero/num_sign_bits hooks Richard Sandiford
@ 2016-12-09 13:28 ` Richard Sandiford
  2016-12-09 13:30 ` [52/67] Use scalar_int_mode in extract/store_bit_field Richard Sandiford
                   ` (18 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:28 UTC (permalink / raw)
  To: gcc-patches

When subregs contain promoted values, as indicated by
SUBREG_PROMOTED_VAR_P, both the unpromoted (outer) and
promoted (inner) values are known to be scalar integers.
This patch adds helper routines that get the modes as
scalar_int_modes.

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

	* rtl.h (subreg_unpromoted_mode, subreg_promoted_mode): New functions.
	* expr.c (convert_move): Use them.
	(convert_modes): Likewise.
	(store_expr_with_bounds): Likewise.

diff --git a/gcc/expr.c b/gcc/expr.c
index 408a8bd..f682925 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -241,7 +241,7 @@ convert_move (rtx to, rtx from, int unsignedp)
   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 (subreg_promoted_mode (from))
 	  >= GET_MODE_PRECISION (to_int_mode))
       && SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp))
     from = gen_lowpart (to_int_mode, from), from_mode = to_int_mode;
@@ -639,7 +639,8 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
   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)
+      && (GET_MODE_PRECISION (subreg_promoted_mode (x))
+	  >= GET_MODE_PRECISION (int_mode))
       && SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
     x = gen_lowpart (int_mode, SUBREG_REG (x));
 
@@ -5414,6 +5415,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
        expression.  */
     {
       rtx inner_target = 0;
+      scalar_int_mode outer_mode = subreg_unpromoted_mode (target);
+      scalar_int_mode inner_mode = subreg_promoted_mode (target);
 
       /* We can do the conversion inside EXP, which will often result
 	 in some optimizations.  Do the conversion in two steps: first
@@ -5423,7 +5426,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
 	 converting modes.  */
       if (INTEGRAL_TYPE_P (TREE_TYPE (exp))
 	  && TREE_TYPE (TREE_TYPE (exp)) == 0
-	  && GET_MODE_PRECISION (GET_MODE (target))
+	  && GET_MODE_PRECISION (outer_mode)
 	     == TYPE_PRECISION (TREE_TYPE (exp)))
 	{
 	  if (!SUBREG_CHECK_PROMOTED_SIGN (target,
@@ -5443,8 +5446,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
 	    }
 
 	  exp = fold_convert_loc (loc, lang_hooks.types.type_for_mode
-				  (GET_MODE (SUBREG_REG (target)),
-				   SUBREG_PROMOTED_SIGN (target)),
+				  (inner_mode, SUBREG_PROMOTED_SIGN (target)),
 				  exp);
 
 	  inner_target = SUBREG_REG (target);
@@ -5470,10 +5472,9 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
 	 sure that we properly convert it.  */
       if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)
 	{
-	  temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
+	  temp = convert_modes (outer_mode, TYPE_MODE (TREE_TYPE (exp)),
 				temp, SUBREG_PROMOTED_SIGN (target));
-	  temp = convert_modes (GET_MODE (SUBREG_REG (target)),
-			        GET_MODE (target), temp,
+	  temp = convert_modes (inner_mode, outer_mode, temp,
 				SUBREG_PROMOTED_SIGN (target));
 	}
 
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 35f61c8..e65020a 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2766,6 +2766,24 @@ unwrap_const_vec_duplicate (T x)
   return x;
 }
 
+/* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X.  */
+
+inline scalar_int_mode
+subreg_unpromoted_mode (rtx x)
+{
+  gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+  return as_a <scalar_int_mode> (GET_MODE (x));
+}
+
+/* Return the promoted (inner) mode of SUBREG_PROMOTED_VAR_P subreg X.  */
+
+inline scalar_int_mode
+subreg_promoted_mode (rtx x)
+{
+  gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+  return as_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)));
+}
+
 /* In emit-rtl.c */
 extern rtvec gen_rtvec_v (int, rtx *);
 extern rtvec gen_rtvec_v (int, rtx_insn **);

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

* [51/67] Use opt_scalar_int_mode when iterating over integer modes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (51 preceding siblings ...)
  2016-12-09 13:30 ` [52/67] Use scalar_int_mode in extract/store_bit_field Richard Sandiford
@ 2016-12-09 13:30 ` Richard Sandiford
  2016-12-09 13:31 ` [53/67] Pass a mode to const_scalar_mask_from_tree Richard Sandiford
                   ` (16 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:30 UTC (permalink / raw)
  To: gcc-patches

This patch uses opt_scalar_int_mode rather than machine_mode
when iterating over scalar_int_modes, in cases where that helps
with future patches.  (Using machine_mode is still OK in places
that don't really care about the mode being a scalar integer.)

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): Use opt_scalar_int_mode for the mode iterator.
	* explow.c (hard_function_value): Likewise.
	* expmed.c (init_expmed_one_mode): Likewise.
	(extract_fixed_bit_field_1): Likewise.  Move the convert_to_mode
	call outside the loop.
	* expr.c (alignment_for_piecewise_move): Use opt_scalar_int_mode
	for the mode iterator.  Require the mode specified by max_pieces
	to exist.
	(emit_block_move_via_movmem): Use opt_scalar_int_mode for the
	mode iterator.
	(copy_blkmode_to_reg): Likewise.
	(set_storage_via_setmem): Likewise.
	* optabs.c (prepare_cmp_insn): Likewise.
	* rtlanal.c (init_num_sign_bit_copies): Likewise.
	* stor-layout.c (finish_bitfield_repreentation): 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 opt_scalar_int_mode for
	the mode iterator.

diff --git a/gcc/cse.c b/gcc/cse.c
index 4d22d78..81db2a0 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4885,11 +4885,12 @@ cse_insn (rtx_insn *insn)
 	  && GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))
 	  && GET_MODE_SIZE (int_mode) < UNITS_PER_WORD)
 	{
-	  machine_mode tmode;
+	  opt_scalar_int_mode tmode_iter;
 	  rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
 
-	  FOR_EACH_WIDER_MODE (tmode, int_mode)
+	  FOR_EACH_WIDER_MODE (tmode_iter, int_mode)
 	    {
+	      scalar_int_mode tmode = *tmode_iter;
 	      if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
 		break;
 
@@ -4932,7 +4933,6 @@ cse_insn (rtx_insn *insn)
 	{
 	  struct rtx_def memory_extend_buf;
 	  rtx memory_extend_rtx = &memory_extend_buf;
-	  machine_mode tmode;
 
 	  /* Set what we are trying to extend and the operation it might
 	     have been extended with.  */
@@ -4940,10 +4940,12 @@ cse_insn (rtx_insn *insn)
 	  PUT_CODE (memory_extend_rtx, extend_op);
 	  XEXP (memory_extend_rtx, 0) = src;
 
-	  FOR_EACH_WIDER_MODE (tmode, int_mode)
+	  opt_scalar_int_mode tmode_iter;
+	  FOR_EACH_WIDER_MODE (tmode_iter, int_mode)
 	    {
 	      struct table_elt *larger_elt;
 
+	      scalar_int_mode tmode = *tmode_iter;
 	      if (GET_MODE_SIZE (tmode) > UNITS_PER_WORD)
 		break;
 
diff --git a/gcc/explow.c b/gcc/explow.c
index 65b78ab..6348035 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -1911,7 +1911,7 @@ hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
       && GET_MODE (val) == BLKmode)
     {
       unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype);
-      machine_mode tmpmode;
+      opt_scalar_int_mode tmpmode;
 
       /* int_size_in_bytes can return -1.  We don't need a check here
 	 since the value of bytes will then be large enough that no
@@ -1920,14 +1920,11 @@ hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
       FOR_EACH_MODE_IN_CLASS (tmpmode, MODE_INT)
 	{
 	  /* Have we found a large enough mode?  */
-	  if (GET_MODE_SIZE (tmpmode) >= bytes)
+	  if (GET_MODE_SIZE (*tmpmode) >= bytes)
 	    break;
 	}
 
-      /* No suitable mode found.  */
-      gcc_assert (tmpmode != VOIDmode);
-
-      PUT_MODE (val, tmpmode);
+      PUT_MODE (val, *tmpmode);
     }
   return val;
 }
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 71e1fa8..5ae4842 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -205,8 +205,9 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
   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, int_mode_to, mode_from, speed);
+      opt_scalar_int_mode int_mode_from;
+      FOR_EACH_MODE_IN_CLASS (int_mode_from, MODE_INT)
+	init_expmed_one_conv (all, int_mode_to, *int_mode_from, speed);
 
       scalar_int_mode wider_mode;
       if (GET_MODE_CLASS (int_mode_to) == MODE_INT
@@ -2009,12 +2010,13 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
 
   /* Find the narrowest integer mode that contains the field.  */
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
-    if (GET_MODE_BITSIZE (mode) >= bitsize + bitnum)
-      {
-	op0 = convert_to_mode (mode, op0, 0);
-	break;
-      }
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
+    if (GET_MODE_BITSIZE (*mode_iter) >= bitsize + bitnum)
+      break;
+
+  mode = *mode_iter;
+  op0 = convert_to_mode (mode, op0, 0);
 
   if (mode != tmode)
     target = 0;
diff --git a/gcc/expr.c b/gcc/expr.c
index f682925..ec88d35 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -697,18 +697,17 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
 static unsigned int
 alignment_for_piecewise_move (unsigned int max_pieces, unsigned int align)
 {
-  machine_mode tmode;
+  scalar_int_mode tmode = *int_mode_for_size (max_pieces * BITS_PER_UNIT, 1);
 
-  tmode = mode_for_size (max_pieces * BITS_PER_UNIT, MODE_INT, 1);
   if (align >= GET_MODE_ALIGNMENT (tmode))
     align = GET_MODE_ALIGNMENT (tmode);
   else
     {
-      machine_mode tmode, xmode;
-
-      xmode = NARROWEST_INT_MODE;
-      FOR_EACH_MODE_IN_CLASS (tmode, MODE_INT)
+      scalar_int_mode xmode = NARROWEST_INT_MODE;
+      opt_scalar_int_mode mode_iter;
+      FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
 	{
+	  tmode = *mode_iter;
 	  if (GET_MODE_SIZE (tmode) > max_pieces
 	      || SLOW_UNALIGNED_ACCESS (tmode, align))
 	    break;
@@ -1704,7 +1703,6 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
 			    unsigned HOST_WIDE_INT probable_max_size)
 {
   int save_volatile_ok = volatile_ok;
-  machine_mode mode;
 
   if (expected_align < align)
     expected_align = align;
@@ -1723,8 +1721,10 @@ 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_EACH_MODE_IN_CLASS (mode, MODE_INT)
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
     {
+      scalar_int_mode mode = *mode_iter;
       enum insn_code code = direct_optab_handler (movmem_optab, mode);
 
       if (code != CODE_FOR_nothing
@@ -2784,13 +2784,13 @@ copy_blkmode_to_reg (machine_mode mode, tree src)
     {
       /* Find the smallest integer mode large enough to hold the
 	 entire structure.  */
-      FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
-	/* Have we found a large enough mode?  */
-	if (GET_MODE_SIZE (mode) >= bytes)
+      opt_scalar_int_mode mode_iter;
+      FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
+	if (GET_MODE_SIZE (*mode_iter) >= bytes)
 	  break;
 
       /* A suitable mode should have been found.  */
-      gcc_assert (mode != VOIDmode);
+      mode = *mode_iter;
     }
 
   if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode))
@@ -3028,8 +3028,6 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
      including more than one in the machine description unless
      the more limited one has some advantage.  */
 
-  machine_mode mode;
-
   if (expected_align < align)
     expected_align = align;
   if (expected_size != -1)
@@ -3040,8 +3038,10 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
 	expected_size = min_size;
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
     {
+      scalar_int_mode mode = *mode_iter;
       enum insn_code code = direct_optab_handler (setmem_optab, mode);
 
       if (code != CODE_FOR_nothing
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 50aae8e..de6ce42 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -347,15 +347,16 @@ gfc_init_c_interop_kinds (void)
 void
 gfc_init_kinds (void)
 {
-  machine_mode_enum mode;
+  opt_scalar_int_mode int_mode_iter;
   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;
 
-  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
-       mode = (machine_mode_enum) ((int) mode + 1))
+  i_index = 0;
+  FOR_EACH_MODE_IN_CLASS (int_mode_iter, MODE_INT)
     {
+      scalar_int_mode mode = *int_mode_iter;
       int kind, bitsize;
 
       if (!targetm.scalar_mode_supported_p (mode))
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 054457a..509f0d3 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -3797,8 +3797,10 @@ 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_EACH_MODE_IN_CLASS (cmp_mode, MODE_INT)
+      opt_scalar_int_mode cmp_mode_iter;
+      FOR_EACH_MODE_IN_CLASS (cmp_mode_iter, MODE_INT)
 	{
+	  scalar_int_mode cmp_mode = *cmp_mode_iter;
 	  cmp_code = direct_optab_handler (cmpmem_optab, cmp_mode);
 	  if (cmp_code == CODE_FOR_nothing)
 	    cmp_code = direct_optab_handler (cmpstr_optab, cmp_mode);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 42d08a2..f74bf14 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5603,12 +5603,14 @@ get_condition (rtx_insn *jump, rtx_insn **earliest, int allow_cc_mode,
 static void
 init_num_sign_bit_copies_in_rep (void)
 {
-  machine_mode mode, in_mode;
+  opt_scalar_int_mode in_mode_iter;
+  scalar_int_mode mode;
 
-  FOR_EACH_MODE_IN_CLASS (in_mode, MODE_INT)
-    FOR_EACH_MODE_UNTIL (mode, in_mode)
+  FOR_EACH_MODE_IN_CLASS (in_mode_iter, MODE_INT)
+    FOR_EACH_MODE_UNTIL (mode, *in_mode_iter)
       {
-	machine_mode i;
+	scalar_int_mode in_mode = *in_mode_iter;
+	scalar_int_mode i;
 
 	/* Currently, it is assumed that TARGET_MODE_REP_EXTENDED
 	   extends to the next widest mode.  */
@@ -5621,7 +5623,7 @@ init_num_sign_bit_copies_in_rep (void)
 	  {
 	    /* This must always exist (for the last iteration it will be
 	       IN_MODE).  */
-	    machine_mode wider = *GET_MODE_WIDER_MODE (i);
+	    scalar_int_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 d872dae..8ff73ef 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1818,7 +1818,6 @@ static void
 finish_bitfield_representative (tree repr, tree field)
 {
   unsigned HOST_WIDE_INT bitsize, maxbitsize;
-  machine_mode mode;
   tree nextf, size;
 
   size = size_diffop (DECL_FIELD_OFFSET (field),
@@ -1882,15 +1881,15 @@ finish_bitfield_representative (tree repr, tree field)
   gcc_assert (maxbitsize % BITS_PER_UNIT == 0);
 
   /* Find the smallest nice mode to use.  */
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
-    if (GET_MODE_BITSIZE (mode) >= bitsize)
+  opt_scalar_int_mode mode_iter;
+  FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
+    if (GET_MODE_BITSIZE (*mode_iter) >= bitsize)
       break;
-  if (mode != VOIDmode
-      && (GET_MODE_BITSIZE (mode) > maxbitsize
-	  || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE))
-    mode = VOIDmode;
 
-  if (mode == VOIDmode)
+  scalar_int_mode mode;
+  if (!mode_iter.exists (&mode)
+      || GET_MODE_BITSIZE (mode) > maxbitsize
+      || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE)
     {
       /* We really want a BLKmode representative only as a last resort,
          considering the member b in

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

* [52/67] Use scalar_int_mode in extract/store_bit_field
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (50 preceding siblings ...)
  2016-12-09 13:28 ` [50/67] Add helper routines for SUBREG_PROMOTED_VAR_P subregs Richard Sandiford
@ 2016-12-09 13:30 ` Richard Sandiford
  2016-12-09 13:30 ` [51/67] Use opt_scalar_int_mode when iterating over integer modes Richard Sandiford
                   ` (17 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:30 UTC (permalink / raw)
  To: gcc-patches

After a certain point, extract_bit_field and store_bit_field
ensure that they're dealing with integer modes or BLKmode MEMs.
This patch uses scalar_int_mode and opt_scalar_int_mode for
those parts.

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

	* expmed.c (store_bit_field_using_insv): Add op0_mode and
	value_mode arguments.  Use scalar_int_mode internally.
	(store_bit_field_1): Rename the new integer mode from imode
	to op0_mode and use it instead of GET_MODE (op0).  Update calls
	to store_split_bit_field, store_bit_field_using_insv and
	store_fixed_bit_field.
	(store_fixed_bit_field): Add op0_mode and value_mode arguments.
	Use scalar_int_mode internally.  Use a bit count rather than a mode
	when calculating the largest bit size for get_best_mode.
	Update calls to store_split_bit_field and store_fixed_bit_field_1.
	(store_fixed_bit_field_1): Add mode and value_mode arguments.
	Remove assertion that OP0 has a scalar integer mode.
	(store_split_bit_field): Add op0_mode and value_mode arguments.
	Update calls to extract_fixed_bit_field.
	(extract_bit_field_using_extv): Add an op0_mode argument.
	Use scalar_int_mode internally.
	(extract_bit_field_1): Rename the new integer mode from imode to
	op0_mode and use it instead of GET_MODE (op0).  Update calls to
	extract_split_bit_field, extract_bit_field_using_extv and
	extract_fixed_bit_field.
	(extract_fixed_bit_field): Add an op0_mode argument.  Update calls
	to extract_split_bit_field and extract_fixed_bit_field_1.
	(extract_fixed_bit_field_1): Add a mode argument.  Remove assertion
	that OP0 has a scalar integer mode.  Use as_a <scalar_int_mode>
	on the target mode.
	(extract_split_bit_field): Add an op0_mode argument.  Update call
	to extract_fixed_bit_field.

diff --git a/gcc/expmed.c b/gcc/expmed.c
index 5ae4842..8ce9d96 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -45,27 +45,31 @@ struct target_expmed default_target_expmed;
 struct target_expmed *this_target_expmed = &default_target_expmed;
 #endif
 
-static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
+static void store_fixed_bit_field (rtx, opt_scalar_int_mode,
 				   unsigned HOST_WIDE_INT,
 				   unsigned HOST_WIDE_INT,
 				   unsigned HOST_WIDE_INT,
-				   rtx, bool);
-static void store_fixed_bit_field_1 (rtx, unsigned HOST_WIDE_INT,
+				   unsigned HOST_WIDE_INT,
+				   rtx, scalar_int_mode, bool);
+static void store_fixed_bit_field_1 (rtx, scalar_int_mode,
+				     unsigned HOST_WIDE_INT,
 				     unsigned HOST_WIDE_INT,
-				     rtx, bool);
-static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
+				     rtx, scalar_int_mode, bool);
+static void store_split_bit_field (rtx, opt_scalar_int_mode,
 				   unsigned HOST_WIDE_INT,
 				   unsigned HOST_WIDE_INT,
 				   unsigned HOST_WIDE_INT,
-				   rtx, bool);
-static rtx extract_fixed_bit_field (machine_mode, rtx,
+				   unsigned HOST_WIDE_INT,
+				   rtx, scalar_int_mode, bool);
+static rtx extract_fixed_bit_field (machine_mode, rtx, opt_scalar_int_mode,
 				    unsigned HOST_WIDE_INT,
 				    unsigned HOST_WIDE_INT, rtx, int, bool);
-static rtx extract_fixed_bit_field_1 (machine_mode, rtx,
+static rtx extract_fixed_bit_field_1 (machine_mode, rtx, scalar_int_mode,
 				      unsigned HOST_WIDE_INT,
 				      unsigned HOST_WIDE_INT, rtx, int, bool);
 static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INT, int);
-static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
+static rtx extract_split_bit_field (rtx, opt_scalar_int_mode,
+				    unsigned HOST_WIDE_INT,
 				    unsigned HOST_WIDE_INT, int, bool);
 static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *);
 static rtx expand_smod_pow2 (machine_mode, rtx, HOST_WIDE_INT);
@@ -569,13 +573,16 @@ simple_mem_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize,
 }
 \f
 /* Try to use instruction INSV to store VALUE into a field of OP0.
-   BITSIZE and BITNUM are as for store_bit_field.  */
+   If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is a
+   BLKmode MEM.  VALUE_MODE is the mode of VALUE.  BITSIZE and BITNUM
+   are as for store_bit_field.  */
 
 static bool
 store_bit_field_using_insv (const extraction_insn *insv, rtx op0,
+			    opt_scalar_int_mode op0_mode,
 			    unsigned HOST_WIDE_INT bitsize,
 			    unsigned HOST_WIDE_INT bitnum,
-			    rtx value)
+			    rtx value, scalar_int_mode value_mode)
 {
   struct expand_operand ops[4];
   rtx value1;
@@ -583,7 +590,7 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0,
   rtx_insn *last = get_last_insn ();
   bool copy_back = false;
 
-  machine_mode op_mode = insv->field_mode;
+  scalar_int_mode op_mode = insv->field_mode;
   unsigned int unit = GET_MODE_BITSIZE (op_mode);
   if (bitsize == 0 || bitsize > unit)
     return false;
@@ -596,7 +603,7 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0,
     {
       /* Convert from counting within OP0 to counting in OP_MODE.  */
       if (BYTES_BIG_ENDIAN)
-	bitnum += unit - GET_MODE_BITSIZE (GET_MODE (op0));
+	bitnum += unit - GET_MODE_BITSIZE (*op0_mode);
 
       /* If xop0 is a register, we need it in OP_MODE
 	 to make it acceptable to the format of insv.  */
@@ -649,30 +656,28 @@ store_bit_field_using_insv (const extraction_insn *insv, rtx op0,
 
   /* Convert VALUE to op_mode (which insv insn wants) in VALUE1.  */
   value1 = value;
-  if (GET_MODE (value) != op_mode)
+  if (value_mode != op_mode)
     {
-      if (GET_MODE_BITSIZE (GET_MODE (value)) >= bitsize)
+      if (GET_MODE_BITSIZE (value_mode) >= bitsize)
 	{
 	  rtx tmp;
 	  /* Optimization: Don't bother really extending VALUE
 	     if it has all the bits we will actually use.  However,
 	     if we must narrow it, be sure we do it correctly.  */
 
-	  if (GET_MODE_SIZE (GET_MODE (value)) < GET_MODE_SIZE (op_mode))
+	  if (GET_MODE_SIZE (value_mode) < GET_MODE_SIZE (op_mode))
 	    {
-	      tmp = simplify_subreg (op_mode, value1, GET_MODE (value), 0);
+	      tmp = simplify_subreg (op_mode, value1, value_mode, 0);
 	      if (! tmp)
 		tmp = simplify_gen_subreg (op_mode,
-					   force_reg (GET_MODE (value),
-						      value1),
-					   GET_MODE (value), 0);
+					   force_reg (value_mode, value1),
+					   value_mode, 0);
 	    }
 	  else
 	    {
 	      tmp = gen_lowpart_if_possible (op_mode, value1);
 	      if (! tmp)
-		tmp = gen_lowpart (op_mode, force_reg (GET_MODE (value),
-						       value1));
+		tmp = gen_lowpart (op_mode, force_reg (value_mode, value1));
 	    }
 	  value1 = tmp;
 	}
@@ -827,14 +832,14 @@ 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.  */
-  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
-  if (!imode.exists () || *imode != GET_MODE (op0))
+  opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0));
+  if (!op0_mode.exists () || *op0_mode != GET_MODE (op0))
     {
       if (MEM_P (op0))
-	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+	op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
 					    0, MEM_SIZE (op0));
       else
-	op0 = gen_lowpart (*imode, op0);
+	op0 = gen_lowpart (*op0_mode, op0);
     }
 
   /* Storing an lsb-aligned field in a register
@@ -946,30 +951,36 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
      with 64 bit registers that uses SFmode for float.  It can also
      occur for unaligned float or complex fields.  */
   orig_value = value;
-  if (GET_MODE (value) != VOIDmode
-      && 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)));
+  scalar_int_mode value_mode;
+  if (GET_MODE (value) == VOIDmode)
+    /* By this point we've dealt with values that are bigger than a word,
+       so word_mode is a conservatively correct choice.  */
+    value_mode = word_mode;
+  else if (!is_a <scalar_int_mode> (GET_MODE (value), &value_mode))
+    {
+      value_mode = *int_mode_for_mode (GET_MODE (value));
+      value = gen_reg_rtx (value_mode);
       emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value);
     }
 
   /* If OP0 is a multi-word register, narrow it to the affected word.
      If the region spans two words, defer to store_split_bit_field.  */
-  if (!MEM_P (op0) && GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
+  if (!MEM_P (op0) && GET_MODE_SIZE (*op0_mode) > UNITS_PER_WORD)
     {
       if (bitnum % BITS_PER_WORD + bitsize > BITS_PER_WORD)
 	{
 	  if (!fallback_p)
 	    return false;
 
-	  store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
-				 bitregion_end, value, reverse);
+	  store_split_bit_field (op0, op0_mode, bitsize, bitnum,
+				 bitregion_start, bitregion_end,
+				 value, value_mode, reverse);
 	  return true;
 	}
-      op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0),
+      op0 = simplify_gen_subreg (word_mode, op0, *op0_mode,
 				 bitnum / BITS_PER_WORD * UNITS_PER_WORD);
       gcc_assert (op0);
+      op0_mode = word_mode;
       bitnum %= BITS_PER_WORD;
     }
 
@@ -981,9 +992,10 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
   if (!MEM_P (op0)
       && !reverse
       && get_best_reg_extraction_insn (&insv, EP_insv,
-				       GET_MODE_BITSIZE (GET_MODE (op0)),
+				       GET_MODE_BITSIZE (*op0_mode),
 				       fieldmode)
-      && store_bit_field_using_insv (&insv, op0, bitsize, bitnum, value))
+      && store_bit_field_using_insv (&insv, op0, op0_mode,
+				     bitsize, bitnum, value, value_mode))
     return true;
 
   /* If OP0 is a memory, try copying it to a register and seeing if a
@@ -992,7 +1004,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
     {
       if (get_best_mem_extraction_insn (&insv, EP_insv, bitsize, bitnum,
 					fieldmode)
-	  && store_bit_field_using_insv (&insv, op0, bitsize, bitnum, value))
+	  && store_bit_field_using_insv (&insv, op0, op0_mode,
+					 bitsize, bitnum, value, value_mode))
 	return true;
 
       rtx_insn *last = get_last_insn ();
@@ -1020,8 +1033,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
   if (!fallback_p)
     return false;
 
-  store_fixed_bit_field (op0, bitsize, bitnum, bitregion_start,
-			 bitregion_end, value, reverse);
+  store_fixed_bit_field (op0, op0_mode, bitsize, bitnum, bitregion_start,
+			 bitregion_end, value, value_mode, reverse);
   return true;
 }
 
@@ -1115,16 +1128,19 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 }
 \f
 /* Use shifts and boolean operations to store VALUE into a bit field of
-   width BITSIZE in OP0, starting at bit BITNUM.
+   width BITSIZE in OP0, starting at bit BITNUM.  If OP0_MODE is defined,
+   it is the mode of OP0, otherwise OP0 is a BLKmode MEM.  VALUE_MODE is
+   the mode of VALUE.
 
    If REVERSE is true, the store is to be done in reverse order.  */
 
 static void
-store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
+store_fixed_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
+		       unsigned HOST_WIDE_INT bitsize,
 		       unsigned HOST_WIDE_INT bitnum,
 		       unsigned HOST_WIDE_INT bitregion_start,
 		       unsigned HOST_WIDE_INT bitregion_end,
-		       rtx value, bool reverse)
+		       rtx value, scalar_int_mode value_mode, bool reverse)
 {
   /* There is a case not handled here:
      a structure with a known alignment of just a halfword
@@ -1133,46 +1149,48 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
      and a field split across two bytes.
      Such cases are not supposed to be able to occur.  */
 
+  scalar_int_mode best_mode;
   if (MEM_P (op0))
     {
-      machine_mode mode = GET_MODE (op0);
-      if (GET_MODE_BITSIZE (mode) == 0
-	  || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode))
-	mode = word_mode;
-      scalar_int_mode best_mode;
+      unsigned int max_bitsize = BITS_PER_WORD;
+      if (op0_mode.exists () && GET_MODE_BITSIZE (*op0_mode) < max_bitsize)
+	max_bitsize = GET_MODE_BITSIZE (*op0_mode);
+
       if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end,
-			  MEM_ALIGN (op0), GET_MODE_BITSIZE (mode),
-			  MEM_VOLATILE_P (op0), &best_mode))
+			  MEM_ALIGN (op0), max_bitsize, MEM_VOLATILE_P (op0),
+			  &best_mode))
 	{
 	  /* The only way this should occur is if the field spans word
 	     boundaries.  */
-	  store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
-				 bitregion_end, value, reverse);
+	  store_split_bit_field (op0, op0_mode, bitsize, bitnum,
+				 bitregion_start, bitregion_end,
+				 value, value_mode, reverse);
 	  return;
 	}
 
       op0 = narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, &bitnum);
     }
+  else
+    best_mode = *op0_mode;
 
-  store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse);
+  store_fixed_bit_field_1 (op0, best_mode, bitsize, bitnum,
+			   value, value_mode, reverse);
 }
 
 /* Helper function for store_fixed_bit_field, stores
-   the bit field always using the MODE of OP0.  */
+   the bit field always using MODE, which is the mode of OP0.  The other
+   arguments are as for store_fixed_bit_field.  */
 
 static void
-store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
+store_fixed_bit_field_1 (rtx op0, scalar_int_mode mode,
+			 unsigned HOST_WIDE_INT bitsize,
 			 unsigned HOST_WIDE_INT bitnum,
-			 rtx value, bool reverse)
+			 rtx value, scalar_int_mode value_mode, bool reverse)
 {
-  machine_mode mode;
   rtx temp;
   int all_zero = 0;
   int all_one = 0;
 
-  mode = GET_MODE (op0);
-  gcc_assert (SCALAR_INT_MODE_P (mode));
-
   /* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode)
      for invalid input, such as f5 from gcc.dg/pr48335-2.c.  */
 
@@ -1207,10 +1225,10 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
     }
   else
     {
-      int must_and = (GET_MODE_BITSIZE (GET_MODE (value)) != bitsize
+      int must_and = (GET_MODE_BITSIZE (value_mode) != bitsize
 		      && bitnum + bitsize != GET_MODE_BITSIZE (mode));
 
-      if (GET_MODE (value) != mode)
+      if (value_mode != mode)
 	value = convert_to_mode (mode, value, 1);
 
       if (must_and)
@@ -1263,18 +1281,21 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
    OP0 is the REG, SUBREG or MEM rtx for the first of the objects.
    BITSIZE is the field width; BITPOS the position of its first bit
    (within the word).
-   VALUE is the value to store.
+   VALUE is the value to store, which has mode VALUE_MODE.
+   If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is
+   a BLKmode MEM.
 
    If REVERSE is true, the store is to be done in reverse order.
 
    This does not yet handle fields wider than BITS_PER_WORD.  */
 
 static void
-store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
+store_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
+		       unsigned HOST_WIDE_INT bitsize,
 		       unsigned HOST_WIDE_INT bitpos,
 		       unsigned HOST_WIDE_INT bitregion_start,
 		       unsigned HOST_WIDE_INT bitregion_end,
-		       rtx value, bool reverse)
+		       rtx value, scalar_int_mode value_mode, bool reverse)
 {
   unsigned int unit, total_bits, bitsdone = 0;
 
@@ -1288,8 +1309,8 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
   /* If OP0 is a memory with a mode, then UNIT must not be larger than
      OP0's mode as well.  Otherwise, store_fixed_bit_field will call us
      again, and we will mutually recurse forever.  */
-  if (MEM_P (op0) && GET_MODE_BITSIZE (GET_MODE (op0)) > 0)
-    unit = MIN (unit, GET_MODE_BITSIZE (GET_MODE (op0)));
+  if (MEM_P (op0) && op0_mode.exists ())
+    unit = MIN (unit, GET_MODE_BITSIZE (*op0_mode));
 
   /* If VALUE is a constant other than a CONST_INT, get it into a register in
      WORD_MODE.  If we can do this using gen_lowpart_common, do so.  Note
@@ -1301,20 +1322,18 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
       if (word && (value != word))
 	value = word;
       else
-	value = gen_lowpart_common (word_mode,
-				    force_reg (GET_MODE (value) != VOIDmode
-					       ? GET_MODE (value)
-					       : word_mode, value));
+	value = gen_lowpart_common (word_mode, force_reg (value_mode, value));
+      value_mode = word_mode;
     }
 
-  total_bits = GET_MODE_BITSIZE (GET_MODE (value));
+  total_bits = GET_MODE_BITSIZE (value_mode);
 
   while (bitsdone < bitsize)
     {
       unsigned HOST_WIDE_INT thissize;
       unsigned HOST_WIDE_INT thispos;
       unsigned HOST_WIDE_INT offset;
-      rtx part, word;
+      rtx part;
 
       offset = (bitpos + bitsdone) / unit;
       thispos = (bitpos + bitsdone) % unit;
@@ -1348,19 +1367,18 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
 			    & ((HOST_WIDE_INT_1 << thissize) - 1));
           /* Likewise, but the source is little-endian.  */
           else if (reverse)
-	    part = extract_fixed_bit_field (word_mode, value, thissize,
+	    part = extract_fixed_bit_field (word_mode, value, value_mode,
+					    thissize,
 					    bitsize - bitsdone - thissize,
 					    NULL_RTX, 1, false);
 	  else
-	    {
-	      int total_bits = GET_MODE_BITSIZE (GET_MODE (value));
-	      /* The args are chosen so that the last part includes the
-		 lsb.  Give extract_bit_field the value it needs (with
-		 endianness compensation) to fetch the piece we want.  */
-	      part = extract_fixed_bit_field (word_mode, value, thissize,
-					      total_bits - bitsize + bitsdone,
-					      NULL_RTX, 1, false);
-	    }
+	    /* The args are chosen so that the last part includes the
+	       lsb.  Give extract_bit_field the value it needs (with
+	       endianness compensation) to fetch the piece we want.  */
+	    part = extract_fixed_bit_field (word_mode, value, value_mode,
+					    thissize,
+					    total_bits - bitsize + bitsdone,
+					    NULL_RTX, 1, false);
 	}
       else
 	{
@@ -1371,34 +1389,42 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
 			    & ((HOST_WIDE_INT_1 << thissize) - 1));
 	  /* Likewise, but the source is big-endian.  */
           else if (reverse)
-	    part = extract_fixed_bit_field (word_mode, value, thissize,
+	    part = extract_fixed_bit_field (word_mode, value, value_mode,
+					    thissize,
 					    total_bits - bitsdone - thissize,
 					    NULL_RTX, 1, false);
 	  else
-	    part = extract_fixed_bit_field (word_mode, value, thissize,
-					    bitsdone, NULL_RTX, 1, false);
+	    part = extract_fixed_bit_field (word_mode, value, value_mode,
+					    thissize, bitsdone, NULL_RTX,
+					    1, false);
 	}
 
       /* If OP0 is a register, then handle OFFSET here.  */
+      rtx op0_piece = op0;
+      opt_scalar_int_mode op0_piece_mode = op0_mode;
       if (SUBREG_P (op0) || REG_P (op0))
 	{
-	  machine_mode op0_mode = GET_MODE (op0);
-	  if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD)
-	    word = offset ? const0_rtx : op0;
+	  if (op0_mode.exists () && GET_MODE_SIZE (*op0_mode) < UNITS_PER_WORD)
+	    {
+	      if (offset)
+		op0_piece = const0_rtx;
+	    }
 	  else
-	    word = operand_subword_force (op0, offset * unit / BITS_PER_WORD,
-					  GET_MODE (op0));
+	    {
+	      op0_piece = operand_subword_force (op0,
+						 offset * unit / BITS_PER_WORD,
+						 GET_MODE (op0));
+	      op0_piece_mode = word_mode;
+	    }
 	  offset &= BITS_PER_WORD / unit - 1;
 	}
-      else
-	word = op0;
 
       /* OFFSET is in UNITs, and UNIT is in bits.  If WORD is const0_rtx,
 	 it is just an out-of-bounds access.  Ignore it.  */
-      if (word != const0_rtx)
-	store_fixed_bit_field (word, thissize, offset * unit + thispos,
-			       bitregion_start, bitregion_end, part,
-			       reverse);
+      if (op0_piece != const0_rtx)
+	store_fixed_bit_field (op0_piece, op0_piece_mode, thissize,
+			       offset * unit + thispos, bitregion_start,
+			       bitregion_end, part, word_mode, reverse);
       bitsdone += thissize;
     }
 }
@@ -1430,11 +1456,13 @@ convert_extracted_bit_field (rtx x, machine_mode mode,
 
 /* Try to use an ext(z)v pattern to extract a field from OP0.
    Return the extracted value on success, otherwise return null.
-   EXT_MODE is the mode of the extraction and the other arguments
-   are as for extract_bit_field.  */
+   EXTV describes the extraction instruction to use.  If OP0_MODE
+   is defined, it is the mode of OP0, otherwise OP0 is a BLKmode MEM.
+   The other arguments are as for extract_bit_field.  */
 
 static rtx
 extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
+			      opt_scalar_int_mode op0_mode,
 			      unsigned HOST_WIDE_INT bitsize,
 			      unsigned HOST_WIDE_INT bitnum,
 			      int unsignedp, rtx target,
@@ -1443,7 +1471,7 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
   struct expand_operand ops[4];
   rtx spec_target = target;
   rtx spec_target_subreg = 0;
-  machine_mode ext_mode = extv->field_mode;
+  scalar_int_mode ext_mode = extv->field_mode;
   unsigned unit = GET_MODE_BITSIZE (ext_mode);
 
   if (bitsize == 0 || unit < bitsize)
@@ -1457,13 +1485,13 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
     {
       /* Convert from counting within OP0 to counting in EXT_MODE.  */
       if (BYTES_BIG_ENDIAN)
-	bitnum += unit - GET_MODE_BITSIZE (GET_MODE (op0));
+	bitnum += unit - GET_MODE_BITSIZE (*op0_mode);
 
       /* If op0 is a register, we need it in EXT_MODE to make it
 	 acceptable to the format of ext(z)v.  */
-      if (GET_CODE (op0) == SUBREG && GET_MODE (op0) != ext_mode)
+      if (GET_CODE (op0) == SUBREG && *op0_mode != ext_mode)
 	return NULL_RTX;
-      if (REG_P (op0) && GET_MODE (op0) != ext_mode)
+      if (REG_P (op0) && *op0_mode != ext_mode)
 	op0 = gen_lowpart_SUBREG (ext_mode, op0);
     }
 
@@ -1609,20 +1637,20 @@ 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.  */
-  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
-  if (!imode.exists () || *imode != GET_MODE (op0))
+  opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0));
+  if (!op0_mode.exists () || *op0_mode != GET_MODE (op0))
     {
       if (MEM_P (op0))
-	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+	op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
 					    0, MEM_SIZE (op0));
-      else if (imode.exists ())
+      else if (op0_mode.exists ())
 	{
-	  op0 = gen_lowpart (*imode, op0);
+	  op0 = gen_lowpart (*op0_mode, 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);
+	    op0 = force_reg (*op0_mode, op0);
 	}
       else
 	{
@@ -1654,11 +1682,11 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
      bit of either OP0 or a word of OP0.  */
   if (!MEM_P (op0)
       && !reverse
-      && lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0))
+      && lowpart_bit_field_p (bitnum, bitsize, *op0_mode)
       && bitsize == GET_MODE_BITSIZE (mode1)
-      && TRULY_NOOP_TRUNCATION_MODES_P (mode1, GET_MODE (op0)))
+      && TRULY_NOOP_TRUNCATION_MODES_P (mode1, *op0_mode))
     {
-      rtx sub = simplify_gen_subreg (mode1, op0, GET_MODE (op0),
+      rtx sub = simplify_gen_subreg (mode1, op0, *op0_mode,
 				     bitnum / BITS_PER_UNIT);
       if (sub)
 	return convert_extracted_bit_field (sub, mode, tmode, unsignedp);
@@ -1761,18 +1789,19 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* If OP0 is a multi-word register, narrow it to the affected word.
      If the region spans two words, defer to extract_split_bit_field.  */
-  if (!MEM_P (op0) && GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
+  if (!MEM_P (op0) && GET_MODE_SIZE (*op0_mode) > UNITS_PER_WORD)
     {
       if (bitnum % BITS_PER_WORD + bitsize > BITS_PER_WORD)
 	{
 	  if (!fallback_p)
 	    return NULL_RTX;
-	  target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
-					    reverse);
+	  target = extract_split_bit_field (op0, op0_mode, bitsize, bitnum,
+					    unsignedp, reverse);
 	  return convert_extracted_bit_field (target, mode, tmode, unsignedp);
 	}
-      op0 = simplify_gen_subreg (word_mode, op0, GET_MODE (op0),
+      op0 = simplify_gen_subreg (word_mode, op0, *op0_mode,
 				 bitnum / BITS_PER_WORD * UNITS_PER_WORD);
+      op0_mode = word_mode;
       bitnum %= BITS_PER_WORD;
     }
 
@@ -1786,10 +1815,10 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 	 contains the field, with appropriate checks for endianness
 	 and TRULY_NOOP_TRUNCATION.  */
       && get_best_reg_extraction_insn (&extv, pattern,
-				       GET_MODE_BITSIZE (GET_MODE (op0)),
-				       tmode))
+				       GET_MODE_BITSIZE (*op0_mode), tmode))
     {
-      rtx result = extract_bit_field_using_extv (&extv, op0, bitsize, bitnum,
+      rtx result = extract_bit_field_using_extv (&extv, op0, op0_mode,
+						 bitsize, bitnum,
 						 unsignedp, target, mode,
 						 tmode);
       if (result)
@@ -1803,9 +1832,9 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       if (get_best_mem_extraction_insn (&extv, pattern, bitsize, bitnum,
 					tmode))
 	{
-	  rtx result = extract_bit_field_using_extv (&extv, op0, bitsize,
-						     bitnum, unsignedp,
-						     target, mode,
+	  rtx result = extract_bit_field_using_extv (&extv, op0, op0_mode,
+						     bitsize, bitnum,
+						     unsignedp, target, mode,
 						     tmode);
 	  if (result)
 	    return result;
@@ -1841,8 +1870,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
        do a load.  */
     int_mode = *int_mode_for_mode (mode);
 
-  target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
-				    unsignedp, reverse);
+  target = extract_fixed_bit_field (int_mode, op0, op0_mode, bitsize,
+				    bitnum, target, unsignedp, reverse);
 
   /* Complex values must be reversed piecewise, so we need to undo the global
      reversal, convert to the complex mode and reverse again.  */
@@ -1920,7 +1949,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 }
 \f
 /* Use shifts and boolean operations to extract a field of BITSIZE bits
-   from bit BITNUM of OP0.
+   from bit BITNUM of OP0.  If OP0_MODE is defined, it is the mode of OP0,
+   otherwise OP0 is a BLKmode MEM.
 
    UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
    If REVERSE is true, the extraction is to be done in reverse order.
@@ -1931,39 +1961,40 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
 static rtx
 extract_fixed_bit_field (machine_mode tmode, rtx op0,
+			 opt_scalar_int_mode op0_mode,
 			 unsigned HOST_WIDE_INT bitsize,
 			 unsigned HOST_WIDE_INT bitnum, rtx target,
 			 int unsignedp, bool reverse)
 {
+  scalar_int_mode mode;
   if (MEM_P (op0))
     {
-      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,
-					reverse);
+	return extract_split_bit_field (op0, op0_mode, bitsize, bitnum,
+					unsignedp, reverse);
 
       op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
     }
+  else
+    mode = *op0_mode;
 
-  return extract_fixed_bit_field_1 (tmode, op0, bitsize, bitnum,
+  return extract_fixed_bit_field_1 (tmode, op0, mode, bitsize, bitnum,
 				    target, unsignedp, reverse);
 }
 
 /* Helper function for extract_fixed_bit_field, extracts
-   the bit field always using the MODE of OP0.  */
+   the bit field always using MODE, which is the mode of OP0.
+   The other arguments are as for extract_fixed_bit_field.  */
 
 static rtx
-extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
+extract_fixed_bit_field_1 (machine_mode tmode, rtx op0, scalar_int_mode mode,
 			   unsigned HOST_WIDE_INT bitsize,
 			   unsigned HOST_WIDE_INT bitnum, rtx target,
 			   int unsignedp, bool reverse)
 {
-  machine_mode mode = GET_MODE (op0);
-  gcc_assert (SCALAR_INT_MODE_P (mode));
-
   /* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode)
      for invalid input, such as extract equivalent of f5 from
      gcc.dg/pr48335-2.c.  */
@@ -1990,16 +2021,19 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
 	    subtarget = 0;
 	  op0 = expand_shift (RSHIFT_EXPR, mode, op0, bitnum, subtarget, 1);
 	}
-      /* Convert the value to the desired mode.  */
-      if (mode != tmode)
-	op0 = convert_to_mode (tmode, op0, 1);
+      /* Convert the value to the desired mode.  TMODE must also be a
+	 scalar integer for this conversion to make sense, since we
+	 shouldn't reinterpret the bits.  */
+      scalar_int_mode new_mode = as_a <scalar_int_mode> (tmode);
+      if (mode != new_mode)
+	op0 = convert_to_mode (new_mode, op0, 1);
 
       /* Unless the msb of the field used to be the msb when we shifted,
 	 mask out the upper bits.  */
 
       if (GET_MODE_BITSIZE (mode) != bitnum + bitsize)
-	return expand_binop (GET_MODE (op0), and_optab, op0,
-			     mask_rtx (GET_MODE (op0), 0, bitsize, 0),
+	return expand_binop (new_mode, and_optab, op0,
+			     mask_rtx (new_mode, 0, bitsize, 0),
 			     target, 1, OPTAB_LIB_WIDEN);
       return op0;
     }
@@ -2049,11 +2083,14 @@ lshift_value (machine_mode mode, unsigned HOST_WIDE_INT value,
    OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
    BITSIZE is the field width; BITPOS, position of its first bit, in the word.
    UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.
+   If OP0_MODE is defined, it is the mode of OP0, otherwise OP0 is
+   a BLKmode MEM.
 
    If REVERSE is true, the extraction is to be done in reverse order.  */
 
 static rtx
-extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
+extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
+			 unsigned HOST_WIDE_INT bitsize,
 			 unsigned HOST_WIDE_INT bitpos, int unsignedp,
 			 bool reverse)
 {
@@ -2072,7 +2109,7 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
   while (bitsdone < bitsize)
     {
       unsigned HOST_WIDE_INT thissize;
-      rtx part, word;
+      rtx part;
       unsigned HOST_WIDE_INT thispos;
       unsigned HOST_WIDE_INT offset;
 
@@ -2086,19 +2123,21 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
       thissize = MIN (thissize, unit - thispos);
 
       /* If OP0 is a register, then handle OFFSET here.  */
+      rtx op0_piece = op0;
+      opt_scalar_int_mode op0_piece_mode = op0_mode;
       if (SUBREG_P (op0) || REG_P (op0))
 	{
-	  word = operand_subword_force (op0, offset, GET_MODE (op0));
+	  op0_piece = operand_subword_force (op0, offset, *op0_mode);
+	  op0_piece_mode = word_mode;
 	  offset = 0;
 	}
-      else
-	word = op0;
 
       /* Extract the parts in bit-counting order,
 	 whose meaning is determined by BYTES_PER_UNIT.
 	 OFFSET is in UNITs, and UNIT is in bits.  */
-      part = extract_fixed_bit_field (word_mode, word, thissize,
-				      offset * unit + thispos, 0, 1, reverse);
+      part = extract_fixed_bit_field (word_mode, op0_piece, op0_piece_mode,
+				      thissize, offset * unit + thispos,
+				      0, 1, reverse);
       bitsdone += thissize;
 
       /* Shift this part into place for the result.  */

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

* [53/67] Pass a mode to const_scalar_mask_from_tree
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (52 preceding siblings ...)
  2016-12-09 13:30 ` [51/67] Use opt_scalar_int_mode when iterating over integer modes Richard Sandiford
@ 2016-12-09 13:31 ` Richard Sandiford
  2016-12-09 13:31 ` [54/67] Add explicit int checks for alternative optab implementations Richard Sandiford
                   ` (15 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:31 UTC (permalink / raw)
  To: gcc-patches

The caller of const_scalar_mask_from_tree has proven that
the mode is a MODE_INT, so this patch passes it down as a
scalar_int_mode.  It also expands the comment a little.

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

	* expr.c (const_scalar_mask_from_tree): Add a mode argument.
	Expand commentary.
	(expand_expr_real_1): Update call accordingly.

diff --git a/gcc/expr.c b/gcc/expr.c
index ec88d35..465326c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -97,7 +97,7 @@ static void emit_single_push_insn (machine_mode, rtx, tree);
 #endif
 static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
 static rtx const_vector_from_tree (tree);
-static rtx const_scalar_mask_from_tree (tree);
+static rtx const_scalar_mask_from_tree (scalar_int_mode, tree);
 static tree tree_expr_size (const_tree);
 static HOST_WIDE_INT int_expr_size (tree);
 
@@ -9893,7 +9893,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	if (is_int_mode (mode, &int_mode))
 	  {
 	    if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
-	      return const_scalar_mask_from_tree (exp);
+	      return const_scalar_mask_from_tree (int_mode, exp);
 	    else
 	      {
 		tree type_for_mode
@@ -11646,12 +11646,12 @@ const_vector_mask_from_tree (tree exp)
   return gen_rtx_CONST_VECTOR (mode, v);
 }
 
-/* Return a CONST_INT rtx representing vector mask for
-   a VECTOR_CST of booleans.  */
+/* EXP is a VECTOR_CST in which each element is either all-zeros or all-ones.
+   Return a constant scalar rtx of mode MODE in which bit X is set if element
+   X of EXP is nonzero.  */
 static rtx
-const_scalar_mask_from_tree (tree exp)
+const_scalar_mask_from_tree (scalar_int_mode mode, tree exp)
 {
-  machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   wide_int res = wi::zero (GET_MODE_PRECISION (mode));
   tree elt;
   unsigned i;

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

* [54/67] Add explicit int checks for alternative optab implementations
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (53 preceding siblings ...)
  2016-12-09 13:31 ` [53/67] Pass a mode to const_scalar_mask_from_tree Richard Sandiford
@ 2016-12-09 13:31 ` Richard Sandiford
  2016-12-09 13:33 ` [55/67] Use scalar_int_mode in simplify_const_unary_operation Richard Sandiford
                   ` (14 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:31 UTC (permalink / raw)
  To: gcc-patches

expand_unop can expand narrow clz, clrsb, ctz, bswap, parity and
ffs operations using optabs for wider modes.  These expansions
apply only to scalar integer modes (and not for example to vectors),
so the patch adds explicit checks for that.

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

	* optabs.c (widen_leading): Change the type of the mode argument
	to scalar_int_mode.  Use opt_scalar_int_mode for the mode iterator.
	(widen_bswap): Likewise.
	(expand_parity): Likewise.
	(expand_ctz): Change the type of the mode argument to scalar_int_mode.
	(expand_ffs): Likewise.
	(epand_unop): Check for scalar integer modes before calling the
	above routines.

diff --git a/gcc/optabs.c b/gcc/optabs.c
index 509f0d3..cc03c9b 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2127,39 +2127,36 @@ expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0,
    A similar operation can be used for clrsb.  UNOPTAB says which operation
    we are trying to expand.  */
 static rtx
-widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab)
+widen_leading (scalar_int_mode mode, rtx op0, rtx target, optab unoptab)
 {
-  enum mode_class mclass = GET_MODE_CLASS (mode);
-  if (CLASS_HAS_WIDER_MODES_P (mclass))
+  opt_scalar_int_mode wider_mode_iter;
+  FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
     {
-      machine_mode wider_mode;
-      FOR_EACH_WIDER_MODE (wider_mode, mode)
+      scalar_int_mode wider_mode = *wider_mode_iter;
+      if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
 	{
-	  if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing)
-	    {
-	      rtx xop0, temp;
-	      rtx_insn *last;
+	  rtx xop0, temp;
+	  rtx_insn *last;
 
-	      last = get_last_insn ();
+	  last = get_last_insn ();
 
-	      if (target == 0)
-		target = gen_reg_rtx (mode);
-	      xop0 = widen_operand (op0, wider_mode, mode,
-				    unoptab != clrsb_optab, false);
-	      temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
-				  unoptab != clrsb_optab);
-	      if (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);
-	      if (temp == 0)
-		delete_insns_since (last);
+	  if (target == 0)
+	    target = gen_reg_rtx (mode);
+	  xop0 = widen_operand (op0, wider_mode, mode,
+				unoptab != clrsb_optab, false);
+	  temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
+			      unoptab != clrsb_optab);
+	  if (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);
+	  if (temp == 0)
+	    delete_insns_since (last);
 
-	      return temp;
-	    }
+	  return temp;
 	}
     }
   return 0;
@@ -2293,22 +2290,20 @@ expand_doubleword_parity (machine_mode mode, rtx op0, rtx target)
    as
 	(lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))).  */
 static rtx
-widen_bswap (machine_mode mode, rtx op0, rtx target)
+widen_bswap (scalar_int_mode mode, rtx op0, rtx target)
 {
-  enum mode_class mclass = GET_MODE_CLASS (mode);
-  machine_mode wider_mode;
   rtx x;
   rtx_insn *last;
+  opt_scalar_int_mode wider_mode_iter;
 
-  if (!CLASS_HAS_WIDER_MODES_P (mclass))
-    return NULL_RTX;
+  FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
+    if (optab_handler (bswap_optab, *wider_mode_iter) != CODE_FOR_nothing)
+      break;
 
-  FOR_EACH_WIDER_MODE (wider_mode, mode)
-    if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing)
-      goto found;
-  return NULL_RTX;
+  if (!wider_mode_iter.exists ())
+    return NULL_RTX;
 
- found:
+  scalar_int_mode wider_mode = *wider_mode_iter;
   last = get_last_insn ();
 
   x = widen_operand (op0, wider_mode, mode, true, true);
@@ -2359,42 +2354,40 @@ expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)
 /* Try calculating (parity x) as (and (popcount x) 1), where
    popcount can also be done in a wider mode.  */
 static rtx
-expand_parity (machine_mode mode, rtx op0, rtx target)
+expand_parity (scalar_int_mode mode, rtx op0, rtx target)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
-  if (CLASS_HAS_WIDER_MODES_P (mclass))
+  opt_scalar_int_mode wider_mode_iter;
+  FOR_EACH_MODE_FROM (wider_mode_iter, mode)
     {
-      machine_mode wider_mode;
-      FOR_EACH_MODE_FROM (wider_mode, mode)
+      scalar_int_mode wider_mode = *wider_mode_iter;
+      if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
 	{
-	  if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing)
-	    {
-	      rtx xop0, temp;
-	      rtx_insn *last;
+	  rtx xop0, temp;
+	  rtx_insn *last;
 
-	      last = get_last_insn ();
+	  last = get_last_insn ();
 
-	      if (target == 0 || GET_MODE (target) != wider_mode)
-		target = gen_reg_rtx (wider_mode);
+	  if (target == 0 || GET_MODE (target) != wider_mode)
+	    target = gen_reg_rtx (wider_mode);
 
-	      xop0 = widen_operand (op0, wider_mode, mode, true, false);
-	      temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
-				  true);
-	      if (temp != 0)
-		temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
-				     target, true, OPTAB_DIRECT);
+	  xop0 = widen_operand (op0, wider_mode, mode, true, false);
+	  temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
+			      true);
+	  if (temp != 0)
+	    temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
+				 target, true, OPTAB_DIRECT);
 
-	      if (temp)
-		{
-		  if (mclass != MODE_INT
-		      || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
-		    return convert_to_mode (mode, temp, 0);
-		  else
-		    return gen_lowpart (mode, temp);
-		}
+	  if (temp)
+	    {
+	      if (mclass != MODE_INT
+		  || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
+		return convert_to_mode (mode, temp, 0);
 	      else
-		delete_insns_since (last);
+		return gen_lowpart (mode, temp);
 	    }
+	  else
+	    delete_insns_since (last);
 	}
     }
   return 0;
@@ -2413,7 +2406,7 @@ expand_parity (machine_mode mode, rtx op0, rtx target)
    less convenient for expand_ffs anyway.  */
 
 static rtx
-expand_ctz (machine_mode mode, rtx op0, rtx target)
+expand_ctz (scalar_int_mode mode, rtx op0, rtx target)
 {
   rtx_insn *seq;
   rtx temp;
@@ -2456,7 +2449,7 @@ expand_ctz (machine_mode mode, rtx op0, rtx target)
    may have an undefined value in that case.  If they do not give us a
    convenient value, we have to generate a test and branch.  */
 static rtx
-expand_ffs (machine_mode mode, rtx op0, rtx target)
+expand_ffs (scalar_int_mode mode, rtx op0, rtx target)
 {
   HOST_WIDE_INT val = 0;
   bool defined_at_zero = false;
@@ -2713,16 +2706,19 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
   /* Widening (or narrowing) clz needs special treatment.  */
   if (unoptab == clz_optab)
     {
-      temp = widen_leading (mode, op0, target, unoptab);
-      if (temp)
-	return temp;
-
-      if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-	  && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
+      if (is_a <scalar_int_mode> (mode, &int_mode))
 	{
-	  temp = expand_doubleword_clz (mode, op0, target);
+	  temp = widen_leading (int_mode, op0, target, unoptab);
 	  if (temp)
 	    return temp;
+
+	  if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+	      && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
+	    {
+	      temp = expand_doubleword_clz (int_mode, op0, target);
+	      if (temp)
+		return temp;
+	    }
 	}
 
       goto try_libcall;
@@ -2730,9 +2726,12 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 
   if (unoptab == clrsb_optab)
     {
-      temp = widen_leading (mode, op0, target, unoptab);
-      if (temp)
-	return temp;
+      if (is_a <scalar_int_mode> (mode, &int_mode))
+	{
+	  temp = widen_leading (int_mode, op0, target, unoptab);
+	  if (temp)
+	    return temp;
+	}
       goto try_libcall;
     }
 
@@ -2804,16 +2803,19 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
 	  delete_insns_since (last);
 	}
 
-      temp = widen_bswap (mode, op0, target);
-      if (temp)
-	return temp;
-
-      if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
-	  && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
+      if (is_a <scalar_int_mode> (mode, &int_mode))
 	{
-	  temp = expand_doubleword_bswap (mode, op0, target);
+	  temp = widen_bswap (int_mode, op0, target);
 	  if (temp)
 	    return temp;
+
+	  if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
+	      && optab_handler (unoptab, word_mode) != CODE_FOR_nothing)
+	    {
+	      temp = expand_doubleword_bswap (mode, op0, target);
+	      if (temp)
+		return temp;
+	    }
 	}
 
       goto try_libcall;
@@ -2914,25 +2916,25 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
     }
 
   /* Try calculating parity (x) as popcount (x) % 2.  */
-  if (unoptab == parity_optab)
+  if (unoptab == parity_optab && is_a <scalar_int_mode> (mode, &int_mode))
     {
-      temp = expand_parity (mode, op0, target);
+      temp = expand_parity (int_mode, op0, target);
       if (temp)
 	return temp;
     }
 
   /* Try implementing ffs (x) in terms of clz (x).  */
-  if (unoptab == ffs_optab)
+  if (unoptab == ffs_optab && is_a <scalar_int_mode> (mode, &int_mode))
     {
-      temp = expand_ffs (mode, op0, target);
+      temp = expand_ffs (int_mode, op0, target);
       if (temp)
 	return temp;
     }
 
   /* Try implementing ctz (x) in terms of clz (x).  */
-  if (unoptab == ctz_optab)
+  if (unoptab == ctz_optab && is_a <scalar_int_mode> (mode, &int_mode))
     {
-      temp = expand_ctz (mode, op0, target);
+      temp = expand_ctz (int_mode, op0, target);
       if (temp)
 	return temp;
     }

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

* [56/67] Use the more specific type when two modes are known to be equal
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (55 preceding siblings ...)
  2016-12-09 13:33 ` [55/67] Use scalar_int_mode in simplify_const_unary_operation Richard Sandiford
@ 2016-12-09 13:33 ` Richard Sandiford
  2016-12-09 13:34 ` [57/67] Use scalar_int_mode in expand_expr_addr_expr Richard Sandiford
                   ` (12 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:33 UTC (permalink / raw)
  To: gcc-patches

This patch adjusts a couple of cases in which we had established
that two modes were equal and happened to be using the one with
the more general type instead of the one with the more specific
type.

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 word_mode instead of innermode
	when the two are known to be equal.

diff --git a/gcc/expr.c b/gcc/expr.c
index 465326c..0d50bd0 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8666,7 +8666,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		  rtx htem, hipart;
 		  op0 = expand_normal (treeop0);
 		  if (TREE_CODE (treeop1) == INTEGER_CST)
-		    op1 = convert_modes (innermode, mode,
+		    op1 = convert_modes (word_mode, mode,
 					 expand_normal (treeop1),
 					 TYPE_UNSIGNED (TREE_TYPE (treeop1)));
 		  else
@@ -8677,8 +8677,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 		    goto widen_mult_const;
 		  temp = expand_binop (mode, other_optab, op0, op1, target,
 				       unsignedp, OPTAB_LIB_WIDEN);
-		  hipart = gen_highpart (innermode, temp);
-		  htem = expand_mult_highpart_adjust (innermode, hipart,
+		  hipart = gen_highpart (word_mode, temp);
+		  htem = expand_mult_highpart_adjust (word_mode, hipart,
 						      op0, op1, hipart,
 						      zextend_p);
 		  if (htem != hipart)

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

* [55/67] Use scalar_int_mode in simplify_const_unary_operation
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (54 preceding siblings ...)
  2016-12-09 13:31 ` [54/67] Add explicit int checks for alternative optab implementations Richard Sandiford
@ 2016-12-09 13:33 ` Richard Sandiford
  2016-12-09 13:33 ` [56/67] Use the more specific type when two modes are known to be equal Richard Sandiford
                   ` (13 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:33 UTC (permalink / raw)
  To: gcc-patches

The main scalar integer block in simplify_const_unary_operation
had the condition:

  if (CONST_SCALAR_INT_P (op) && width > 0)

where "width > 0" was a roundabout way of testing != VOIDmode.
This patch replaces it with a check for a scalar_int_mode instead.
It also uses the number of bits in the input rather than the output
mode to determine the result of a "count ... bits in zero" operation.
(At the momemnt these modes have to be the same, but it still seems
conceptually wrong to use the number of bits in the output mode.)

The handling of float->integer ops also checked "width > 0",
but this was redundant with the earlier check for MODE_INT.

These changes require the rtl wi:: routines to take machine_mode_enums,
to avoid an ambiguity when using scalar_int_modes instead of
machine_modes.  The problem is that machine_mode_enum (like all enums)
can be implicitly converted to an integer, and so the mode classes can
indirectly be converted to an integer too.  (And this is useful when
modes are used as array indices, for example.)  So when scalar_int_mode
was used, the non-rtl wi:: candidates that take integer precisions
instead of modes had the same rank as the machine_mode ones.

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

	* rtl.h (wi::shwi): Take a machine_mode_enum rather than
	a machine_mode.
	(wi::min_value): Likewise.
	(wi::max_value): Likewise,
	* simplify-rtx.c (simplify_const_unary_operation): Use
	is_a <scalar_int_mode> instead of checking for a nonzero
	precision.  Forcibly convert op_mode to a scalar_int_mode
	in that case.  More clearly differentiate the operand and
	result modes and use the former when deciding what the value
	of a count-bits operation should be.  Use is_int_mode instead
	of checking for a MODE_INT.  Remove redundant check for whether
	this mode has a zero precision.

diff --git a/gcc/rtl.h b/gcc/rtl.h
index e65020a..a5ca103 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2139,13 +2139,13 @@ wi::int_traits <rtx_mode_t>::decompose (HOST_WIDE_INT *,
 
 namespace wi
 {
-  hwi_with_prec shwi (HOST_WIDE_INT, machine_mode mode);
-  wide_int min_value (machine_mode, signop);
-  wide_int max_value (machine_mode, signop);
+  hwi_with_prec shwi (HOST_WIDE_INT, machine_mode_enum);
+  wide_int min_value (machine_mode_enum, signop);
+  wide_int max_value (machine_mode_enum, signop);
 }
 
 inline wi::hwi_with_prec
-wi::shwi (HOST_WIDE_INT val, machine_mode mode)
+wi::shwi (HOST_WIDE_INT val, machine_mode_enum mode)
 {
   return shwi (val, GET_MODE_PRECISION (mode));
 }
@@ -2153,7 +2153,7 @@ wi::shwi (HOST_WIDE_INT val, machine_mode mode)
 /* Produce the smallest number that is represented in MODE.  The precision
    is taken from MODE and the sign from SGN.  */
 inline wide_int
-wi::min_value (machine_mode mode, signop sgn)
+wi::min_value (machine_mode_enum mode, signop sgn)
 {
   return min_value (GET_MODE_PRECISION (mode), sgn);
 }
@@ -2161,7 +2161,7 @@ wi::min_value (machine_mode mode, signop sgn)
 /* Produce the largest number that is represented in MODE.  The precision
    is taken from MODE and the sign from SGN.  */
 inline wide_int
-wi::max_value (machine_mode mode, signop sgn)
+wi::max_value (machine_mode_enum mode, signop sgn)
 {
   return max_value (GET_MODE_PRECISION (mode), sgn);
 }
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index f4997bf..465e02a 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1683,7 +1683,7 @@ rtx
 simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
 				rtx op, machine_mode op_mode)
 {
-  unsigned int width = GET_MODE_PRECISION (mode);
+  scalar_int_mode result_mode;
 
   if (code == VEC_DUPLICATE)
     {
@@ -1798,10 +1798,13 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
       return const_double_from_real_value (d, mode);
     }
 
-  if (CONST_SCALAR_INT_P (op) && width > 0)
+  if (CONST_SCALAR_INT_P (op) && is_a <scalar_int_mode> (mode, &result_mode))
     {
+      unsigned int width = GET_MODE_PRECISION (result_mode);
       wide_int result;
-      machine_mode imode = op_mode == VOIDmode ? mode : op_mode;
+      scalar_int_mode imode = (op_mode == VOIDmode
+			       ? result_mode
+			       : as_a <scalar_int_mode> (op_mode));
       rtx_mode_t op0 = rtx_mode_t (op, imode);
       int int_value;
 
@@ -1830,35 +1833,35 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
 	  break;
 
 	case FFS:
-	  result = wi::shwi (wi::ffs (op0), mode);
+	  result = wi::shwi (wi::ffs (op0), result_mode);
 	  break;
 
 	case CLZ:
 	  if (wi::ne_p (op0, 0))
 	    int_value = wi::clz (op0);
-	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, int_value))
-	    int_value = GET_MODE_PRECISION (mode);
-	  result = wi::shwi (int_value, mode);
+	  else if (! CLZ_DEFINED_VALUE_AT_ZERO (imode, int_value))
+	    int_value = GET_MODE_PRECISION (imode);
+	  result = wi::shwi (int_value, result_mode);
 	  break;
 
 	case CLRSB:
-	  result = wi::shwi (wi::clrsb (op0), mode);
+	  result = wi::shwi (wi::clrsb (op0), result_mode);
 	  break;
 
 	case CTZ:
 	  if (wi::ne_p (op0, 0))
 	    int_value = wi::ctz (op0);
-	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, int_value))
-	    int_value = GET_MODE_PRECISION (mode);
-	  result = wi::shwi (int_value, mode);
+	  else if (! CTZ_DEFINED_VALUE_AT_ZERO (imode, int_value))
+	    int_value = GET_MODE_PRECISION (imode);
+	  result = wi::shwi (int_value, result_mode);
 	  break;
 
 	case POPCOUNT:
-	  result = wi::shwi (wi::popcount (op0), mode);
+	  result = wi::shwi (wi::popcount (op0), result_mode);
 	  break;
 
 	case PARITY:
-	  result = wi::shwi (wi::parity (op0), mode);
+	  result = wi::shwi (wi::parity (op0), result_mode);
 	  break;
 
 	case BSWAP:
@@ -1879,7 +1882,7 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
 	  return 0;
 	}
 
-      return immed_wide_int_const (result, mode);
+      return immed_wide_int_const (result, result_mode);
     }
 
   else if (CONST_DOUBLE_AS_FLOAT_P (op) 
@@ -1936,9 +1939,9 @@ simplify_const_unary_operation (enum rtx_code code, machine_mode mode,
     }
   else if (CONST_DOUBLE_AS_FLOAT_P (op)
 	   && SCALAR_FLOAT_MODE_P (GET_MODE (op))
-	   && GET_MODE_CLASS (mode) == MODE_INT
-	   && width > 0)
+	   && is_int_mode (mode, &result_mode))
     {
+      unsigned int width = GET_MODE_PRECISION (result_mode);
       /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX
 	 operators are intentionally left unspecified (to ease implementation
 	 by target backends), for consistency, this routine implements the

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

* [57/67] Use scalar_int_mode in expand_expr_addr_expr
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (56 preceding siblings ...)
  2016-12-09 13:33 ` [56/67] Use the more specific type when two modes are known to be equal Richard Sandiford
@ 2016-12-09 13:34 ` Richard Sandiford
  2016-12-09 13:35 ` [58/67] Use scalar_int_mode in a try_combine optimisation Richard Sandiford
                   ` (11 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:34 UTC (permalink / raw)
  To: gcc-patches

This patch rewrites the condition:

  if (tmode != address_mode && tmode != pointer_mode)
    tmode = address_mode;

to the equivalent:

  tmode == pointer_mode ? pointer_mode : address_mode

The latter has the advantage that the result is naturally
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>

	* expr.c (expand_expr_addr_expr): Add a new_tmode local variable
	that is always either address_mode or pointer_mode.

diff --git a/gcc/expr.c b/gcc/expr.c
index 0d50bd0..b331563 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7909,20 +7909,21 @@ expand_expr_addr_expr (tree exp, rtx target, machine_mode tmode,
   /* We can get called with some Weird Things if the user does silliness
      like "(short) &a".  In that case, convert_memory_address won't do
      the right thing, so ignore the given target mode.  */
-  if (tmode != address_mode && tmode != pointer_mode)
-    tmode = address_mode;
+  machine_mode new_tmode = (tmode == pointer_mode
+			    ? pointer_mode
+			    : address_mode);
 
   result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
-				    tmode, modifier, as);
+				    new_tmode, modifier, as);
 
   /* Despite expand_expr claims concerning ignoring TMODE when not
      strictly convenient, stuff breaks if we don't honor it.  Note
      that combined with the above, we only do this for pointer modes.  */
   rmode = GET_MODE (result);
   if (rmode == VOIDmode)
-    rmode = tmode;
-  if (rmode != tmode)
-    result = convert_memory_address_addr_space (tmode, result, as);
+    rmode = new_tmode;
+  if (rmode != new_tmode)
+    result = convert_memory_address_addr_space (new_tmode, result, as);
 
   return result;
 }

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

* [58/67] Use scalar_int_mode in a try_combine optimisation
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (57 preceding siblings ...)
  2016-12-09 13:34 ` [57/67] Use scalar_int_mode in expand_expr_addr_expr Richard Sandiford
@ 2016-12-09 13:35 ` Richard Sandiford
  2016-12-09 13:36 ` [59/67] Add a rtx_jump_table_data::get_data_mode helper Richard Sandiford
                   ` (10 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:35 UTC (permalink / raw)
  To: gcc-patches

This patch uses scalar_int_modes for:

  /* If I2 is setting a pseudo to a constant and I3 is setting some
     sub-part of it to another constant, merge them by making a new
     constant.  */

This was already implicit, but the danger with just checking
CONST_SCALAR_INT_P is that it can include CC values too.

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_combine): Use is_a <scalar_int_mode> when
	trying to combine a full-register integer set with a subreg
	integer set.

diff --git a/gcc/combine.c b/gcc/combine.c
index 6e32b37..dd7f1fa 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2631,6 +2631,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
   rtx other_pat = 0;
   rtx new_other_notes;
   int i;
+  scalar_int_mode dest_mode, temp_mode;
 
   /* Immediately return if any of I0,I1,I2 are the same insn (I3 can
      never be).  */
@@ -2831,33 +2832,40 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
      constant.  */
   if (i1 == 0
       && (temp_expr = single_set (i2)) != 0
+      && is_a <scalar_int_mode> (GET_MODE (SET_DEST (temp_expr)), &temp_mode)
       && CONST_SCALAR_INT_P (SET_SRC (temp_expr))
       && GET_CODE (PATTERN (i3)) == SET
       && CONST_SCALAR_INT_P (SET_SRC (PATTERN (i3)))
       && reg_subword_p (SET_DEST (PATTERN (i3)), SET_DEST (temp_expr)))
     {
       rtx dest = SET_DEST (PATTERN (i3));
+      rtx temp_dest = SET_DEST (temp_expr);
       int offset = -1;
       int width = 0;
-      
+
       if (GET_CODE (dest) == ZERO_EXTRACT)
 	{
 	  if (CONST_INT_P (XEXP (dest, 1))
-	      && CONST_INT_P (XEXP (dest, 2)))
+	      && CONST_INT_P (XEXP (dest, 2))
+	      && is_a <scalar_int_mode> (GET_MODE (XEXP (dest, 0)),
+					 &dest_mode))
 	    {
 	      width = INTVAL (XEXP (dest, 1));
 	      offset = INTVAL (XEXP (dest, 2));
 	      dest = XEXP (dest, 0);
 	      if (BITS_BIG_ENDIAN)
-		offset = GET_MODE_PRECISION (GET_MODE (dest)) - width - offset;
+		offset = GET_MODE_PRECISION (dest_mode) - width - offset;
 	    }
 	}
       else
 	{
 	  if (GET_CODE (dest) == STRICT_LOW_PART)
 	    dest = XEXP (dest, 0);
-	  width = GET_MODE_PRECISION (GET_MODE (dest));
-	  offset = 0;
+	  if (is_a <scalar_int_mode> (GET_MODE (dest), &dest_mode))
+	    {
+	      width = GET_MODE_PRECISION (dest_mode);
+	      offset = 0;
+	    }
 	}
 
       if (offset >= 0)
@@ -2866,9 +2874,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 	  if (subreg_lowpart_p (dest))
 	    ;
 	  /* Handle the case where inner is twice the size of outer.  */
-	  else if (GET_MODE_PRECISION (GET_MODE (SET_DEST (temp_expr)))
-		   == 2 * GET_MODE_PRECISION (GET_MODE (dest)))
-	    offset += GET_MODE_PRECISION (GET_MODE (dest));
+	  else if (GET_MODE_PRECISION (temp_mode)
+		   == 2 * GET_MODE_PRECISION (dest_mode))
+	    offset += GET_MODE_PRECISION (dest_mode);
 	  /* Otherwise give up for now.  */
 	  else
 	    offset = -1;
@@ -2879,23 +2887,22 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 	  rtx inner = SET_SRC (PATTERN (i3));
 	  rtx outer = SET_SRC (temp_expr);
 
-	  wide_int o
-	    = wi::insert (rtx_mode_t (outer, GET_MODE (SET_DEST (temp_expr))),
-			  rtx_mode_t (inner, GET_MODE (dest)),
-			  offset, width);
+	  wide_int o = wi::insert (rtx_mode_t (outer, temp_mode),
+				   rtx_mode_t (inner, dest_mode),
+				   offset, width);
 
 	  combine_merges++;
 	  subst_insn = i3;
 	  subst_low_luid = DF_INSN_LUID (i2);
 	  added_sets_2 = added_sets_1 = added_sets_0 = 0;
-	  i2dest = SET_DEST (temp_expr);
+	  i2dest = temp_dest;
 	  i2dest_killed = dead_or_set_p (i2, i2dest);
 
 	  /* Replace the source in I2 with the new constant and make the
 	     resulting insn the new pattern for I3.  Then skip to where we
 	     validate the pattern.  Everything was set up above.  */
 	  SUBST (SET_SRC (temp_expr),
-		 immed_wide_int_const (o, GET_MODE (SET_DEST (temp_expr))));
+		 immed_wide_int_const (o, temp_mode));
 
 	  newpat = PATTERN (i2);
 

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

* [60/67] Pass scalar_int_modes to do_jump_by_parts_*
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (59 preceding siblings ...)
  2016-12-09 13:36 ` [59/67] Add a rtx_jump_table_data::get_data_mode helper Richard Sandiford
@ 2016-12-09 13:36 ` Richard Sandiford
  2016-12-09 13:37 ` [61/67] Use scalar_int_mode in the AArch64 port Richard Sandiford
                   ` (8 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:36 UTC (permalink / raw)
  To: gcc-patches

The callers of do_jump_by_parts_* had already established
that the modes were MODE_INTs, so this patch passes the
modes down as scalar_int_modes.

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

	* dojump.c (do_jump_by_parts_greater_rtx): Change the type of
	the mode argument to scalar_int_mode.
	(do_jump_by_parts_zero_rtx): Likewise.
	(do_jump_by_parts_equality_rtx): Likewise.
	(do_jump_by_parts_greater): Take a mode argument.
	(do_jump_by_parts_equality): Likewise.
	(do_jump_1): Update calls accordingly.

diff --git a/gcc/dojump.c b/gcc/dojump.c
index 749742b..c48d2ed 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -38,10 +38,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 
 static bool prefer_and_bit_test (machine_mode, int);
-static void do_jump_by_parts_greater (tree, tree, int,
+static void do_jump_by_parts_greater (scalar_int_mode, tree, tree, int,
 				      rtx_code_label *, rtx_code_label *, int);
-static void do_jump_by_parts_equality (tree, tree, rtx_code_label *,
-				       rtx_code_label *, int);
+static void do_jump_by_parts_equality (scalar_int_mode, tree, tree,
+				       rtx_code_label *, rtx_code_label *,
+				       int);
 static void do_compare_and_jump	(tree, tree, enum rtx_code, enum rtx_code,
 				 rtx_code_label *, rtx_code_label *, int);
 
@@ -226,7 +227,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 	  do_jump (op0, if_true_label, if_false_label, inv (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,
+	  do_jump_by_parts_equality (int_mode, op0, op1, if_false_label,
 				     if_true_label, prob);
         else
 	  do_compare_and_jump (op0, op1, EQ, EQ, if_false_label, if_true_label,
@@ -247,7 +248,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
 	  do_jump (op0, if_false_label, if_true_label, 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,
+	  do_jump_by_parts_equality (int_mode, 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,
@@ -259,7 +260,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
       mode = TYPE_MODE (TREE_TYPE (op0));
       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,
+	do_jump_by_parts_greater (int_mode, 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,
@@ -270,7 +271,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
       mode = TYPE_MODE (TREE_TYPE (op0));
       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,
+	do_jump_by_parts_greater (int_mode, 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,
@@ -281,7 +282,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
       mode = TYPE_MODE (TREE_TYPE (op0));
       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,
+	do_jump_by_parts_greater (int_mode, 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,
@@ -292,7 +293,7 @@ do_jump_1 (enum tree_code code, tree op0, tree op1,
       mode = TYPE_MODE (TREE_TYPE (op0));
       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,
+	do_jump_by_parts_greater (int_mode, 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,
@@ -671,7 +672,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
    Jump to IF_TRUE_LABEL if OP0 is greater, IF_FALSE_LABEL otherwise.  */
 
 static void
-do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
+do_jump_by_parts_greater_rtx (scalar_int_mode mode, int unsignedp, rtx op0,
 			      rtx op1, rtx_code_label *if_false_label,
 			      rtx_code_label *if_true_label,
 			      int prob)
@@ -746,16 +747,15 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
 /* Given a comparison expression EXP for values too wide to be compared
    with one insn, test the comparison and jump to the appropriate label.
    The code of EXP is ignored; we always test GT if SWAP is 0,
-   and LT if SWAP is 1.  */
+   and LT if SWAP is 1.  MODE is the mode of the two operands.  */
 
 static void
-do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
-			  rtx_code_label *if_false_label,
+do_jump_by_parts_greater (scalar_int_mode mode, tree treeop0, tree treeop1,
+			  int swap, rtx_code_label *if_false_label,
 			  rtx_code_label *if_true_label, int prob)
 {
   rtx op0 = expand_normal (swap ? treeop1 : treeop0);
   rtx op1 = expand_normal (swap ? treeop0 : treeop1);
-  machine_mode mode = TYPE_MODE (TREE_TYPE (treeop0));
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0));
 
   do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
@@ -768,7 +768,7 @@ do_jump_by_parts_greater (tree treeop0, tree treeop1, int swap,
    to indicate drop through.  */
 
 static void
-do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
+do_jump_by_parts_zero_rtx (scalar_int_mode mode, rtx op0,
 			   rtx_code_label *if_false_label,
 			   rtx_code_label *if_true_label, int prob)
 {
@@ -818,7 +818,7 @@ do_jump_by_parts_zero_rtx (machine_mode mode, rtx op0,
    to indicate drop through.  */
 
 static void
-do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
+do_jump_by_parts_equality_rtx (scalar_int_mode mode, rtx op0, rtx op1,
 			       rtx_code_label *if_false_label,
 			       rtx_code_label *if_true_label, int prob)
 {
@@ -855,16 +855,16 @@ do_jump_by_parts_equality_rtx (machine_mode mode, rtx op0, rtx op1,
 }
 
 /* Given an EQ_EXPR expression EXP for values too wide to be compared
-   with one insn, test the comparison and jump to the appropriate label.  */
+   with one insn, test the comparison and jump to the appropriate label.
+   MODE is the mode of the two operands.  */
 
 static void
-do_jump_by_parts_equality (tree treeop0, tree treeop1,
+do_jump_by_parts_equality (scalar_int_mode mode, tree treeop0, tree treeop1,
 			   rtx_code_label *if_false_label,
 			   rtx_code_label *if_true_label, int prob)
 {
   rtx op0 = expand_normal (treeop0);
   rtx op1 = expand_normal (treeop1);
-  machine_mode mode = TYPE_MODE (TREE_TYPE (treeop0));
   do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
 				 if_true_label, prob);
 }

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

* [59/67] Add a rtx_jump_table_data::get_data_mode helper
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (58 preceding siblings ...)
  2016-12-09 13:35 ` [58/67] Use scalar_int_mode in a try_combine optimisation Richard Sandiford
@ 2016-12-09 13:36 ` Richard Sandiford
  2016-12-09 13:36 ` [60/67] Pass scalar_int_modes to do_jump_by_parts_* Richard Sandiford
                   ` (9 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:36 UTC (permalink / raw)
  To: gcc-patches

This patch adds a helper function to get the mode of the addresses
or offsets in a jump table.  It also changes the final.c code to use
rtx_jump_table_data over rtx or rtx_insn in cases where it needed
to use the new helper.  This in turn meant adding a safe_dyn_cast
equivalent of safe_as_a, to cope with null NEXT_INSNs.

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

	* is-a.h (safe_dyn_cast): New function.
	* rtl.h (rtx_jump_table_data::get_data_mode): New function.
	(jump_table_for_label): Likewise.
	* final.c (final_addr_vec_align): Take an rtx_jump_table_data *
	instead of an rtx_insn *.
	(shorten_branches): Use dyn_cast instead of LABEL_P and
	JUMP_TABLE_DATA_P.  Use jump_table_for_label and
	rtx_jump_table_data::get_data_mode.
	(final_scan_insn): Likewise.

diff --git a/gcc/final.c b/gcc/final.c
index 91acb01..388ef64 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -213,9 +213,6 @@ static void leaf_renumber_regs (rtx_insn *);
 #if HAVE_cc0
 static int alter_cond (rtx);
 #endif
-#ifndef ADDR_VEC_ALIGN
-static int final_addr_vec_align (rtx_insn *);
-#endif
 static int align_fuzz (rtx, rtx, int, unsigned);
 static void collect_fn_hard_reg_usage (void);
 static tree get_call_fndecl (rtx_insn *);
@@ -513,9 +510,9 @@ default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
 
 #ifndef ADDR_VEC_ALIGN
 static int
-final_addr_vec_align (rtx_insn *addr_vec)
+final_addr_vec_align (rtx_jump_table_data *addr_vec)
 {
-  int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
+  int align = GET_MODE_SIZE (addr_vec->get_data_mode ());
 
   if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
     align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
@@ -932,45 +929,41 @@ shorten_branches (rtx_insn *first)
       if (INSN_P (insn))
 	continue;
 
-      if (LABEL_P (insn))
+      if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
 	{
-	  rtx_insn *next;
-	  bool next_is_jumptable;
-
 	  /* Merge in alignments computed by compute_alignments.  */
-	  log = LABEL_TO_ALIGNMENT (insn);
+	  log = LABEL_TO_ALIGNMENT (label);
 	  if (max_log < log)
 	    {
 	      max_log = log;
-	      max_skip = LABEL_TO_MAX_SKIP (insn);
+	      max_skip = LABEL_TO_MAX_SKIP (label);
 	    }
 
-	  next = next_nonnote_insn (insn);
-	  next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
-	  if (!next_is_jumptable)
+	  rtx_jump_table_data *table = jump_table_for_label (label);
+	  if (!table)
 	    {
-	      log = LABEL_ALIGN (insn);
+	      log = LABEL_ALIGN (label);
 	      if (max_log < log)
 		{
 		  max_log = log;
-		  max_skip = targetm.asm_out.label_align_max_skip (insn);
+		  max_skip = targetm.asm_out.label_align_max_skip (label);
 		}
 	    }
 	  /* ADDR_VECs only take room if read-only data goes into the text
 	     section.  */
 	  if ((JUMP_TABLES_IN_TEXT_SECTION
 	       || readonly_data_section == text_section)
-	      && next_is_jumptable)
+	      && table)
 	    {
-	      log = ADDR_VEC_ALIGN (next);
+	      log = ADDR_VEC_ALIGN (table);
 	      if (max_log < log)
 		{
 		  max_log = log;
-		  max_skip = targetm.asm_out.label_align_max_skip (insn);
+		  max_skip = targetm.asm_out.label_align_max_skip (label);
 		}
 	    }
-	  LABEL_TO_ALIGNMENT (insn) = max_log;
-	  LABEL_TO_MAX_SKIP (insn) = max_skip;
+	  LABEL_TO_ALIGNMENT (label) = max_log;
+	  LABEL_TO_MAX_SKIP (label) = max_skip;
 	  max_log = 0;
 	  max_skip = 0;
 	}
@@ -1126,7 +1119,7 @@ shorten_branches (rtx_insn *first)
 	continue;
 
       body = PATTERN (insn);
-      if (JUMP_TABLE_DATA_P (insn))
+      if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
 	{
 	  /* This only takes room if read-only data goes into the text
 	     section.  */
@@ -1134,7 +1127,7 @@ shorten_branches (rtx_insn *first)
 	      || readonly_data_section == text_section)
 	    insn_lengths[uid] = (XVECLEN (body,
 					  GET_CODE (body) == ADDR_DIFF_VEC)
-				 * GET_MODE_SIZE (GET_MODE (body)));
+				 * GET_MODE_SIZE (table->get_data_mode ()));
 	  /* Alignment is handled by ADDR_VEC_ALIGN.  */
 	}
       else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
@@ -1214,28 +1207,27 @@ shorten_branches (rtx_insn *first)
 
 	  uid = INSN_UID (insn);
 
-	  if (LABEL_P (insn))
+	  if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
 	    {
-	      int log = LABEL_TO_ALIGNMENT (insn);
+	      int log = LABEL_TO_ALIGNMENT (label);
 
 #ifdef CASE_VECTOR_SHORTEN_MODE
 	      /* If the mode of a following jump table was changed, we
 		 may need to update the alignment of this label.  */
-	      rtx_insn *next;
-	      bool next_is_jumptable;
-
-	      next = next_nonnote_insn (insn);
-	      next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
-	      if ((JUMP_TABLES_IN_TEXT_SECTION
-		   || readonly_data_section == text_section)
-		  && next_is_jumptable)
+
+	      if (JUMP_TABLES_IN_TEXT_SECTION
+		  || readonly_data_section == text_section)
 		{
-		  int newlog = ADDR_VEC_ALIGN (next);
-		  if (newlog != log)
+		  rtx_jump_table_data *table = jump_table_for_label (label);
+		  if (table)
 		    {
-		      log = newlog;
-		      LABEL_TO_ALIGNMENT (insn) = log;
-		      something_changed = 1;
+		      int newlog = ADDR_VEC_ALIGN (table);
+		      if (newlog != log)
+			{
+			  log = newlog;
+			  LABEL_TO_ALIGNMENT (insn) = log;
+			  something_changed = 1;
+			}
 		    }
 		}
 #endif
@@ -1266,6 +1258,7 @@ shorten_branches (rtx_insn *first)
 	      && JUMP_TABLE_DATA_P (insn)
 	      && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
 	    {
+	      rtx_jump_table_data *table = as_a <rtx_jump_table_data *> (insn);
 	      rtx body = PATTERN (insn);
 	      int old_length = insn_lengths[uid];
 	      rtx_insn *rel_lab =
@@ -1361,13 +1354,14 @@ shorten_branches (rtx_insn *first)
 						   max_addr - rel_addr, body);
 	      if (!increasing
 		  || (GET_MODE_SIZE (vec_mode)
-		      >= GET_MODE_SIZE (GET_MODE (body))))
+		      >= GET_MODE_SIZE (table->get_data_mode ())))
 		PUT_MODE (body, vec_mode);
 	      if (JUMP_TABLES_IN_TEXT_SECTION
 		  || readonly_data_section == text_section)
 		{
 		  insn_lengths[uid]
-		    = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
+		    = (XVECLEN (body, 1)
+		       * GET_MODE_SIZE (table->get_data_mode ()));
 		  insn_current_address += insn_lengths[uid];
 		  if (insn_lengths[uid] != old_length)
 		    something_changed = 1;
@@ -2183,6 +2177,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
   rtx set;
 #endif
   rtx_insn *next;
+  rtx_jump_table_data *table;
 
   insn_counter++;
 
@@ -2437,11 +2432,11 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 
       app_disable ();
 
-      next = next_nonnote_insn (insn);
       /* If this label is followed by a jump-table, make sure we put
 	 the label in the read-only section.  Also possibly write the
 	 label and jump table together.  */
-      if (next != 0 && JUMP_TABLE_DATA_P (next))
+      table = jump_table_for_label (as_a <rtx_code_label *> (insn));
+      if (table)
 	{
 #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
 	  /* In this case, the case vector is being moved by the
@@ -2456,7 +2451,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 				 (current_function_decl));
 
 #ifdef ADDR_VEC_ALIGN
-	      log_align = ADDR_VEC_ALIGN (next);
+	      log_align = ADDR_VEC_ALIGN (table);
 #else
 	      log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
 #endif
@@ -2466,8 +2461,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	    switch_to_section (current_function_section ());
 
 #ifdef ASM_OUTPUT_CASE_LABEL
-	  ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
-				 next);
+	  ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
 #else
 	  targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
 #endif
diff --git a/gcc/is-a.h b/gcc/is-a.h
index 872aec1..05dd11d 100644
--- a/gcc/is-a.h
+++ b/gcc/is-a.h
@@ -103,6 +103,11 @@ TYPE dyn_cast <TYPE> (pointer)
     Note that we have converted two sets of assertions in the calls to varpool
     into safe and efficient use of a variable.
 
+TYPE safe_dyn_cast <TYPE> (pointer)
+
+    Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
+    and returns null results for them.
+
 
 If you use these functions and get a 'inline function not defined' or a
 'missing symbol' error message for 'is_a_helper<....>::test', it means that
@@ -222,4 +227,13 @@ dyn_cast (U *p)
     return static_cast <T> (0);
 }
 
+/* Similar to dyn_cast, except that the pointer may be null.  */
+
+template <typename T, typename U>
+inline T
+safe_dyn_cast (U *p)
+{
+  return p ? dyn_cast <T> (p) : 0;
+}
+
 #endif  /* GCC_IS_A_H  */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index a5ca103..0d1dc85 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -634,6 +634,7 @@ public:
      This method gets the underlying vec.  */
 
   inline rtvec get_labels () const;
+  inline scalar_int_mode get_data_mode () const;
 };
 
 class GTY(()) rtx_barrier : public rtx_insn
@@ -1477,6 +1478,24 @@ inline rtvec rtx_jump_table_data::get_labels () const
     return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */
 }
 
+/* Return the mode of the data in the table, which is always a scalar
+   integer.  */
+
+inline scalar_int_mode
+rtx_jump_table_data::get_data_mode () const
+{
+  return as_a <scalar_int_mode> (GET_MODE (PATTERN (this)));
+}
+
+/* If LABEL is followed by a jump table, return the table, otherwise
+   return null.  */
+
+inline rtx_jump_table_data *
+jump_table_for_label (const rtx_code_label *label)
+{
+  return safe_dyn_cast <rtx_jump_table_data *> (NEXT_INSN (label));
+}
+
 #define RTX_FRAME_RELATED_P(RTX)					\
   (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN,	\
 		    CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)

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

* [61/67] Use scalar_int_mode in the AArch64 port
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (60 preceding siblings ...)
  2016-12-09 13:36 ` [60/67] Pass scalar_int_modes to do_jump_by_parts_* Richard Sandiford
@ 2016-12-09 13:37 ` Richard Sandiford
  2016-12-09 13:38 ` [62/67] Big machine_mode to scalar_int_mode replacement Richard Sandiford
                   ` (7 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:37 UTC (permalink / raw)
  To: gcc-patches

This patch makes the AArch64 port use scalar_int_mode in various places.
Other ports won't need this kind of change; we only need it for AArch64
because of the polynomial integers that are added by later patches.

The only change in functionality is in the rtx_costs handling
of CONST_INT.  If the caller doesn't supply a mode, we now pass
word_mode rather than VOIDmode to aarch64_internal_mov_immediate.
aarch64_movw_imm will therefore not now truncate large constants
in this situation.

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

	* config/aarch64/aarch64-protos.h (aarch64_and_bitmask_imm): Take
	a scalar_int_mode instead of a machine_mode.
	(aarch64_is_extend_from_extract): Likewise.
	(aarch64_mask_and_shift_for_ubfiz_p): Likewise.
	(aarch64_move_imm): Likewise.
	(aarch64_output_scalar_simd_mov_immediate): Likewise.
	(aarch64_simd_scalar_immediate_valid_for_move): Likewise.
	(aarch64_simd_attr_length_rglist): Delete.
	* config/aarch64/aarch64.c (aarch64_is_extend_from_extract): Take
	a scalar_int_mode instead of a machine_mode.
	(aarch64_add_offset): Likewise.
	(aarch64_internal_mov_immediate): Likewise
	(aarch64_add_constant_internal): Likewise.
	(aarch64_add_constant): Likewise.
	(aarch64_movw_imm): Likewise.
	(aarch64_and_bitmask_imm): Likewise.
	(aarch64_move_imm): Likewise.
	(aarch64_rtx_arith_op_extract_p): Likewise.
	(aarch64_mask_and_shift_for_ubfiz_p): Likewise.
	(aarch64_simd_scalar_immediate_valid_for_move): Likewise.
	Remove assert that the mode isn't a vector.
	(aarch64_output_scalar_simd_mov_immediate): Likewise.
	(aarch64_expand_mov_immediate): Update calls after above changes.
	(aarch64_output_casesi): Use as_a <scalar_int_mode>.
	(aarch64_strip_extend): Check for scalar integer modes.
	(aarch64_rtx_costs): Likewise, using wode_mode as the mode of
	a CONST_INT when the mode parameter is VOIDmode.
	* config/aarch64/predicates.md (aarch64_logical_and_immediate):
	Update call to aarch64_and_bitmask_imm.

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 803d4fc..17f1b93 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -298,7 +298,8 @@ int aarch64_get_condition_code (rtx);
 bool aarch64_bitmask_imm (HOST_WIDE_INT val, machine_mode);
 unsigned HOST_WIDE_INT aarch64_and_split_imm1 (HOST_WIDE_INT val_in);
 unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
-bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode);
+bool aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in,
+			      scalar_int_mode mode);
 int aarch64_branch_cost (bool, bool);
 enum aarch64_symbol_type aarch64_classify_symbolic_expression (rtx);
 bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
@@ -311,22 +312,21 @@ bool aarch64_function_arg_regno_p (unsigned);
 bool aarch64_fusion_enabled_p (enum aarch64_fusion_pairs);
 bool aarch64_gen_movmemqi (rtx *);
 bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
-bool aarch64_is_extend_from_extract (machine_mode, rtx, rtx);
+bool aarch64_is_extend_from_extract (scalar_int_mode, rtx, rtx);
 bool aarch64_is_long_call_p (rtx);
 bool aarch64_is_noplt_call_p (rtx);
 bool aarch64_label_mentioned_p (rtx);
 void aarch64_declare_function_name (FILE *, const char*, tree);
 bool aarch64_legitimate_pic_operand_p (rtx);
-bool aarch64_mask_and_shift_for_ubfiz_p (machine_mode, rtx, rtx);
+bool aarch64_mask_and_shift_for_ubfiz_p (scalar_int_mode, rtx, rtx);
 bool aarch64_modes_tieable_p (machine_mode mode1,
 			      machine_mode mode2);
 bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
-bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
+bool aarch64_move_imm (HOST_WIDE_INT, scalar_int_mode);
 bool aarch64_mov_operand_p (rtx, 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_scalar_simd_mov_immediate (rtx, scalar_int_mode);
 char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
 bool aarch64_pad_arg_upward (machine_mode, const_tree);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
@@ -335,7 +335,7 @@ bool aarch64_regno_ok_for_index_p (int, bool);
 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);
+bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
 bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
 bool aarch64_simd_valid_immediate (rtx, machine_mode, bool,
 				   struct simd_immediate_info *);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ed2e44b..d8019bf 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1118,7 +1118,7 @@ aarch64_is_noplt_call_p (rtx sym)
 
    (extract:MODE (mult (reg) (MULT_IMM)) (EXTRACT_IMM) (const_int 0)).  */
 bool
-aarch64_is_extend_from_extract (machine_mode mode, rtx mult_imm,
+aarch64_is_extend_from_extract (scalar_int_mode mode, rtx mult_imm,
 				rtx extract_imm)
 {
   HOST_WIDE_INT mult_val, extract_val;
@@ -1744,7 +1744,8 @@ aarch64_force_temporary (machine_mode mode, rtx x, rtx value)
 
 
 static rtx
-aarch64_add_offset (machine_mode mode, rtx temp, rtx reg, HOST_WIDE_INT offset)
+aarch64_add_offset (scalar_int_mode mode, rtx temp, rtx reg,
+		    HOST_WIDE_INT offset)
 {
   if (!aarch64_plus_immediate (GEN_INT (offset), mode))
     {
@@ -1762,7 +1763,7 @@ aarch64_add_offset (machine_mode mode, rtx temp, rtx reg, HOST_WIDE_INT offset)
 
 static int
 aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate,
-				machine_mode mode)
+				scalar_int_mode mode)
 {
   int i;
   unsigned HOST_WIDE_INT val, val2, mask;
@@ -1868,9 +1869,11 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
   gcc_assert (mode == SImode || mode == DImode);
 
   /* Check on what type of symbol it is.  */
-  if (GET_CODE (imm) == SYMBOL_REF
-      || GET_CODE (imm) == LABEL_REF
-      || GET_CODE (imm) == CONST)
+  scalar_int_mode int_mode;
+  if ((GET_CODE (imm) == SYMBOL_REF
+       || GET_CODE (imm) == LABEL_REF
+       || GET_CODE (imm) == CONST)
+      && is_a <scalar_int_mode> (mode, &int_mode))
     {
       rtx mem, base, offset;
       enum aarch64_symbol_type sty;
@@ -1884,11 +1887,12 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	{
 	case SYMBOL_FORCE_TO_MEM:
 	  if (offset != const0_rtx
-	      && targetm.cannot_force_const_mem (mode, imm))
+	      && targetm.cannot_force_const_mem (int_mode, imm))
 	    {
 	      gcc_assert (can_create_pseudo_p ());
-	      base = aarch64_force_temporary (mode, dest, base);
-	      base = aarch64_add_offset (mode, NULL, base, INTVAL (offset));
+	      base = aarch64_force_temporary (int_mode, dest, base);
+	      base = aarch64_add_offset (int_mode, NULL, base,
+					 INTVAL (offset));
 	      aarch64_emit_move (dest, base);
 	      return;
 	    }
@@ -1908,8 +1912,8 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	      mem = gen_rtx_MEM (ptr_mode, base);
 	    }
 
-	  if (mode != ptr_mode)
-	    mem = gen_rtx_ZERO_EXTEND (mode, mem);
+	  if (int_mode != ptr_mode)
+	    mem = gen_rtx_ZERO_EXTEND (int_mode, mem);
 
 	  emit_insn (gen_rtx_SET (dest, mem));
 
@@ -1925,8 +1929,9 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	  if (offset != const0_rtx)
 	    {
 	      gcc_assert(can_create_pseudo_p ());
-	      base = aarch64_force_temporary (mode, dest, base);
-	      base = aarch64_add_offset (mode, NULL, base, INTVAL (offset));
+	      base = aarch64_force_temporary (int_mode, dest, base);
+	      base = aarch64_add_offset (int_mode, NULL, base,
+					 INTVAL (offset));
 	      aarch64_emit_move (dest, base);
 	      return;
 	    }
@@ -1960,7 +1965,8 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
       return;
     }
 
-  aarch64_internal_mov_immediate (dest, imm, true, GET_MODE (dest));
+  aarch64_internal_mov_immediate (dest, imm, true,
+				  as_a <scalar_int_mode> (mode));
 }
 
 /* Add DELTA to REGNUM in mode MODE.  SCRATCHREG can be used to hold a
@@ -1976,9 +1982,9 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
    large immediate).  */
 
 static void
-aarch64_add_constant_internal (machine_mode mode, int regnum, int scratchreg,
-			       HOST_WIDE_INT delta, bool frame_related_p,
-			       bool emit_move_imm)
+aarch64_add_constant_internal (scalar_int_mode mode, int regnum,
+			       int scratchreg, HOST_WIDE_INT delta,
+			       bool frame_related_p, bool emit_move_imm)
 {
   HOST_WIDE_INT mdelta = abs_hwi (delta);
   rtx this_rtx = gen_rtx_REG (mode, regnum);
@@ -2025,7 +2031,7 @@ aarch64_add_constant_internal (machine_mode mode, int regnum, int scratchreg,
 }
 
 static inline void
-aarch64_add_constant (machine_mode mode, int regnum, int scratchreg,
+aarch64_add_constant (scalar_int_mode mode, int regnum, int scratchreg,
 		      HOST_WIDE_INT delta)
 {
   aarch64_add_constant_internal (mode, regnum, scratchreg, delta, false, true);
@@ -3854,7 +3860,7 @@ aarch64_uimm12_shift (HOST_WIDE_INT val)
 /* Return true if val is an immediate that can be loaded into a
    register by a MOVZ instruction.  */
 static bool
-aarch64_movw_imm (HOST_WIDE_INT val, machine_mode mode)
+aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode)
 {
   if (GET_MODE_SIZE (mode) > 4)
     {
@@ -3956,7 +3962,7 @@ aarch64_and_split_imm2 (HOST_WIDE_INT val_in)
 /* Return true if VAL_IN is a valid 'and' bitmask immediate.  */
 
 bool
-aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode)
+aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, scalar_int_mode mode)
 {
   if (aarch64_bitmask_imm (val_in, mode))
     return false;
@@ -3972,7 +3978,7 @@ aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode)
 /* Return true if val is an immediate that can be loaded into a
    register in a single instruction.  */
 bool
-aarch64_move_imm (HOST_WIDE_INT val, machine_mode mode)
+aarch64_move_imm (HOST_WIDE_INT val, scalar_int_mode mode)
 {
   if (aarch64_movw_imm (val, mode) || aarch64_movw_imm (~val, mode))
     return 1;
@@ -5800,7 +5806,8 @@ aarch64_output_casesi (rtx *operands)
 
   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
 
-  index = exact_log2 (GET_MODE_SIZE (GET_MODE (diff_vec)));
+  scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (diff_vec));
+  index = exact_log2 (GET_MODE_SIZE (mode));
 
   gcc_assert (index >= 0 && index <= 3);
 
@@ -5919,13 +5926,17 @@ aarch64_strip_shift (rtx x)
 static rtx
 aarch64_strip_extend (rtx x)
 {
+  scalar_int_mode mode;
   rtx op = x;
 
+  if (!is_a <scalar_int_mode> (GET_MODE (op), &mode))
+    return op;
+
   /* Zero and sign extraction of a widened value.  */
   if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
       && XEXP (op, 2) == const0_rtx
       && GET_CODE (XEXP (op, 0)) == MULT
-      && aarch64_is_extend_from_extract (GET_MODE (op), XEXP (XEXP (op, 0), 1),
+      && aarch64_is_extend_from_extract (mode, XEXP (XEXP (op, 0), 1),
 					 XEXP (op, 1)))
     return XEXP (XEXP (op, 0), 0);
 
@@ -6224,7 +6235,7 @@ aarch64_branch_cost (bool speed_p, bool predictable_p)
 /* Return true if the RTX X in mode MODE is a zero or sign extract
    usable in an ADD or SUB (extended register) instruction.  */
 static bool
-aarch64_rtx_arith_op_extract_p (rtx x, machine_mode mode)
+aarch64_rtx_arith_op_extract_p (rtx x, scalar_int_mode mode)
 {
   /* Catch add with a sign extract.
      This is add_<optab><mode>_multp2.  */
@@ -6468,7 +6479,8 @@ aarch64_extend_bitfield_pattern_p (rtx x)
    mode MODE.  See the *andim_ashift<mode>_bfiz pattern.  */
 
 bool
-aarch64_mask_and_shift_for_ubfiz_p (machine_mode mode, rtx mask, rtx shft_amnt)
+aarch64_mask_and_shift_for_ubfiz_p (scalar_int_mode mode, rtx mask,
+				    rtx shft_amnt)
 {
   return CONST_INT_P (mask) && CONST_INT_P (shft_amnt)
 	 && INTVAL (shft_amnt) < GET_MODE_BITSIZE (mode)
@@ -6606,8 +6618,10 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	     proportionally expensive to the number of instructions
 	     required to build that constant.  This is true whether we
 	     are compiling for SPEED or otherwise.  */
+	  if (!is_a <scalar_int_mode> (mode, &int_mode))
+	    int_mode = word_mode;
 	  *cost = COSTS_N_INSNS (aarch64_internal_mov_immediate
-				 (NULL_RTX, x, false, mode));
+				 (NULL_RTX, x, false, int_mode));
 	}
       return true;
 
@@ -6860,7 +6874,8 @@ cost_minus:
 	  }
 
 	/* Look for SUB (extended register).  */
-        if (aarch64_rtx_arith_op_extract_p (op1, mode))
+	if (is_a <scalar_int_mode> (mode, &int_mode)
+	    && aarch64_rtx_arith_op_extract_p (op1, int_mode))
 	  {
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
@@ -6939,7 +6954,8 @@ cost_plus:
 	*cost += rtx_cost (op1, mode, PLUS, 1, speed);
 
 	/* Look for ADD (extended register).  */
-        if (aarch64_rtx_arith_op_extract_p (op0, mode))
+	if (is_a <scalar_int_mode> (mode, &int_mode)
+	    && aarch64_rtx_arith_op_extract_p (op0, int_mode))
 	  {
 	    if (speed)
 	      *cost += extra_cost->alu.extend_arith;
@@ -11262,11 +11278,10 @@ aarch64_simd_gen_const_vector_dup (machine_mode mode, int val)
 /* Check OP is a legal scalar immediate for the MOVI instruction.  */
 
 bool
-aarch64_simd_scalar_immediate_valid_for_move (rtx op, machine_mode mode)
+aarch64_simd_scalar_immediate_valid_for_move (rtx op, scalar_int_mode mode)
 {
   machine_mode vmode;
 
-  gcc_assert (!VECTOR_MODE_P (mode));
   vmode = aarch64_preferred_simd_mode (mode);
   rtx op_v = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (op));
   return aarch64_simd_valid_immediate (op_v, vmode, false, NULL);
@@ -12543,12 +12558,10 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
 }
 
 char*
-aarch64_output_scalar_simd_mov_immediate (rtx immediate,
-					  machine_mode mode)
+aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode)
 {
   machine_mode vmode;
 
-  gcc_assert (!VECTOR_MODE_P (mode));
   vmode = aarch64_simd_container_mode (mode, 64);
   rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate));
   return aarch64_output_simd_mov_immediate (v_op, vmode, 64);
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index daa991b..d599c5d 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -108,7 +108,8 @@
 
 (define_predicate "aarch64_logical_and_immediate"
   (and (match_code "const_int")
-       (match_test "aarch64_and_bitmask_imm (INTVAL (op), mode)")))
+       (match_test "aarch64_and_bitmask_imm (INTVAL (op),
+					     as_a <scalar_int_mode> (mode))")))
 
 (define_predicate "aarch64_shift_imm_si"
   (and (match_code "const_int")

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

* [63/67] Simplifications after type switch
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (62 preceding siblings ...)
  2016-12-09 13:38 ` [62/67] Big machine_mode to scalar_int_mode replacement Richard Sandiford
@ 2016-12-09 13:38 ` Richard Sandiford
  2016-12-09 13:40 ` [66/67] Add a scalar_mode_pod class Richard Sandiford
                   ` (5 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:38 UTC (permalink / raw)
  To: gcc-patches

This patch makes a few simplifications after the previous
mechanical machine_mode->scalar_int_mode change.

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

	* expmed.c (extract_high_half): Use scalar_int_mode and remove
	assertion.
	(expmed_mult_highpart_optab): Likewise.
	(expmed_mult_highpart): Likewise.

diff --git a/gcc/expmed.c b/gcc/expmed.c
index 5da4c0b..2027d76 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -3602,14 +3602,11 @@ expand_mult_highpart_adjust (scalar_int_mode mode, rtx adj_operand, rtx op0,
 static rtx
 extract_high_half (scalar_int_mode mode, rtx op)
 {
-  machine_mode wider_mode;
-
   if (mode == word_mode)
     return gen_highpart (mode, op);
 
-  gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
+  scalar_int_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);
@@ -3623,15 +3620,13 @@ expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1,
 			    rtx target, int unsignedp, int max_cost)
 {
   rtx narrow_op1 = gen_int_mode (INTVAL (op1), mode);
-  machine_mode wider_mode;
   optab moptab;
   rtx tem;
   int size;
   bool speed = optimize_insn_for_speed_p ();
 
-  gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
+  scalar_int_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
@@ -3737,7 +3732,6 @@ static rtx
 expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1,
 		      rtx target, int unsignedp, int max_cost)
 {
-  machine_mode wider_mode = *GET_MODE_WIDER_MODE (mode);
   unsigned HOST_WIDE_INT cnst1;
   int extra_cost;
   bool sign_adjust = false;
@@ -3746,7 +3740,6 @@ expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1,
   rtx tem;
   bool speed = optimize_insn_for_speed_p ();
 
-  gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
   /* We can't support modes wider than HOST_BITS_PER_INT.  */
   gcc_assert (HWI_COMPUTABLE_MODE_P (mode));
 
@@ -3756,6 +3749,7 @@ expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1,
      ??? We might be able to perform double-word arithmetic if
      mode == word_mode, however all the cost calculations in
      synth_mult etc. assume single-word operations.  */
+  scalar_int_mode wider_mode = *GET_MODE_WIDER_MODE (mode);
   if (GET_MODE_BITSIZE (wider_mode) > BITS_PER_WORD)
     return expmed_mult_highpart_optab (mode, op0, op1, target,
 				       unsignedp, max_cost);

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

* [62/67] Big machine_mode to scalar_int_mode replacement
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (61 preceding siblings ...)
  2016-12-09 13:37 ` [61/67] Use scalar_int_mode in the AArch64 port Richard Sandiford
@ 2016-12-09 13:38 ` Richard Sandiford
  2016-12-09 13:38 ` [63/67] Simplifications after type switch Richard Sandiford
                   ` (6 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:38 UTC (permalink / raw)
  To: gcc-patches

This patch changes the types of various things from machine_mode
to scalar_int_mode, in cases where (after previous patches)
simply changing the type is enough on its own.  The patch does
nothing other than that.

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

	* builtins.h (builtin_strncpy_read_str): Take a scalar_int_mode
	instead of a machine_mode.
	(builtin_memset_read_str): Likewise.
	* builtins.c (c_readstr): Likewise.
	(builtin_memcpy_read_str): Likewise.
	(builtin_strncpy_read_str): Likewise.
	(builtin_memset_read_str): Likewise.
	(builtin_memset_gen_str): Likewise.
	(expand_builtin_signbit): Use scalar_int_mode for local variables.
	* cfgexpand.c (convert_debug_memory_address): Take a scalar_int_mode
	instead of a machine_mode.
	* combine.c (make_extraction): Use scalar_int_mode for local
	variables.
	(try_widen_shift_mode): Take and return scalar_int_modes instead
	of machine_modes.
	* config/aarch64/aarch64.c (aarch64_libgcc_cmp_return_mode): Return
	a scalar_int_mode instead of a machine_mode.
	* config/avr/avr.c (avr_addr_space_address_mode): Likewise.
	(avr_addr_space_pointer_mode): Likewise.
	* config/cr16/cr16.c (cr16_unwind_word_mode): Likewise.
	* config/msp430/msp430.c (msp430_addr_space_pointer_mode): Likewise.
	(msp430_unwind_word_mode): Likewise.
	* config/spu/spu.c (spu_unwind_word_mode): Likewise.
	(spu_addr_space_pointer_mode): Likewise.
	(spu_addr_space_address_mode): Likewise.
	(spu_libgcc_cmp_return_mode): Likewise.
	(spu_libgcc_shift_count_mode): Likewise.
	* config/rl78/rl78.c (rl78_addr_space_address_mode): Likewise.
	(rl78_addr_space_pointer_mode): Likewise.
	(fl78_unwind_word_mode): Likewise.
	(rl78_valid_pointer_mode): Take a scalar_int_mode instead of a
	machine_mode.
	* config/alpha/alpha.c (vms_valid_pointer_mode): Likewise.
	* config/ia64/ia64.c (ia64_vms_valid_pointer_mode): Likewise.
	* config/mips/mips.c (mips_mode_rep_extended): Likewise.
	(mips_valid_pointer_mode): Likewise.
	* config/tilegx/tilegx.c (tilegx_mode_rep_extended): Likewise.
	* config/ft32/ft32.c (ft32_valid_pointer_mode): Likewise.
	(ft32_addr_space_pointer_mode): Return a scalar_int_mode instead
	of a machine_mode.
	(ft32_addr_space_address_mode): Likewise.
	* config/m32c/m32c.c (m32c_valid_pointer_mode): Take a
	scalar_int_mode instead of a machine_mode.
	(m32c_addr_space_pointer_mode): Return a scalar_int_mode instead
	of a machine_mode.
	(m32c_addr_space_address_mode): Likewise.
	* config/rs6000/rs6000.h (rs6000_pmode): Change type from
	machine_mode to scalar_int_mode.
	* config/rs6000/rs6000.c (rs6000_pmode): Likewise.
	(rs6000_abi_word_mode): Return a scalar_int_mode rather than a
	machine_mode.
	(rs6000_eh_return_filter_mode): Likewise.
	* config/s390/s390.c (s390_libgcc_cmp_return_mode): Likewise.
	(s390_libgcc_shift_count_mode): Likewise.
	(s390_unwind_word_mode): Likewise.
	(s390_valid_pointer_mode): Take a scalar_int_mode rather than a
	machine_mode.
	* target.def (mode_rep_extended): Likewise.
	(valid_pointer_mode): Likewise.
	(addr_space.valid_pointer_mode): Likewise.
	(eh_return_filter_mode): Return a scalar_int_mode rather than
	a machine_mode.
	(libgcc_cmp_return_mode): Likewise.
	(libgcc_shift_count_mode): Likewise.
	(unwind_word_mode): Likewise.
	(addr_space.pointer_mode): Likewise.
	(addr_space.address_mode): Likewise.
	* doc/tm.texi: Regenerate.
	* dojump.c (prefer_and_bit_test): Take a scalar_int_mode rather than
	a machine_mode.
	(do_jump): Use scalar_int_mode for local variables.
	* dwarf2cfi.c (init_return_column_size): Take a scalar_int_mode
	rather than a machine_mode.
	* dwarf2out.c (convert_descriptor_to_mode): Likewise.
	* emit-rtl.c (adjust_address_1): Use scalar_int_mode for local
	variables.
	* except.c (sjlj_emit_dispatch_table): Likewise.
	(expand_builtin_eh_copy_values): Likewise.
	* explow.c (convert_memory_address_addr_space_1): Likewise.
	Take a scalar_int_mode rather than a machine_mode.
	(convert_memory_address_addr_space): Take a scalar_int_mode rather
	than a machine_mode.
	(memory_address_addr_space): Use scalar_int_mode for local variables.
	* expmed.h (expand_mult_highpart_adjust): Take a scalar_int_mode
	rather than a machine_mode.
	* expmed.c (mask_rtx): Likewise.
	(init_expmed_one_conv): Likewise.
	(expand_mult_highpart_adjust): Likewise.
	(extract_high_half): Likewise.
	(expmed_mult_highpart_optab): Likewise.
	(expmed_mult_highpart): Likewise.
	(expand_smod_pow2): Likewise.
	(expand_sdiv_pow2): Likewise.
	(adjust_bit_field_mem_for_reg): Use scalar_int_mode for local
	variables.
	(extract_low_bits): Likewise.
	* expr.h (by_pieces_constfn): Take a scalar_int_mode rather than
	a machine_mode.
	* expr.c (pieces_addr:adjust):  Likewise.
	(can_store_by_pieces): Likewise.
	(store_by_pieces): Likewise.
	(clear_by_pieces_1): Likewise.
	(expand_expr_addr_expr_1): Likewise.
	(expand_expr_addr_expr): Use scalar_int_mode for local variables.
	(expand_expr_real_1): Likewise.
	(try_casesi): Likewise.
	* final.c (shorten_branches): Likewise.
	* fold-const.c (fold_convert_const_int_from_fixed): Change the
	type of "mode" to machine_mode.
	* internal-fn.c (expand_arith_overflow_result_store): Take a
	scalar_int_mode rather than a machine_mode.
	(expand_mul_overflow): Use scalar_int_mode for local variables.
	* loop-doloop.c (doloop_modify): Likewise.
	(doloop_optimize): Likewise.
	* lower-subreg.h (target_lower_subreg::x_twice_word_mode): Change
	type to scalar_int_mode.
	* optabs.c (expand_subword_shift): Take a scalar_int_mode rather
	than a machine_mode.
	(expand_doubleword_shift_condmove): Likewise.
	(expand_doubleword_shift): Likewise.
	(expand_doubleword_clz): Likewise.
	(expand_doubleword_popcount): Likewise.
	(expand_doubleword_parity): Likewise.
	(expand_absneg_bit): Use scalar_int_mode for local variables.
	(prepare_float_lib_cmp): Likewise.
	* rtl.h (convert_memory_address_addr_space_1): Take a scalar_int_mode
	rather than a machine_mode.
	(convert_memory_address_addr_space): Likewise.
	(get_mode_bounds): Likewise.
	(get_address_mode): Return a scalar_int_mode rather than a
	machine_mode.
	* rtlanal.c (get_address_mode): Likewise.
	* stor-layout.c (get_mode_bounds): Take a scalar_int_mode rather
	than a machine_mode.
	* targhooks.c (default_mode_rep_extended): Likewise.
	(default_valid_pointer_mode): Likewise.
	(default_addr_space_valid_pointer_mode): Likewise.
	(default_eh_return_filter_mode): Return a scalar_int_mode rather
	than a machine_mode.
	(default_libgcc_cmp_return_mode): Likewise.
	(default_libgcc_shift_count_mode): Likewise.
	(default_unwind_word_mode): Likewise.
	(default_addr_space_pointer_mode): Likewise.
	(default_addr_space_address_mode): Likewise.
	* targhooks.h (default_eh_return_filter_mode): Likewise.
	(default_libgcc_cmp_return_mode): Likewise.
	(default_libgcc_shift_count_mode): Likewise.
	(default_unwind_word_mode): Likewise.
	(default_addr_space_pointer_mode): Likewise.
	(default_addr_space_address_mode): Likewise.
	(default_mode_rep_extended): Take a scalar_int_mode rather than
	a machine_mode.
	(default_valid_pointer_mode): Likewise.
	(default_addr_space_valid_pointer_mode): Likewise.
	* tree-ssa-address.c (addr_for_mem_ref): Use scalar_int_mode for
	local variables.
	* tree-ssa-loop-ivopts.c (compute_max_addr_offset): Likewise.
	(get_address_cost): Likewise.
	(get_shiftadd_cost): Take a scalar_int_mode rather than a
	machine_mode.
	* tree-switch-conversion.c (array_value_type): Use scalar_int_mode
	for local variables.
	* tree-vrp.c (simplify_float_conversion_using_ranges): Likewise.
	* var-tracking.c (use_narrower_mode): Take a scalar_int_mode rather
	than a machine_mode.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index cf22e96..860b1a8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -91,7 +91,7 @@ builtin_info_type builtin_info[(int)END_BUILTINS];
 /* Non-zero if __builtin_constant_p should be folded right away.  */
 bool force_folding_builtin_constant_p;
 
-static rtx c_readstr (const char *, machine_mode);
+static rtx c_readstr (const char *, scalar_int_mode);
 static int target_char_cast (tree, char *);
 static rtx get_memory_rtx (tree, tree);
 static int apply_args_size (void);
@@ -117,7 +117,7 @@ static rtx expand_builtin_va_end (tree);
 static rtx expand_builtin_va_copy (tree);
 static rtx expand_builtin_strcmp (tree, rtx);
 static rtx expand_builtin_strncmp (tree, rtx, machine_mode);
-static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode);
+static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
 static rtx expand_builtin_memcpy (tree, rtx);
 static rtx expand_builtin_memcpy_with_bounds (tree, rtx);
 static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree);
@@ -131,7 +131,7 @@ static rtx expand_builtin_strcpy_args (tree, tree, rtx);
 static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
 static rtx expand_builtin_strncat (tree, rtx);
 static rtx expand_builtin_strncpy (tree, rtx);
-static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, machine_mode);
+static rtx builtin_memset_gen_str (void *, HOST_WIDE_INT, scalar_int_mode);
 static rtx expand_builtin_memset (tree, rtx, machine_mode);
 static rtx expand_builtin_memset_with_bounds (tree, rtx, machine_mode);
 static rtx expand_builtin_memset_args (tree, tree, tree, rtx, machine_mode, tree);
@@ -662,7 +662,7 @@ c_strlen (tree src, int only_value)
    GET_MODE_BITSIZE (MODE) bits from string constant STR.  */
 
 static rtx
-c_readstr (const char *str, machine_mode mode)
+c_readstr (const char *str, scalar_int_mode mode)
 {
   HOST_WIDE_INT ch;
   unsigned int i, j;
@@ -2857,7 +2857,7 @@ expand_builtin_strlen (tree exp, rtx target,
 
 static rtx
 builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
-			 machine_mode mode)
+			 scalar_int_mode mode)
 {
   const char *str = (const char *) data;
 
@@ -3693,7 +3693,7 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode)
 
 rtx
 builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
-			  machine_mode mode)
+			  scalar_int_mode mode)
 {
   const char *str = (const char *) data;
 
@@ -3908,7 +3908,7 @@ expand_builtin_strncpy (tree exp, rtx target)
 
 rtx
 builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
-			 machine_mode mode)
+			 scalar_int_mode mode)
 {
   const char *c = (const char *) data;
   char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
@@ -3925,7 +3925,7 @@ builtin_memset_read_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
 
 static rtx
 builtin_memset_gen_str (void *data, HOST_WIDE_INT offset ATTRIBUTE_UNUSED,
-			machine_mode mode)
+			scalar_int_mode mode)
 {
   rtx target, coeff;
   size_t size;
@@ -5211,7 +5211,7 @@ expand_builtin_signbit (tree exp, rtx target)
 {
   const struct real_format *fmt;
   scalar_float_mode fmode;
-  machine_mode imode, rmode;
+  scalar_int_mode rmode, imode;
   tree arg;
   int word, bitpos;
   enum insn_code icode;
diff --git a/gcc/builtins.h b/gcc/builtins.h
index 5e83646..5ce3f4f 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -63,8 +63,8 @@ extern void expand_builtin_setjmp_receiver (rtx);
 extern void expand_builtin_update_setjmp_buf (rtx);
 extern tree mathfn_built_in (tree, enum built_in_function fn);
 extern tree mathfn_built_in (tree, combined_fn);
-extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, machine_mode);
-extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, machine_mode);
+extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
+extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, scalar_int_mode);
 extern rtx expand_builtin_saveregs (void);
 extern tree std_build_builtin_va_list (void);
 extern tree std_fn_abi_va_list (tree);
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c4863dd..3d9f3ac 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3951,7 +3951,7 @@ round_udiv_adjust (machine_mode mode, rtx mod, rtx op1)
    any rtl.  */
 
 static rtx
-convert_debug_memory_address (machine_mode mode, rtx x,
+convert_debug_memory_address (scalar_int_mode mode, rtx x,
 			      addr_space_t as)
 {
 #ifndef POINTERS_EXTEND_UNSIGNED
diff --git a/gcc/combine.c b/gcc/combine.c
index dd7f1fa..f1a89d8 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7405,9 +7405,9 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
      ignore the POS lowest bits, etc.  */
   machine_mode is_mode = GET_MODE (inner);
   machine_mode inner_mode;
-  machine_mode wanted_inner_mode;
-  machine_mode wanted_inner_reg_mode = word_mode;
-  machine_mode pos_mode = word_mode;
+  scalar_int_mode wanted_inner_mode;
+  scalar_int_mode wanted_inner_reg_mode = word_mode;
+  scalar_int_mode pos_mode = word_mode;
   machine_mode extraction_mode = word_mode;
   rtx new_rtx = 0;
   rtx orig_pos_rtx = pos_rtx;
@@ -10294,9 +10294,9 @@ merge_outer_ops (enum rtx_code *pop0, HOST_WIDE_INT *pconst0, enum rtx_code op1,
    result of the shift is subject to operation OUTER_CODE with operand
    OUTER_CONST.  */
 
-static machine_mode
+static scalar_int_mode
 try_widen_shift_mode (enum rtx_code code, rtx op, int count,
-		      machine_mode orig_mode, machine_mode mode,
+		      scalar_int_mode orig_mode, scalar_int_mode mode,
 		      enum rtx_code outer_code, HOST_WIDE_INT outer_const)
 {
   gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode));
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index d8019bf..9981f55 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2576,7 +2576,7 @@ aarch64_pad_reg_upward (machine_mode mode, const_tree type,
   return !BYTES_BIG_ENDIAN;
 }
 
-static machine_mode
+static scalar_int_mode
 aarch64_libgcc_cmp_return_mode (void)
 {
   return SImode;
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 59774bf..620a442 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -206,7 +206,7 @@ static void alpha_override_options_after_change (void);
 
 #if TARGET_ABI_OPEN_VMS
 static void alpha_write_linkage (FILE *, const char *);
-static bool vms_valid_pointer_mode (machine_mode);
+static bool vms_valid_pointer_mode (scalar_int_mode);
 #else
 #define vms_patch_builtins()  gcc_unreachable()
 #endif
@@ -816,7 +816,7 @@ alpha_in_small_data_p (const_tree exp)
 
 #if TARGET_ABI_OPEN_VMS
 static bool
-vms_valid_pointer_mode (machine_mode mode)
+vms_valid_pointer_mode (scalar_int_mode mode)
 {
   return (mode == SImode || mode == DImode);
 }
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index e3a611f..105ceb1 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -12542,7 +12542,7 @@ avr_case_values_threshold (void)
 
 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'.  */
 
-static machine_mode
+static scalar_int_mode
 avr_addr_space_address_mode (addr_space_t as)
 {
   return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
@@ -12551,7 +12551,7 @@ avr_addr_space_address_mode (addr_space_t as)
 
 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'.  */
 
-static machine_mode
+static scalar_int_mode
 avr_addr_space_pointer_mode (addr_space_t as)
 {
   return avr_addr_space_address_mode (as);
diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c
index cc24fa5..3686409 100644
--- a/gcc/config/cr16/cr16.c
+++ b/gcc/config/cr16/cr16.c
@@ -2090,7 +2090,7 @@ notice_update_cc (rtx exp)
   return;
 }
 
-static machine_mode
+static scalar_int_mode
 cr16_unwind_word_mode (void)
 {
   return SImode;
diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c
index 5679dad..fe4e6b5 100644
--- a/gcc/config/ft32/ft32.c
+++ b/gcc/config/ft32/ft32.c
@@ -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 (machine_mode mode)
+ft32_valid_pointer_mode (scalar_int_mode mode)
 {
   if (mode == SImode)
     return 1;
@@ -799,7 +799,7 @@ ft32_valid_pointer_mode (machine_mode mode)
 
 #undef TARGET_ADDR_SPACE_POINTER_MODE
 #define TARGET_ADDR_SPACE_POINTER_MODE ft32_addr_space_pointer_mode
-static machine_mode
+static scalar_int_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 machine_mode
+static scalar_int_mode
 ft32_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 {
   return Pmode;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index d43edc8..91bf0a0 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -298,7 +298,7 @@ static void ia64_vms_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
 static void ia64_soft_fp_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
-static bool ia64_vms_valid_pointer_mode (machine_mode mode)
+static bool ia64_vms_valid_pointer_mode (scalar_int_mode mode)
      ATTRIBUTE_UNUSED;
 static tree ia64_vms_common_object_attribute (tree *, tree, tree, int, bool *)
      ATTRIBUTE_UNUSED;
@@ -10727,7 +10727,7 @@ ia64_soft_fp_init_libfuncs (void)
 }
 
 static bool
-ia64_vms_valid_pointer_mode (machine_mode mode)
+ia64_vms_valid_pointer_mode (scalar_int_mode mode)
 {
   return (mode == SImode || mode == DImode);
 }
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 460ae19..3881cd3 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -1435,7 +1435,7 @@ m32c_function_arg_regno_p (int r)
 #undef TARGET_VALID_POINTER_MODE
 #define TARGET_VALID_POINTER_MODE m32c_valid_pointer_mode
 static bool
-m32c_valid_pointer_mode (machine_mode mode)
+m32c_valid_pointer_mode (scalar_int_mode mode)
 {
   if (mode == HImode
       || mode == PSImode
@@ -1928,7 +1928,7 @@ m32c_legitimize_reload_address (rtx * x,
 /* Return the appropriate mode for a named address pointer.  */
 #undef TARGET_ADDR_SPACE_POINTER_MODE
 #define TARGET_ADDR_SPACE_POINTER_MODE m32c_addr_space_pointer_mode
-static machine_mode
+static scalar_int_mode
 m32c_addr_space_pointer_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -1945,7 +1945,7 @@ m32c_addr_space_pointer_mode (addr_space_t addrspace)
 /* Return the appropriate mode for a named address address.  */
 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
 #define TARGET_ADDR_SPACE_ADDRESS_MODE m32c_addr_space_address_mode
-static machine_mode
+static scalar_int_mode
 m32c_addr_space_address_mode (addr_space_t addrspace)
 {
   switch (addrspace)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 6c08aed..ae93ddb 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -13254,7 +13254,7 @@ mips_secondary_reload_class (enum reg_class rclass,
 /* Implement TARGET_MODE_REP_EXTENDED.  */
 
 static int
-mips_mode_rep_extended (machine_mode mode, machine_mode mode_rep)
+mips_mode_rep_extended (scalar_int_mode mode, scalar_int_mode mode_rep)
 {
   /* On 64-bit targets, SImode register values are sign-extended to DImode.  */
   if (TARGET_64BIT && mode == SImode && mode_rep == DImode)
@@ -13266,7 +13266,7 @@ mips_mode_rep_extended (machine_mode mode, machine_mode mode_rep)
 /* Implement TARGET_VALID_POINTER_MODE.  */
 
 static bool
-mips_valid_pointer_mode (machine_mode mode)
+mips_valid_pointer_mode (scalar_int_mode mode)
 {
   return mode == SImode || (TARGET_64BIT && mode == DImode);
 }
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 998b105..3711e45 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1015,7 +1015,7 @@ msp430_initial_elimination_offset (int from, int to)
 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
 
-static machine_mode
+static scalar_int_mode
 msp430_addr_space_pointer_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -1035,7 +1035,7 @@ msp430_addr_space_pointer_mode (addr_space_t addrspace)
 #undef  TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
 
-static machine_mode
+static scalar_int_mode
 msp430_unwind_word_mode (void)
 {
   /* This needs to match msp430_init_dwarf_reg_sizes_extra (below).  */
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index d5ea068..423cd5d 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -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 machine_mode
+static scalar_int_mode
 rl78_addr_space_address_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -1037,7 +1037,7 @@ rl78_far_p (rtx x)
 #undef  TARGET_ADDR_SPACE_POINTER_MODE
 #define TARGET_ADDR_SPACE_POINTER_MODE rl78_addr_space_pointer_mode
 
-static machine_mode
+static scalar_int_mode
 rl78_addr_space_pointer_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -1058,7 +1058,7 @@ rl78_addr_space_pointer_mode (addr_space_t addrspace)
 #define TARGET_VALID_POINTER_MODE rl78_valid_pointer_mode
 
 static bool
-rl78_valid_pointer_mode (machine_mode m)
+rl78_valid_pointer_mode (scalar_int_mode m)
 {
   return (m == HImode || m == SImode);
 }
@@ -4637,7 +4637,7 @@ rl78_asm_out_integer (rtx x, unsigned int size, int aligned_p)
 #undef  TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rl78_unwind_word_mode
 
-static machine_mode
+static scalar_int_mode
 rl78_unwind_word_mode (void)
 {
   return HImode;
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 06aae77..ac48e44 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -181,7 +181,7 @@ 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.  */
-machine_mode rs6000_pmode;
+scalar_int_mode rs6000_pmode;
 
 /* Width in bits of a pointer.  */
 unsigned rs6000_pointer_size;
@@ -11273,7 +11273,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
 /* The mode the ABI uses for a word.  This is not the same as word_mode
    for -m32 -mpowerpc64.  This is used to implement various target hooks.  */
 
-static machine_mode
+static scalar_int_mode
 rs6000_abi_word_mode (void)
 {
   return TARGET_32BIT ? SImode : DImode;
@@ -37643,7 +37643,7 @@ rs6000_dbx_register_number (unsigned int regno, unsigned int format)
 }
 
 /* target hook eh_return_filter_mode */
-static machine_mode
+static scalar_int_mode
 rs6000_eh_return_filter_mode (void)
 {
   return TARGET_32BIT ? SImode : word_mode;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 0c68f28..a471d75 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2211,7 +2211,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.  */
-extern machine_mode rs6000_pmode;
+extern scalar_int_mode rs6000_pmode;
 #define Pmode rs6000_pmode
 
 /* Supply definition of STACK_SIZE_MODE for allocate_dynamic_stack_space.  */
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 510c24c..3862c15 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1168,19 +1168,19 @@ s390_label_align (rtx_insn *label)
   return align_labels_log;
 }
 
-static machine_mode
+static scalar_int_mode
 s390_libgcc_cmp_return_mode (void)
 {
   return TARGET_64BIT ? DImode : SImode;
 }
 
-static machine_mode
+static scalar_int_mode
 s390_libgcc_shift_count_mode (void)
 {
   return TARGET_64BIT ? DImode : SImode;
 }
 
-static machine_mode
+static scalar_int_mode
 s390_unwind_word_mode (void)
 {
   return TARGET_64BIT ? DImode : SImode;
@@ -12855,7 +12855,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
 }
 
 static bool
-s390_valid_pointer_mode (machine_mode mode)
+s390_valid_pointer_mode (scalar_int_mode mode)
 {
   return (mode == SImode || (TARGET_64BIT && mode == DImode));
 }
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index ea449e0..565533e 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -5322,7 +5322,7 @@ spu_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
   return true;
 }
 
-static machine_mode
+static scalar_int_mode
 spu_unwind_word_mode (void)
 {
   return SImode;
@@ -6698,7 +6698,7 @@ spu_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_packed
 }
 
 /* Return the appropriate mode for a named address pointer.  */
-static machine_mode
+static scalar_int_mode
 spu_addr_space_pointer_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -6713,7 +6713,7 @@ spu_addr_space_pointer_mode (addr_space_t addrspace)
 }
 
 /* Return the appropriate mode for a named address address.  */
-static machine_mode
+static scalar_int_mode
 spu_addr_space_address_mode (addr_space_t addrspace)
 {
   switch (addrspace)
@@ -6859,7 +6859,7 @@ spu_init_expanders (void)
     }
 }
 
-static machine_mode
+static scalar_int_mode
 spu_libgcc_cmp_return_mode (void)
 {
 
@@ -6868,7 +6868,7 @@ spu_libgcc_cmp_return_mode (void)
   return SImode;
 }
 
-static machine_mode
+static scalar_int_mode
 spu_libgcc_shift_count_mode (void)
 {
 /* For SPU word mode is TI mode so it is better to use SImode
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 5c97c62..9705e23 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -187,7 +187,7 @@ tilegx_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
 
 /* Implement TARGET_MODE_REP_EXTENDED.  */
 static int
-tilegx_mode_rep_extended (machine_mode mode, machine_mode mode_rep)
+tilegx_mode_rep_extended (scalar_int_mode mode, scalar_int_mode mode_rep)
 {
   /* SImode register values are sign-extended to DImode.  */
   if (mode == SImode && mode_rep == DImode)
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 05f0719..cc747ea 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1337,21 +1337,21 @@ You would most commonly define this macro if the @code{allocate_stack}
 pattern needs to support both a 32- and a 64-bit mode.
 @end defmac
 
-@deftypefn {Target Hook} machine_mode TARGET_LIBGCC_CMP_RETURN_MODE (void)
+@deftypefn {Target Hook} scalar_int_mode TARGET_LIBGCC_CMP_RETURN_MODE (void)
 This target hook should return the mode to be used for the return value
 of compare instructions expanded to libgcc calls.  If not defined
 @code{word_mode} is returned which is the right choice for a majority of
 targets.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_LIBGCC_SHIFT_COUNT_MODE (void)
+@deftypefn {Target Hook} scalar_int_mode TARGET_LIBGCC_SHIFT_COUNT_MODE (void)
 This target hook should return the mode to be used for the shift count operand
 of shift instructions expanded to libgcc calls.  If not defined
 @code{word_mode} is returned which is the right choice for a majority of
 targets.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_UNWIND_WORD_MODE (void)
+@deftypefn {Target Hook} scalar_int_mode TARGET_UNWIND_WORD_MODE (void)
 Return machine mode to be used for @code{_Unwind_Word} type.
 The default is to use @code{word_mode}.
 @end deftypefn
@@ -4194,7 +4194,7 @@ arguments to @code{va_arg}; the latter two are as in
 @code{gimplify.c:gimplify_expr}.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_VALID_POINTER_MODE (machine_mode @var{mode})
+@deftypefn {Target Hook} bool TARGET_VALID_POINTER_MODE (scalar_int_mode @var{mode})
 Define this to return nonzero if the port can handle pointers
 with machine mode @var{mode}.  The default version of this
 hook returns true for both @code{ptr_mode} and @code{Pmode}.
@@ -10495,19 +10495,19 @@ named address space #1:
 c_register_addr_space ("__ea", ADDR_SPACE_EA);
 @end smallexample
 
-@deftypefn {Target Hook} machine_mode TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
+@deftypefn {Target Hook} scalar_int_mode TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
 Define this to return the machine mode to use for pointers to
 @var{address_space} if the target supports named address spaces.
 The default version of this hook returns @code{ptr_mode}.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_ADDR_SPACE_ADDRESS_MODE (addr_space_t @var{address_space})
+@deftypefn {Target Hook} scalar_int_mode TARGET_ADDR_SPACE_ADDRESS_MODE (addr_space_t @var{address_space})
 Define this to return the machine mode to use for addresses in
 @var{address_space} if the target supports named address spaces.
 The default version of this hook returns @code{Pmode}.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_VALID_POINTER_MODE (machine_mode @var{mode}, addr_space_t @var{as})
+@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_VALID_POINTER_MODE (scalar_int_mode @var{mode}, addr_space_t @var{as})
 Define this to return nonzero if the port can handle pointers
 with machine mode @var{mode} to address space @var{as}.  This target
 hook is the same as the @code{TARGET_VALID_POINTER_MODE} target hook,
@@ -10770,7 +10770,7 @@ If this is the case, making @code{TRULY_NOOP_TRUNCATION} return 0 in
 such cases may improve things.
 @end defmac
 
-@deftypefn {Target Hook} int TARGET_MODE_REP_EXTENDED (machine_mode @var{mode}, machine_mode @var{rep_mode})
+@deftypefn {Target Hook} int TARGET_MODE_REP_EXTENDED (scalar_int_mode @var{mode}, scalar_int_mode @var{rep_mode})
 The representation of an integral mode can be such that the values
 are always extended to a wider integral mode.  Return
 @code{SIGN_EXTEND} if values of @var{mode} are represented in
diff --git a/gcc/dojump.c b/gcc/dojump.c
index c48d2ed..19539e9 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "langhooks.h"
 
-static bool prefer_and_bit_test (machine_mode, int);
+static bool prefer_and_bit_test (scalar_int_mode, int);
 static void do_jump_by_parts_greater (scalar_int_mode, tree, tree, int,
 				      rtx_code_label *, rtx_code_label *, int);
 static void do_jump_by_parts_equality (scalar_int_mode, tree, tree,
@@ -167,7 +167,7 @@ static GTY(()) rtx shift_test;
    is preferred.  */
 
 static bool
-prefer_and_bit_test (machine_mode mode, int bitnum)
+prefer_and_bit_test (scalar_int_mode mode, int bitnum)
 {
   bool speed_p;
   wide_int mask = wi::set_bit_in_zero (bitnum, GET_MODE_PRECISION (mode));
@@ -432,7 +432,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
   rtx temp;
   int i;
   tree type;
-  machine_mode mode;
+  scalar_int_mode mode;
   rtx_code_label *drop_through_label = NULL;
 
   switch (code)
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index d7b0e5c..c9145cc 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -234,7 +234,7 @@ expand_builtin_dwarf_sp_column (void)
    which has mode MODE.  Initialize column C as a return address column.  */
 
 static void
-init_return_column_size (machine_mode mode, rtx mem, unsigned int c)
+init_return_column_size (scalar_int_mode mode, rtx mem, unsigned int c)
 {
   HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
   HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index accca42..ae75e57 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -13712,7 +13712,7 @@ base_type_for_mode (machine_mode mode, bool unsignedp)
    possible.  */
 
 static dw_loc_descr_ref
-convert_descriptor_to_mode (machine_mode mode, dw_loc_descr_ref op)
+convert_descriptor_to_mode (scalar_int_mode mode, dw_loc_descr_ref op)
 {
   machine_mode outer_mode = mode;
   dw_die_ref type_die;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 9fbd7a2..7267d06 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -2196,12 +2196,12 @@ adjust_address_1 (rtx memref, machine_mode mode, HOST_WIDE_INT offset,
 {
   rtx addr = XEXP (memref, 0);
   rtx new_rtx;
-  machine_mode address_mode;
+  scalar_int_mode address_mode;
   int pbits;
   struct mem_attrs attrs = *get_mem_attrs (memref), *defattrs;
   unsigned HOST_WIDE_INT max_align;
 #ifdef POINTERS_EXTEND_UNSIGNED
-  machine_mode pointer_mode
+  scalar_int_mode pointer_mode
     = targetm.addr_space.pointer_mode (attrs.addrspace);
 #endif
 
diff --git a/gcc/except.c b/gcc/except.c
index 2379fb3..1be39f0 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -1251,8 +1251,8 @@ sjlj_emit_function_exit (void)
 static void
 sjlj_emit_dispatch_table (rtx_code_label *dispatch_label, int num_dispatch)
 {
-  machine_mode unwind_word_mode = targetm.unwind_word_mode ();
-  machine_mode filter_mode = targetm.eh_return_filter_mode ();
+  scalar_int_mode unwind_word_mode = targetm.unwind_word_mode ();
+  scalar_int_mode filter_mode = targetm.eh_return_filter_mode ();
   eh_landing_pad lp;
   rtx mem, fc, exc_ptr_reg, filter_reg;
   rtx_insn *seq;
@@ -2078,7 +2078,7 @@ expand_builtin_eh_copy_values (tree exp)
     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 0));
   eh_region src
     = expand_builtin_eh_common (CALL_EXPR_ARG (exp, 1));
-  machine_mode fmode = targetm.eh_return_filter_mode ();
+  scalar_int_mode fmode = targetm.eh_return_filter_mode ();
 
   if (dst->exc_ptr_reg == NULL)
     dst->exc_ptr_reg = gen_reg_rtx (ptr_mode);
diff --git a/gcc/explow.c b/gcc/explow.c
index 6348035..e615e5b 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -274,7 +274,7 @@ break_out_memory_refs (rtx x)
    it should return NULL if it can't be simplified without emitting insns.  */
 
 rtx
-convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
+convert_memory_address_addr_space_1 (scalar_int_mode to_mode ATTRIBUTE_UNUSED,
 				     rtx x, addr_space_t as ATTRIBUTE_UNUSED,
 				     bool in_const ATTRIBUTE_UNUSED,
 				     bool no_emit ATTRIBUTE_UNUSED)
@@ -283,7 +283,7 @@ convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
   gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
   return x;
 #else /* defined(POINTERS_EXTEND_UNSIGNED) */
-  machine_mode pointer_mode, address_mode, from_mode;
+  scalar_int_mode pointer_mode, address_mode, from_mode;
   rtx temp;
   enum rtx_code code;
 
@@ -379,7 +379,8 @@ convert_memory_address_addr_space_1 (machine_mode to_mode ATTRIBUTE_UNUSED,
    arithmetic insns can be used.  */
 
 rtx
-convert_memory_address_addr_space (machine_mode to_mode, rtx x, addr_space_t as)
+convert_memory_address_addr_space (scalar_int_mode to_mode, rtx x,
+				   addr_space_t as)
 {
   return convert_memory_address_addr_space_1 (to_mode, x, as, false, false);
 }
@@ -393,7 +394,7 @@ rtx
 memory_address_addr_space (machine_mode mode, rtx x, addr_space_t as)
 {
   rtx oldx = x;
-  machine_mode address_mode = targetm.addr_space.address_mode (as);
+  scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
 
   x = convert_memory_address_addr_space (address_mode, x, as);
 
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 8ce9d96..5da4c0b 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -72,8 +72,8 @@ static rtx extract_split_bit_field (rtx, opt_scalar_int_mode,
 				    unsigned HOST_WIDE_INT,
 				    unsigned HOST_WIDE_INT, int, bool);
 static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *);
-static rtx expand_smod_pow2 (machine_mode, rtx, HOST_WIDE_INT);
-static rtx expand_sdiv_pow2 (machine_mode, rtx, HOST_WIDE_INT);
+static rtx expand_smod_pow2 (scalar_int_mode, rtx, HOST_WIDE_INT);
+static rtx expand_sdiv_pow2 (scalar_int_mode, rtx, HOST_WIDE_INT);
 
 /* Return a constant integer mask value of mode MODE with BITSIZE ones
    followed by BITPOS zeros, or the complement of that if COMPLEMENT.
@@ -81,7 +81,7 @@ static rtx expand_sdiv_pow2 (machine_mode, rtx, HOST_WIDE_INT);
    mask is zero-extended if BITSIZE+BITPOS is too small for MODE.  */
 
 static inline rtx
-mask_rtx (machine_mode mode, int bitpos, int bitsize, bool complement)
+mask_rtx (scalar_int_mode mode, int bitpos, int bitsize, bool complement)
 {
   return immed_wide_int_const
     (wi::shifted_mask (bitpos, bitsize, complement,
@@ -118,8 +118,8 @@ struct init_expmed_rtl
 };
 
 static void
-init_expmed_one_conv (struct init_expmed_rtl *all, machine_mode to_mode,
-		      machine_mode from_mode, bool speed)
+init_expmed_one_conv (struct init_expmed_rtl *all, scalar_int_mode to_mode,
+		      scalar_int_mode from_mode, bool speed)
 {
   int to_size, from_size;
   rtx which;
@@ -476,7 +476,7 @@ adjust_bit_field_mem_for_reg (enum extraction_pattern pattern,
 	{
 	  /* Limit the search to the mode required by the corresponding
 	     register insertion or extraction instruction, if any.  */
-	  machine_mode limit_mode = word_mode;
+	  scalar_int_mode limit_mode = word_mode;
 	  extraction_insn insn;
 	  if (get_best_reg_extraction_insn (&insn, pattern,
 					    GET_MODE_BITSIZE (best_mode),
@@ -2199,7 +2199,7 @@ extract_split_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
 rtx
 extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src)
 {
-  machine_mode int_mode, src_int_mode;
+  scalar_int_mode int_mode, src_int_mode;
 
   if (mode == src_mode)
     return src;
@@ -2530,9 +2530,9 @@ static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INT,
 static rtx expand_mult_const (machine_mode, rtx, HOST_WIDE_INT, rtx,
 			      const struct algorithm *, enum mult_variant);
 static unsigned HOST_WIDE_INT invert_mod2n (unsigned HOST_WIDE_INT, int);
-static rtx extract_high_half (machine_mode, rtx);
-static rtx expmed_mult_highpart (machine_mode, rtx, rtx, rtx, int, int);
-static rtx expmed_mult_highpart_optab (machine_mode, rtx, rtx, rtx,
+static rtx extract_high_half (scalar_int_mode, rtx);
+static rtx expmed_mult_highpart (scalar_int_mode, rtx, rtx, rtx, int, int);
+static rtx expmed_mult_highpart_optab (scalar_int_mode, rtx, rtx, rtx,
 				       int, int);
 /* Compute and return the best algorithm for multiplying by T.
    The algorithm must cost less than cost_limit
@@ -3575,7 +3575,7 @@ invert_mod2n (unsigned HOST_WIDE_INT x, int n)
    MODE is the mode of operation.  */
 
 rtx
-expand_mult_highpart_adjust (machine_mode mode, rtx adj_operand, rtx op0,
+expand_mult_highpart_adjust (scalar_int_mode mode, rtx adj_operand, rtx op0,
 			     rtx op1, rtx target, int unsignedp)
 {
   rtx tem;
@@ -3600,7 +3600,7 @@ expand_mult_highpart_adjust (machine_mode mode, rtx adj_operand, rtx op0,
 /* Subroutine of expmed_mult_highpart.  Return the MODE high part of OP.  */
 
 static rtx
-extract_high_half (machine_mode mode, rtx op)
+extract_high_half (scalar_int_mode mode, rtx op)
 {
   machine_mode wider_mode;
 
@@ -3619,7 +3619,7 @@ extract_high_half (machine_mode mode, rtx op)
    optab.  OP1 is an rtx for the constant operand.  */
 
 static rtx
-expmed_mult_highpart_optab (machine_mode mode, rtx op0, rtx op1,
+expmed_mult_highpart_optab (scalar_int_mode mode, rtx op0, rtx op1,
 			    rtx target, int unsignedp, int max_cost)
 {
   rtx narrow_op1 = gen_int_mode (INTVAL (op1), mode);
@@ -3734,7 +3734,7 @@ expmed_mult_highpart_optab (machine_mode mode, rtx op0, rtx op1,
    MAX_COST is the total allowed cost for the expanded RTL.  */
 
 static rtx
-expmed_mult_highpart (machine_mode mode, rtx op0, rtx op1,
+expmed_mult_highpart (scalar_int_mode mode, rtx op0, rtx op1,
 		      rtx target, int unsignedp, int max_cost)
 {
   machine_mode wider_mode = *GET_MODE_WIDER_MODE (mode);
@@ -3798,7 +3798,7 @@ expmed_mult_highpart (machine_mode mode, rtx op0, rtx op1,
 /* Expand signed modulus of OP0 by a power of two D in mode MODE.  */
 
 static rtx
-expand_smod_pow2 (machine_mode mode, rtx op0, HOST_WIDE_INT d)
+expand_smod_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INT d)
 {
   rtx result, temp, shift;
   rtx_code_label *label;
@@ -3895,7 +3895,7 @@ expand_smod_pow2 (machine_mode mode, rtx op0, HOST_WIDE_INT d)
    This routine is only called for positive values of D.  */
 
 static rtx
-expand_sdiv_pow2 (machine_mode mode, rtx op0, HOST_WIDE_INT d)
+expand_sdiv_pow2 (scalar_int_mode mode, rtx op0, HOST_WIDE_INT d)
 {
   rtx temp;
   rtx_code_label *label;
diff --git a/gcc/expmed.h b/gcc/expmed.h
index f22fa1e..1f95652 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -728,6 +728,7 @@ extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
 			      machine_mode, machine_mode, bool);
 extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
 extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
-extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int);
+extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
+					rtx, int);
 
 #endif  // EXPMED_H
diff --git a/gcc/expr.c b/gcc/expr.c
index b331563..2376d69 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -839,7 +839,7 @@ class pieces_addr
   void *m_cfndata;
 public:
   pieces_addr (rtx, bool, by_pieces_constfn, void *);
-  rtx adjust (machine_mode, HOST_WIDE_INT);
+  rtx adjust (scalar_int_mode, HOST_WIDE_INT);
   void increment_address (HOST_WIDE_INT);
   void maybe_predec (HOST_WIDE_INT);
   void maybe_postinc (HOST_WIDE_INT);
@@ -941,7 +941,7 @@ pieces_addr::decide_autoinc (machine_mode ARG_UNUSED (mode), bool reverse,
    but we still modify the MEM's properties.  */
 
 rtx
-pieces_addr::adjust (machine_mode mode, HOST_WIDE_INT offset)
+pieces_addr::adjust (scalar_int_mode mode, HOST_WIDE_INT offset)
 {
   if (m_constfn)
     return m_constfn (m_cfndata, offset, mode);
@@ -1274,7 +1274,7 @@ store_by_pieces_d::finish_endp (int endp)
 
 int
 can_store_by_pieces (unsigned HOST_WIDE_INT len,
-		     rtx (*constfun) (void *, HOST_WIDE_INT, machine_mode),
+		     rtx (*constfun) (void *, HOST_WIDE_INT, scalar_int_mode),
 		     void *constfundata, unsigned int align, bool memsetp)
 {
   unsigned HOST_WIDE_INT l;
@@ -1353,7 +1353,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
 
 rtx
 store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
-		 rtx (*constfun) (void *, HOST_WIDE_INT, machine_mode),
+		 rtx (*constfun) (void *, HOST_WIDE_INT, scalar_int_mode),
 		 void *constfundata, unsigned int align, bool memsetp, int endp)
 {
   if (len == 0)
@@ -1380,7 +1380,7 @@ store_by_pieces (rtx to, unsigned HOST_WIDE_INT len,
    Return const0_rtx unconditionally.  */
 
 static rtx
-clear_by_pieces_1 (void *, HOST_WIDE_INT, machine_mode)
+clear_by_pieces_1 (void *, HOST_WIDE_INT, scalar_int_mode)
 {
   return const0_rtx;
 }
@@ -7705,7 +7705,7 @@ expand_expr_constant (tree exp, int defer, enum expand_modifier modifier)
    The TARGET, TMODE and MODIFIER arguments are as for expand_expr.  */
 
 static rtx
-expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
+expand_expr_addr_expr_1 (tree exp, rtx target, scalar_int_mode tmode,
 		         enum expand_modifier modifier, addr_space_t as)
 {
   rtx result, subtarget;
@@ -7890,8 +7890,8 @@ expand_expr_addr_expr (tree exp, rtx target, machine_mode tmode,
 		       enum expand_modifier modifier)
 {
   addr_space_t as = ADDR_SPACE_GENERIC;
-  machine_mode address_mode = Pmode;
-  machine_mode pointer_mode = ptr_mode;
+  scalar_int_mode address_mode = Pmode;
+  scalar_int_mode pointer_mode = ptr_mode;
   machine_mode rmode;
   rtx result;
 
@@ -7909,9 +7909,9 @@ expand_expr_addr_expr (tree exp, rtx target, machine_mode tmode,
   /* We can get called with some Weird Things if the user does silliness
      like "(short) &a".  In that case, convert_memory_address won't do
      the right thing, so ignore the given target mode.  */
-  machine_mode new_tmode = (tmode == pointer_mode
-			    ? pointer_mode
-			    : address_mode);
+  scalar_int_mode new_tmode = (tmode == pointer_mode
+			       ? pointer_mode
+			       : address_mode);
 
   result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
 				    new_tmode, modifier, as);
@@ -9923,7 +9923,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	  /* Writing into CONST_DECL is always invalid, but handle it
 	     gracefully.  */
 	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
-	  machine_mode address_mode = targetm.addr_space.address_mode (as);
+	  scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
 	  op0 = expand_expr_addr_expr_1 (exp, NULL_RTX, address_mode,
 					 EXPAND_NORMAL, as);
 	  op0 = memory_address_addr_space (mode, op0, as);
@@ -11461,7 +11461,7 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
             int default_probability)
 {
   struct expand_operand ops[5];
-  machine_mode index_mode = SImode;
+  scalar_int_mode index_mode = SImode;
   rtx op1, op2, index;
 
   if (! targetm.have_casesi ())
diff --git a/gcc/expr.h b/gcc/expr.h
index 558721d..a2be4a6 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -103,7 +103,7 @@ enum block_op_methods
   BLOCK_OP_TAILCALL
 };
 
-typedef rtx (*by_pieces_constfn) (void *, HOST_WIDE_INT, machine_mode);
+typedef rtx (*by_pieces_constfn) (void *, HOST_WIDE_INT, scalar_int_mode);
 
 extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods);
 extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
diff --git a/gcc/final.c b/gcc/final.c
index 388ef64..531a8a3 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1271,7 +1271,7 @@ shorten_branches (rtx_insn *first)
 	      rtx_insn *prev;
 	      int rel_align = 0;
 	      addr_diff_vec_flags flags;
-	      machine_mode vec_mode;
+	      scalar_int_mode vec_mode;
 
 	      /* Avoid automatic aggregate initialization.  */
 	      flags = ADDR_DIFF_VEC_FLAGS (body);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 902e22b..d9ee4fb 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1919,7 +1919,7 @@ fold_convert_const_int_from_fixed (tree type, const_tree arg1)
 {
   tree t;
   double_int temp, temp_trunc;
-  unsigned int mode;
+  machine_mode mode;
 
   /* Right shift FIXED_CST to temp by fbit.  */
   temp = TREE_FIXED_CST (arg1).data;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 61e844f..9dd9eb5 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -580,7 +580,7 @@ expand_arith_set_overflow (tree lhs, rtx target)
 
 static void
 expand_arith_overflow_result_store (tree lhs, rtx target,
-				    machine_mode mode, rtx res)
+				    scalar_int_mode mode, rtx res)
 {
   scalar_int_mode tgtmode
     = as_a <scalar_int_mode> (GET_MODE_INNER (GET_MODE (target)));
@@ -1468,8 +1468,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
     {
       struct separate_ops ops;
       int prec = GET_MODE_PRECISION (mode);
-      scalar_int_mode hmode;
-      machine_mode wmode;
+      scalar_int_mode hmode, wmode;
       ops.op0 = make_tree (type, op0);
       ops.op1 = make_tree (type, op1);
       ops.op2 = NULL_TREE;
diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c
index b032534..528e209 100644
--- a/gcc/loop-doloop.c
+++ b/gcc/loop-doloop.c
@@ -409,7 +409,7 @@ doloop_modify (struct loop *loop, struct niter_desc *desc,
   int nonneg = 0;
   bool increment_count;
   basic_block loop_end = desc->out_edge->src;
-  machine_mode mode;
+  scalar_int_mode mode;
   rtx true_prob_val;
   widest_int iterations;
 
@@ -606,7 +606,7 @@ record_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
 static bool
 doloop_optimize (struct loop *loop)
 {
-  machine_mode mode;
+  scalar_int_mode mode;
   rtx doloop_reg;
   rtx count;
   widest_int iterations, iterations_max;
diff --git a/gcc/lower-subreg.h b/gcc/lower-subreg.h
index 82dc13b..06c2f4f 100644
--- a/gcc/lower-subreg.h
+++ b/gcc/lower-subreg.h
@@ -43,7 +43,7 @@ struct lower_subreg_choices {
 /* Target-specific information for the subreg lowering pass.  */
 struct target_lower_subreg {
   /* An integer mode that is twice as wide as word_mode.  */
-  machine_mode x_twice_word_mode;
+  scalar_int_mode x_twice_word_mode;
 
   /* What we have decided to do when optimizing for size (index 0)
      and speed (index 1).  */
diff --git a/gcc/optabs.c b/gcc/optabs.c
index cc03c9b..6aa5de1 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -434,7 +434,7 @@ expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1,
    value are the same as for the parent routine.  */
 
 static bool
-expand_subword_shift (machine_mode op1_mode, optab binoptab,
+expand_subword_shift (scalar_int_mode op1_mode, optab binoptab,
 		      rtx outof_input, rtx into_input, rtx op1,
 		      rtx outof_target, rtx into_target,
 		      int unsignedp, enum optab_methods methods,
@@ -517,7 +517,7 @@ expand_subword_shift (machine_mode op1_mode, optab binoptab,
    arguments are the same as the parent routine.  */
 
 static bool
-expand_doubleword_shift_condmove (machine_mode op1_mode, optab binoptab,
+expand_doubleword_shift_condmove (scalar_int_mode op1_mode, optab binoptab,
 				  enum rtx_code cmp_code, rtx cmp1, rtx cmp2,
 				  rtx outof_input, rtx into_input,
 				  rtx subword_op1, rtx superword_op1,
@@ -600,7 +600,7 @@ expand_doubleword_shift_condmove (machine_mode op1_mode, optab binoptab,
    Return true if the shift could be successfully synthesized.  */
 
 static bool
-expand_doubleword_shift (machine_mode op1_mode, optab binoptab,
+expand_doubleword_shift (scalar_int_mode op1_mode, optab binoptab,
 			 rtx outof_input, rtx into_input, rtx op1,
 			 rtx outof_target, rtx into_target,
 			 int unsignedp, enum optab_methods methods,
@@ -2165,7 +2165,7 @@ widen_leading (scalar_int_mode mode, rtx op0, rtx target, optab unoptab)
 /* Try calculating clz of a double-word quantity as two clz's of word-sized
    quantities, choosing which based on whether the high word is nonzero.  */
 static rtx
-expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
+expand_doubleword_clz (scalar_int_mode mode, rtx op0, rtx target)
 {
   rtx xop0 = force_reg (mode, op0);
   rtx subhi = gen_highpart (word_mode, xop0);
@@ -2236,7 +2236,7 @@ expand_doubleword_clz (machine_mode mode, rtx op0, rtx target)
 /* Try calculating popcount of a double-word quantity as two popcount's of
    word-sized quantities and summing up the results.  */
 static rtx
-expand_doubleword_popcount (machine_mode mode, rtx op0, rtx target)
+expand_doubleword_popcount (scalar_int_mode mode, rtx op0, rtx target)
 {
   rtx t0, t1, t;
   rtx_insn *seq;
@@ -2276,7 +2276,7 @@ expand_doubleword_popcount (machine_mode mode, rtx op0, rtx target)
    as
 	(parity:narrow (low (x) ^ high (x))) */
 static rtx
-expand_doubleword_parity (machine_mode mode, rtx op0, rtx target)
+expand_doubleword_parity (scalar_int_mode mode, rtx op0, rtx target)
 {
   rtx t = expand_binop (word_mode, xor_optab,
 			operand_subword_force (op0, 0, mode),
@@ -2552,7 +2552,7 @@ expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
 {
   const struct real_format *fmt;
   int bitpos, word, nwords, i;
-  machine_mode imode;
+  scalar_int_mode imode;
   rtx temp;
   rtx_insn *insns;
 
@@ -4062,13 +4062,13 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison,
   enum rtx_code swapped = swap_condition (comparison);
   enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
   machine_mode orig_mode = GET_MODE (x);
-  machine_mode mode, cmp_mode;
+  machine_mode mode;
   rtx true_rtx, false_rtx;
   rtx value, target, equiv;
   rtx_insn *insns;
   rtx libfunc = 0;
   bool reversed_p = false;
-  cmp_mode = targetm.libgcc_cmp_return_mode ();
+  scalar_int_mode cmp_mode = targetm.libgcc_cmp_return_mode ();
 
   FOR_EACH_MODE_FROM (mode, orig_mode)
     {
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 0d1dc85..35cfbe6 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2849,9 +2849,9 @@ subreg_highpart_offset (machine_mode outermode, machine_mode innermode)
 
 extern int byte_lowpart_offset (machine_mode, machine_mode);
 extern rtx make_safe_from (rtx, rtx);
-extern rtx convert_memory_address_addr_space_1 (machine_mode, rtx,
+extern rtx convert_memory_address_addr_space_1 (scalar_int_mode, rtx,
 						addr_space_t, bool, bool);
-extern rtx convert_memory_address_addr_space (machine_mode, rtx,
+extern rtx convert_memory_address_addr_space (scalar_int_mode, rtx,
 					      addr_space_t);
 #define convert_memory_address(to_mode,x) \
 	convert_memory_address_addr_space ((to_mode), (x), ADDR_SPACE_GENERIC)
@@ -3051,7 +3051,7 @@ inline rtx single_set (const rtx_insn *insn)
   return single_set_2 (insn, PATTERN (insn));
 }
 
-extern machine_mode get_address_mode (rtx mem);
+extern scalar_int_mode get_address_mode (rtx mem);
 extern int rtx_addr_can_trap_p (const_rtx);
 extern bool nonzero_address_p (const_rtx);
 extern int rtx_unstable_p (const_rtx);
@@ -3782,8 +3782,8 @@ extern GTY(()) rtx stack_limit_rtx;
 extern unsigned int variable_tracking_main (void);
 
 /* In stor-layout.c.  */
-extern void get_mode_bounds (machine_mode, int, machine_mode,
-			     rtx *, rtx *);
+extern void get_mode_bounds (scalar_int_mode, int,
+			     scalar_int_mode, rtx *, rtx *);
 
 /* In loop-iv.c  */
 extern rtx canon_condition (rtx);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index f74bf14..e47c50d 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -5736,7 +5736,7 @@ low_bitmask_len (machine_mode mode, unsigned HOST_WIDE_INT m)
 
 /* Return the mode of MEM's address.  */
 
-machine_mode
+scalar_int_mode
 get_address_mode (rtx mem)
 {
   machine_mode mode;
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 8ff73ef..48634d9 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2880,8 +2880,8 @@ get_best_mode (int bitsize, int bitpos,
    SIGN).  The returned constants are made to be usable in TARGET_MODE.  */
 
 void
-get_mode_bounds (machine_mode mode, int sign,
-		 machine_mode target_mode,
+get_mode_bounds (scalar_int_mode mode, int sign,
+		 scalar_int_mode target_mode,
 		 rtx *mmin, rtx *mmax)
 {
   unsigned size = GET_MODE_PRECISION (mode);
diff --git a/gcc/target.def b/gcc/target.def
index c450a1d..25473c6 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1989,7 +1989,7 @@ char *, (void), hook_charptr_void_null)
 DEFHOOK_UNDOC
 (eh_return_filter_mode,
  "Return machine mode for filter value.",
- machine_mode, (void),
+ scalar_int_mode, (void),
  default_eh_return_filter_mode)
 
 /* Return machine mode for libgcc expanded cmp instructions.  */
@@ -1999,7 +1999,7 @@ DEFHOOK
 of compare instructions expanded to libgcc calls.  If not defined\n\
 @code{word_mode} is returned which is the right choice for a majority of\n\
 targets.",
- machine_mode, (void),
+ scalar_int_mode, (void),
  default_libgcc_cmp_return_mode)
 
 /* Return machine mode for libgcc expanded shift instructions.  */
@@ -2009,7 +2009,7 @@ DEFHOOK
 of shift instructions expanded to libgcc calls.  If not defined\n\
 @code{word_mode} is returned which is the right choice for a majority of\n\
 targets.",
- machine_mode, (void),
+ scalar_int_mode, (void),
  default_libgcc_shift_count_mode)
 
 /* Return machine mode to be used for _Unwind_Word type.  */
@@ -2017,7 +2017,7 @@ DEFHOOK
 (unwind_word_mode,
  "Return machine mode to be used for @code{_Unwind_Word} type.\n\
 The default is to use @code{word_mode}.",
- machine_mode, (void),
+ scalar_int_mode, (void),
  default_unwind_word_mode)
 
 /* Given two decls, merge their attributes and return the result.  */
@@ -3136,7 +3136,7 @@ extension.\n\
 In order to enforce the representation of @code{mode},\n\
 @code{TRULY_NOOP_TRUNCATION} should return false when truncating to\n\
 @code{mode}.",
- int, (machine_mode mode, machine_mode rep_mode),
+ int, (scalar_int_mode mode, scalar_int_mode rep_mode),
  default_mode_rep_extended)
 
 /* True if MODE is valid for a pointer in __attribute__((mode("MODE"))).  */
@@ -3145,7 +3145,7 @@ DEFHOOK
  "Define this to return nonzero if the port can handle pointers\n\
 with machine mode @var{mode}.  The default version of this\n\
 hook returns true for both @code{ptr_mode} and @code{Pmode}.",
- bool, (machine_mode mode),
+ bool, (scalar_int_mode mode),
  default_valid_pointer_mode)
 
 /* Disambiguate with errno.  */
@@ -3170,7 +3170,7 @@ DEFHOOK
  "Define this to return the machine mode to use for pointers to\n\
 @var{address_space} if the target supports named address spaces.\n\
 The default version of this hook returns @code{ptr_mode}.",
- machine_mode, (addr_space_t address_space),
+ scalar_int_mode, (addr_space_t address_space),
  default_addr_space_pointer_mode)
 
 /* MODE to use for an address in another address space.  */
@@ -3179,7 +3179,7 @@ DEFHOOK
  "Define this to return the machine mode to use for addresses in\n\
 @var{address_space} if the target supports named address spaces.\n\
 The default version of this hook returns @code{Pmode}.",
- machine_mode, (addr_space_t address_space),
+ scalar_int_mode, (addr_space_t address_space),
  default_addr_space_address_mode)
 
 /* True if MODE is valid for a pointer in __attribute__((mode("MODE")))
@@ -3193,7 +3193,7 @@ except that it includes explicit named address space support.  The default\n\
 version of this hook returns true for the modes returned by either the\n\
 @code{TARGET_ADDR_SPACE_POINTER_MODE} or @code{TARGET_ADDR_SPACE_ADDRESS_MODE}\n\
 target hooks for the given address space.",
- bool, (machine_mode mode, addr_space_t as),
+ bool, (scalar_int_mode mode, addr_space_t as),
  default_addr_space_valid_pointer_mode)
 
 /* True if an address is a valid memory address to a given named address
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 8951bc3..df76ba1 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -214,25 +214,25 @@ default_pretend_outgoing_varargs_named (cumulative_args_t ca ATTRIBUTE_UNUSED)
 	  != default_setup_incoming_varargs);
 }
 
-machine_mode
+scalar_int_mode
 default_eh_return_filter_mode (void)
 {
   return targetm.unwind_word_mode ();
 }
 
-machine_mode
+scalar_int_mode
 default_libgcc_cmp_return_mode (void)
 {
   return word_mode;
 }
 
-machine_mode
+scalar_int_mode
 default_libgcc_shift_count_mode (void)
 {
   return word_mode;
 }
 
-machine_mode
+scalar_int_mode
 default_unwind_word_mode (void)
 {
   return word_mode;
@@ -257,8 +257,7 @@ default_min_divisions_for_recip_mul (machine_mode mode ATTRIBUTE_UNUSED)
 /* The default implementation of TARGET_MODE_REP_EXTENDED.  */
 
 int
-default_mode_rep_extended (machine_mode mode ATTRIBUTE_UNUSED,
-			   machine_mode mode_rep ATTRIBUTE_UNUSED)
+default_mode_rep_extended (scalar_int_mode, scalar_int_mode)
 {
   return UNKNOWN;
 }
@@ -1260,7 +1259,7 @@ default_destroy_cost_data (void *data)
 /* Determine whether or not a pointer mode is valid. Assume defaults
    of ptr_mode or Pmode - can be overridden.  */
 bool
-default_valid_pointer_mode (machine_mode mode)
+default_valid_pointer_mode (scalar_int_mode mode)
 {
   return (mode == ptr_mode || mode == Pmode);
 }
@@ -1295,7 +1294,7 @@ default_ref_may_alias_errno (ao_ref *ref)
 /* Return the mode for a pointer to a given ADDRSPACE,
    defaulting to ptr_mode for all address spaces.  */
 
-machine_mode
+scalar_int_mode
 default_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 {
   return ptr_mode;
@@ -1304,7 +1303,7 @@ default_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 /* Return the mode for an address in a given ADDRSPACE,
    defaulting to Pmode for all address spaces.  */
 
-machine_mode
+scalar_int_mode
 default_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
 {
   return Pmode;
@@ -1314,7 +1313,7 @@ default_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
    To match the above, the same modes apply to all address spaces.  */
 
 bool
-default_addr_space_valid_pointer_mode (machine_mode mode,
+default_addr_space_valid_pointer_mode (scalar_int_mode mode,
 				       addr_space_t as ATTRIBUTE_UNUSED)
 {
   return targetm.valid_pointer_mode (mode);
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 151c0f0..c182e45 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -43,14 +43,14 @@ extern void default_setup_incoming_varargs (cumulative_args_t, machine_mode, tre
 extern rtx default_builtin_setjmp_frame_value (void);
 extern bool default_pretend_outgoing_varargs_named (cumulative_args_t);
 
-extern machine_mode default_eh_return_filter_mode (void);
-extern machine_mode default_libgcc_cmp_return_mode (void);
-extern machine_mode default_libgcc_shift_count_mode (void);
-extern machine_mode default_unwind_word_mode (void);
+extern scalar_int_mode default_eh_return_filter_mode (void);
+extern scalar_int_mode default_libgcc_cmp_return_mode (void);
+extern scalar_int_mode default_libgcc_shift_count_mode (void);
+extern scalar_int_mode default_unwind_word_mode (void);
 extern unsigned HOST_WIDE_INT default_shift_truncation_mask
   (machine_mode);
 extern unsigned int default_min_divisions_for_recip_mul (machine_mode);
-extern int default_mode_rep_extended (machine_mode, machine_mode);
+extern int default_mode_rep_extended (scalar_int_mode, scalar_int_mode);
 
 extern tree default_stack_protect_guard (void);
 extern tree default_external_stack_protect_fail (void);
@@ -169,11 +169,11 @@ extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
 extern bool default_target_option_pragma_parse (tree, tree);
 extern bool default_target_can_inline_p (tree, tree);
-extern bool default_valid_pointer_mode (machine_mode);
+extern bool default_valid_pointer_mode (scalar_int_mode);
 extern bool default_ref_may_alias_errno (struct ao_ref *);
-extern machine_mode default_addr_space_pointer_mode (addr_space_t);
-extern machine_mode default_addr_space_address_mode (addr_space_t);
-extern bool default_addr_space_valid_pointer_mode (machine_mode,
+extern scalar_int_mode default_addr_space_pointer_mode (addr_space_t);
+extern scalar_int_mode default_addr_space_address_mode (addr_space_t);
+extern bool default_addr_space_valid_pointer_mode (scalar_int_mode,
 						   addr_space_t);
 extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
 						     bool, addr_space_t);
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index a53ade0..2de1d5f 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -195,8 +195,8 @@ rtx
 addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
 		  bool really_expand)
 {
-  machine_mode address_mode = targetm.addr_space.address_mode (as);
-  machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
+  scalar_int_mode pointer_mode = targetm.addr_space.pointer_mode (as);
   rtx address, sym, bse, idx, st, off;
   struct mem_addr_template *templ;
 
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 3653586..837ce65 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -2465,7 +2465,8 @@ compute_max_addr_offset (struct iv_use *use)
   HOST_WIDE_INT i, off;
   unsigned list_index, num;
   addr_space_t as;
-  machine_mode mem_mode, addr_mode;
+  machine_mode mem_mode;
+  scalar_int_mode addr_mode;
   static vec<HOST_WIDE_INT> max_offset_list;
 
   as = TYPE_ADDR_SPACE (TREE_TYPE (use->iv->base));
@@ -3970,7 +3971,7 @@ get_address_cost (bool symbol_present, bool var_present,
 		  addr_space_t as, bool speed,
 		  bool stmt_after_inc, bool *may_autoinc)
 {
-  machine_mode address_mode = targetm.addr_space.address_mode (as);
+  scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
   static vec<address_cost_data *> address_cost_data_list;
   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mem_mode;
   address_cost_data *data;
@@ -4285,7 +4286,7 @@ get_address_cost (bool symbol_present, bool var_present,
     the cost in COST.  */
 
 static bool
-get_shiftadd_cost (tree expr, machine_mode mode, comp_cost cost0,
+get_shiftadd_cost (tree expr, scalar_int_mode mode, comp_cost cost0,
 		   comp_cost cost1, tree mult, bool speed, comp_cost *cost)
 {
   comp_cost res;
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index e4c8a60..329ece1 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -952,7 +952,7 @@ array_value_type (gswitch *swtch, tree type, int num,
     return type;
 
   scalar_int_mode type_mode = SCALAR_INT_TYPE_MODE (type);
-  machine_mode mode = get_narrowest_mode (type_mode);
+  scalar_int_mode mode = get_narrowest_mode (type_mode);
   if (GET_MODE_SIZE (type_mode) <= GET_MODE_SIZE (mode))
     return type;
 
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index acd536c..41b5065 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -9970,7 +9970,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
   value_range *vr = get_value_range (rhs1);
   scalar_float_mode fltmode
     = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
-  machine_mode mode;
+  scalar_int_mode mode;
   tree tem;
   gassign *conv;
 
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index bec9195..6d52bd6 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -970,7 +970,7 @@ use_narrower_mode_test (rtx x, const_rtx subreg)
 /* Transform X into narrower mode MODE from wider mode WMODE.  */
 
 static rtx
-use_narrower_mode (rtx x, machine_mode mode, machine_mode wmode)
+use_narrower_mode (rtx x, scalar_int_mode mode, scalar_int_mode wmode)
 {
   rtx op0, op1;
   if (CONSTANT_P (x))

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

* [66/67] Add a scalar_mode_pod class
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (63 preceding siblings ...)
  2016-12-09 13:38 ` [63/67] Simplifications after type switch Richard Sandiford
@ 2016-12-09 13:40 ` Richard Sandiford
  2016-12-09 13:40 ` [65/67] Use scalar_mode in the AArch64 port Richard Sandiford
                   ` (4 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:40 UTC (permalink / raw)
  To: gcc-patches

This patch adds a scalar_mode_pod class and uses it for
fixed_value, instead of machine_mode_enum.

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

	* coretypes.h (scalar_mode_pod): New typedef.
	* machmode.h (gt_ggc_mx, gt_pch_nx): New functions.
	* fixed-value.h (fixed_value::mode): Change type to scalar_mode_pod.
	* fold-const.c (fold_convert_const_int_from_fixed): Use scalar_mode.
	* tree-streamer-in.c (unpack_ts_fixed_cst_value_fields): Use
	as_a <scalar_mode>.

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 0fdd025..564d7fe 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -64,6 +64,7 @@ typedef opt_mode<scalar_mode> opt_scalar_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_mode> scalar_mode_pod;
 typedef pod_mode<scalar_int_mode> scalar_int_mode_pod;
 
 /* Subclasses of rtx_def, using indentation to show the class
diff --git a/gcc/fixed-value.h b/gcc/fixed-value.h
index 78df6e6..5e75f66 100644
--- a/gcc/fixed-value.h
+++ b/gcc/fixed-value.h
@@ -22,8 +22,8 @@ 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_enum mode;	/* Use machine mode to know IBIT and FBIT.  */
+  double_int data;       /* Store data up to 2 wide integers.  */
+  scalar_mode_pod mode;  /* Use machine mode to know IBIT and FBIT.  */
 };
 
 #define FIXED_VALUE_TYPE struct fixed_value
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3876883..7c6e0d9 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1919,7 +1919,7 @@ fold_convert_const_int_from_fixed (tree type, const_tree arg1)
 {
   tree t;
   double_int temp, temp_trunc;
-  machine_mode mode;
+  scalar_mode mode;
 
   /* Right shift FIXED_CST to temp by fbit.  */
   temp = TREE_FIXED_CST (arg1).data;
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 1dae146..fe62965 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -902,4 +902,22 @@ namespace mode_iterator
        mode_iterator::iterate_p (&(ITERATOR)); \
        mode_iterator::get_2xwider (&(ITERATOR)))
 
+template<typename T>
+void
+gt_ggc_mx (pod_mode<T> *)
+{
+}
+
+template<typename T>
+void
+gt_pch_nx (pod_mode<T> *)
+{
+}
+
+template<typename T>
+void
+gt_pch_nx (pod_mode<T> *, void (*) (void *, void *), void *)
+{
+}
+
 #endif /* not HAVE_MACHINE_MODES */
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 3d8a7bb..d1e7f96 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -208,7 +208,7 @@ static void
 unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
 {
   FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
-  fp->mode = bp_unpack_machine_mode (bp);
+  fp->mode = as_a <scalar_mode> (bp_unpack_machine_mode (bp));
   fp->data.low = bp_unpack_var_len_int (bp);
   fp->data.high = bp_unpack_var_len_int (bp);
   TREE_FIXED_CST_PTR (expr) = fp;

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

* [65/67] Use scalar_mode in the AArch64 port
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (64 preceding siblings ...)
  2016-12-09 13:40 ` [66/67] Add a scalar_mode_pod class Richard Sandiford
@ 2016-12-09 13:40 ` Richard Sandiford
  2016-12-09 13:40 ` [64/67] Add a scalar_mode class Richard Sandiford
                   ` (3 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:40 UTC (permalink / raw)
  To: gcc-patches

Similar to the previous scalar_int_mode patch.

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

	* config/aarch64/aarch64-protos.h (aarch64_gen_adjusted_ldpstp):
	Take a scalar_mode rather than a machine_mode.
	(aarch64_operands_adjust_ok_for_ldpstp): Likewise.
	* config/aarch64/aarch64.c (aarch64_simd_container_mode): Likewise.
	(aarch64_operands_adjust_ok_for_ldpstp): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.

diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 17f1b93..72329c7 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -423,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, machine_mode, RTX_CODE);
+bool aarch64_gen_adjusted_ldpstp (rtx *, bool, scalar_mode, RTX_CODE);
 #endif /* RTX_CODE */
 
 void aarch64_init_builtins (void);
@@ -451,7 +451,7 @@ 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, machine_mode);
-bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, machine_mode);
+bool aarch64_operands_adjust_ok_for_ldpstp (rtx *, bool, scalar_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 283f73c..88f64d7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10780,7 +10780,7 @@ aarch64_vector_mode_supported_p (machine_mode mode)
 /* Return appropriate SIMD container
    for MODE within a vector of WIDTH bits.  */
 static machine_mode
-aarch64_simd_container_mode (machine_mode mode, unsigned width)
+aarch64_simd_container_mode (scalar_mode mode, unsigned width)
 {
   gcc_assert (width == 64 || width == 128);
   if (TARGET_SIMD)
@@ -14206,7 +14206,7 @@ aarch64_operands_ok_for_ldpstp (rtx *operands, bool load,
 
 bool
 aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
-				       machine_mode mode)
+				       scalar_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;
@@ -14340,7 +14340,7 @@ aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load,
 
 bool
 aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
-			     machine_mode mode, RTX_CODE code)
+			     scalar_mode mode, RTX_CODE code)
 {
   rtx base, offset, t1, t2;
   rtx mem_1, mem_2, mem_3, mem_4;

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

* [64/67] Add a scalar_mode class
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (65 preceding siblings ...)
  2016-12-09 13:40 ` [65/67] Use scalar_mode in the AArch64 port Richard Sandiford
@ 2016-12-09 13:40 ` Richard Sandiford
  2016-12-09 13:41 ` [67/67] Add a complex_mode class Richard Sandiford
                   ` (2 subsequent siblings)
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:40 UTC (permalink / raw)
  To: gcc-patches

This patch adds a scalar_mode class that can hold any scalar mode,
specifically:

  - scalar integers
  - scalar floating-point values
  - scalar fractional modes
  - scalar accumulator modes
  - pointer bounds modes

The type is useful in four main situations:

  - as the mode of a CONST_SCALAR_INT_P.  Logically these would
    be scalar_int_modes, but we also use CONST_INT for pointer
    bounds modes.

  - while operating on the fixed-point modes (fractional and
    accumulator).  It would be possible to define special classes
    for these, but at the moment nothing would benefit from them.
    In particular, there's no use case that would help select between
    one class for all fixed-point modes versus one class for fractional
    modes and one class for accumulator modes.

  - in hooks like scalar_mode_supported_p.

  - as the mode of a vector element, in cases where we don't need
    to distinguish between integer and floating-point elements.

The number of uses is much smaller than for scalar_int_mode,
so the patch handles them all at once.

The patch also gets rid of a redundant assignment to total_bytes
in native_interpret_real.  The variable was already set to the
same value in the variable declaration block.

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

	* coretypes.h (scalar_mode): New type.
	(opt_scalar_mode): New typedef.
	* machmode.h (scalar_mode): New class.
	(scalar_mode::includes_p): New function.
	(scalar_mode::from_int): Likewise.
	(mode_to_inner): Return a scalar_mode rather than a machine_mode.
	(mode_for_vector): Take a scalar_mode rather than a machine_mode.
	(is_float_mode): New function.
	(mode_iterator::get_2xwider): Likewise.
	* target.def (preferred_simd_mode): Take a scalar_mode rather
	than a machine_mode.
	(scalar_mode_supported_p): Likewise.
	* doc/tm.texi: Regenerate.
	* tree.h (SCALAR_TYPE_MODE): New macro.
	* cfgexpand.c (expand_debug_expr): Use scalar_mode.
	* config/aarch64/aarch64.c (aarch64_expand_vector_init): Likewise.
	(aarch64_preferred_mode): Take a scalar_mode rather than a
	machine_mode.
	(aarch64_scalar_mode_supported_p): Likewise.
	* config/alpha/alpha.c (alpha_scalar_mode_supported_p): Likewise.
	* config/arc/arc.c (arc_preferred_simd_mode): Likewise.
	* config/arm/arm.c (arm_scalar_mode_supported_p): Likewise.
	(arm_preferred_simd_mode): Likewise.
	* config/avr/avr.c (avr_scalar_mode_supported_p): Likewise.
	(avr_out_round): Use as_a <scalar_mode>.
	* config/c6x/c6x.c (c6x_preferred_simd_mode): Take a scalar_mode
	rather than a machine_mode.
	(c6x_scalar_mode_supported_p): Likewise.
	* config/epiphany/epiphany.c (epiphany_preferred_simd_mode): Likewise.
	* config/i386/i386.c (ix86_scalar_mode_supported_p): Likewise.
	(ix86_preferred_simd_mode): Likewise.
	* config/ia64/ia64.c (ia64_scalar_mode_supported_p): Likewise.
	* config/mips/mips.c (mips_scalar_mode_supported_p): Likewise.
	(mips_preferred_simd_mode): Likewise.
	* config/msp430/msp430.c (msp430_scalar_mode_supported_p): Likewise.
	* config/pa/pa.c (pa_scalar_mode_supported_p): Likewise.
	* config/pdp11/pdp11.c (pdp11_scalar_mode_supported_p): Likewise.
	* config/rs6000/rs6000.c (rs6000_preferred_simd_mode): Likewise.
	(rs6000_scalar_mode_supported_p): Likewise.
	* config/s390/s390.c (s390_scalar_mode_supported_p): Likewise.
	(s390_preferred_simd_mode): Likewise.
	* config/sparc/sparc.c (sparc_preferred_simd_mode): Likewise.
	* config/spu/spu.c (spu_scalar_mode_supported_p): Likewise.
	* config/tilegx/tilegx.c (tilegx_scalar_mode_supported_p): Likewise.
	* config/tilepro/tilepro.c (tilepro_scalar_mode_supported_p):
	Likewise.
	* dwarf2out.c (loc_descriptor): Use as_a <scalar_mode>.
	* explow.c (trunc_int_for_mode): Likewise.
	(promote_mode): Likewise.
	* emit-rtl.c (immed_wide_int_const): Likewise.
	(immed_double_const): Use is_a <scalar_mode> instead of separate
	mode class checks.
	(init_emit_once): Use opt_scalar_mode for some iterators.
	* expmed.c (store_bit_field_1): Use scalar_mode.
	(extract_bit_field_1): Likewise.
	* expr.c (convert_move): Split handling of scalars into...
	(convert_move_scalar): ...this new function.  Use opt_scalar_mode
	for a mode iterator.
	(write_complex_part): Use scalar_mode.
	(read_complex_part): Likewise.
	(emit_move_complex_part): Likewise.
	(expand_expr_addr_expr_1): Use SCALAR_TYPE_MODE.
	(expand_expr_real_2): Likewise.  Use scakar_mode.
	* fixed-value.h (fixed_from_double_int): Take a scalar_mode
	rather than a machine_mode.
	(fixed_from_string): Likewise.
	(fixed_convert): Likewise.
	(fixed_convert_from_int): Likewise.
	(fixed_convert_from_real): Likewise.
	(fixed_convert_from_fixed): Likewise.
	* fixed-value.c (fixed_from_double_int): Likewise.
	(fixed_from_string): Likewise.
	(fixed_convert): Likewise.
	(fixed_convert_from_int): Likewise.
	(fixed_convert_from_real): Likewise.
	(fixed_convert_from_fixed): Likewise.
	* fold-const.c (fold_convert_const_fixed_from_fixed): Use
	SCALAR_TYPE_MODE.
	(fold_convert_const_fixed_from_int): Likewise.
	(fold_convert_const_fixed_from_real): Likewise.
	(native_encode_fixed): Use scalar_mode.
	(native_encode_complex): Use SCALAR_TYPE_MODE.
	(native_encode_vector): Likewise.
	(native_interpret_fixed): Likewise.
	(native_interpret_real): Likewise.
	(native_interpret_complex): Likewise.
	(native_interpret_vector): Likewise.
	* omp-simd-clone.c (simd_clone_adjust_return_type): Likewise.
	(simd_clone_adjust_argument_types): Likewise.
	(simd_clone_init_simd_arrays): Likewise.
	(simd_clone_adjust): Likewise.
	* function.c (assign_parm_setup_reg): Use scalar_mode.
	(assign_parms_unsplit_complex): Likewise.
	* genmodes.c (get_mode_class): Handle remaining scalar modes.
	* omp-low.c (omp_clause_aligned_alignment): Use opt_scalar_mode
	for mode iterators.
	(expand_omp_atomic): Use is_int_mode and is_float_mode.
	* optabs-query.c (can_vec_mask_load_store_p): Return false for
	non-scalar modes.
	* optabs.c (expand_binop): Use scalar_mode.
	(expand_fix): Use opt_scalar_mode for a mode iterator.
	(expand_float): Likewise.  Use is_a <scalar_mode>.
	* rtl.h (wi::int_traits<rtx_mode_t>::get_precision): Use
	as_a <scalar_mode>.
	(wi::shwi): Likewise.
	(wi::min_value): Likewise.
	(wi::max_value): Likewise.
	* rtlanal.c (subreg_get_info): Use scalar_mode.
	* sdbout.c (sdbout_params): Use is_a <scalar_mode>.
	* simplify-rtx.c (simplify_immed_subreg): Use scalar_mode.
	Fix rtx_mode_t argument for CONST_WIDE_INT.
	* stor-layout.c (mode_for_vector): Take a scalar_mode instead
	of a machine_mode.
	(layout_type): Use SCALAR_TYPE_MODE.
	* targhooks.h (default_scalar_mode_supported_p): Take a scalar_mode
	instead of a machine_mode.
	(default_preferred_simd_mode): Likewise.
	* targhooks.c (default_scalar_mode_supported_p): Likewise.
	(default_preferred_simd_mode): Likewise.
	* tree.c (build_minus_one_cst): Use SCALAR_TYPE_MODE.
	* tree-cfg.c (verify_gimple_assign_ternary): Likewise.
	* tree-inline.c (estimate_move_cost): Likewise.
	* tree-ssa-math-opts.c (convert_plusminus_to_widen): Likewise.
	* tree-vect-loop.c (vect_create_epilog_for_reduction): Likewise.
	(vectorizable_reduction): Likewise.
	* tree-vect-patterns.c (vect_recog_widen_mult_pattern): Likewise.
	(vect_recog_mixed_size_cond_pattern): Likewise.
	(check_bool_pattern): Likewise.
	(adjust_bool_pattern): Likewise.
	(search_type_for_real_1): Likewise.
	* tree-vect-slp.c (vect_schedule_slp_instance): Likewise.
	* tree-vect-stmts.c (vectorizable_conversion): Likewise.
	Use opt_scalar_mode for a mode iterator.
	(get_vectype_for_scalar_type): Use is_int_mode and is_float_mode.
	* ubsan.c (ubsan_encode_value): Use SCALAR_TYPE_MODE.
	* varasm.c (output_constant): Likewise.
	(output_constant_pool_2): Use scalar_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 (vector_mode_valid_p) Fold GET_MODE_INNER call
	into scalar_mode_supported_p call.
	(handle_mode_attribute): Update call to scalar_mode_supported_p.
	* c-lex.c (interpret_fixed): Use SCALAR_TYPE_MODE.
	* c-common.c (c_build_vec_perm_expr): Likewise.
	(c_common_fixed_point_type_for_size): Use opt_scalar_mode
	for the mode iterator.

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

	* c-typeck.c (c_common_type): Use SCALAR_TYPE_MODE and
	as_a <scalar_mode>.
	(build_binary_op): Use SCALAR_TYPE_MODE.

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

	* typeck.c (cp_build_binary_op): Use SCALAR_TYPE_MODE.

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 14b43fe..6953bf2 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -1226,7 +1226,6 @@ static bool
 vector_mode_valid_p (machine_mode mode)
 {
   enum mode_class mclass = GET_MODE_CLASS (mode);
-  machine_mode innermode;
 
   /* Doh!  What's going on?  */
   if (mclass != MODE_VECTOR_INT
@@ -1241,14 +1240,12 @@ vector_mode_valid_p (machine_mode mode)
   if (targetm.vector_mode_supported_p (mode))
     return true;
 
-  innermode = GET_MODE_INNER (mode);
-
   /* We should probably return 1 if requesting V4DI and we have no DI,
      but we have V2DI, but this is probably very unlikely.  */
 
   /* If we have support for the inner mode, we can safely emulate it.
      We may not have V2DI, but me can emulate with a pair of DIs.  */
-  return targetm.scalar_mode_supported_p (innermode);
+  return targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
 }
 
 
@@ -1324,7 +1321,8 @@ handle_mode_attribute (tree *node, tree name, tree args,
 	case MODE_UFRACT:
 	case MODE_ACCUM:
 	case MODE_UACCUM:
-	  valid_mode = targetm.scalar_mode_supported_p (mode);
+	  valid_mode
+	    = targetm.scalar_mode_supported_p (as_a <scalar_mode> (mode));
 	  break;
 
 	case MODE_COMPLEX_INT:
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0e06725..fa9af7f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1027,8 +1027,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask,
       return error_mark_node;
     }
 
-  if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
-      != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
+  if (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
+      != GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
     {
       if (complain)
 	error_at (loc, "__builtin_shuffle argument vector(s) inner type "
@@ -2125,12 +2125,12 @@ c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
   else
     mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
 
-  machine_mode mode;
+  opt_scalar_mode mode;
   FOR_EACH_MODE_IN_CLASS (mode, mclass)
-    if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
+    if (GET_MODE_IBIT (*mode) >= ibit && GET_MODE_FBIT (*mode) >= fbit)
       break;
 
-  if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode))
+  if (!mode.exists () || !targetm.scalar_mode_supported_p (*mode))
     {
       sorry ("GCC cannot support operators with integer types and "
 	     "fixed-point types that have too many integral and "
@@ -2138,7 +2138,7 @@ c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
       return 0;
     }
 
-  return c_common_type_for_mode (mode, satp);
+  return c_common_type_for_mode (*mode, satp);
 }
 
 /* Used for communication between c_common_type_for_mode and
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index e3803b0..adc58b1 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -1109,7 +1109,7 @@ interpret_fixed (const cpp_token *token, unsigned int flags)
   memcpy (copy, token->val.str.text, copylen);
   copy[copylen] = '\0';
 
-  fixed_from_string (&fixed, copy, TYPE_MODE (type));
+  fixed_from_string (&fixed, copy, SCALAR_TYPE_MODE (type));
 
   /* Create a node with determined type and value.  */
   value = build_fixed (type, fixed);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index f0917ed..6326023 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -808,11 +808,11 @@ c_common_type (tree t1, tree t2)
   if (code1 == FIXED_POINT_TYPE || code2 == FIXED_POINT_TYPE)
     {
       unsigned int unsignedp = 0, satp = 0;
-      machine_mode m1, m2;
+      scalar_mode m1, m2;
       unsigned int fbit1, ibit1, fbit2, ibit2, max_fbit, max_ibit;
 
-      m1 = TYPE_MODE (t1);
-      m2 = TYPE_MODE (t2);
+      m1 = SCALAR_TYPE_MODE (t1);
+      m2 = SCALAR_TYPE_MODE (t2);
 
       /* If one input type is saturating, the result type is saturating.  */
       if (TYPE_SATURATING (t1) || TYPE_SATURATING (t2))
@@ -844,7 +844,8 @@ c_common_type (tree t1, tree t2)
 		mclass = MODE_ACCUM;
 	      else
 		gcc_unreachable ();
-	      m1 = mode_for_size (GET_MODE_PRECISION (m1), mclass, 0);
+	      m1 = as_a <scalar_mode>
+		(mode_for_size (GET_MODE_PRECISION (m1), mclass, 0));
 	    }
 	  if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
 	    {
@@ -855,7 +856,8 @@ c_common_type (tree t1, tree t2)
 		mclass = MODE_ACCUM;
 	      else
 		gcc_unreachable ();
-	      m2 = mode_for_size (GET_MODE_PRECISION (m2), mclass, 0);
+	      m2 = as_a <scalar_mode>
+		(mode_for_size (GET_MODE_PRECISION (m2), mclass, 0));
 	    }
 	}
 
@@ -11217,7 +11219,8 @@ build_binary_op (location_t location, enum tree_code code,
 
           /* Always construct signed integer vector type.  */
           intt = c_common_type_for_size (GET_MODE_BITSIZE
-					   (TYPE_MODE (TREE_TYPE (type0))), 0);
+					 (SCALAR_TYPE_MODE
+					  (TREE_TYPE (type0))), 0);
           result_type = build_opaque_vector_type (intt,
 						  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
@@ -11376,7 +11379,8 @@ build_binary_op (location_t location, enum tree_code code,
 
           /* Always construct signed integer vector type.  */
           intt = c_common_type_for_size (GET_MODE_BITSIZE
-					   (TYPE_MODE (TREE_TYPE (type0))), 0);
+					 (SCALAR_TYPE_MODE
+					  (TREE_TYPE (type0))), 0);
           result_type = build_opaque_vector_type (intt,
 						  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 3d9f3ac..4866c4a 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4812,7 +4812,7 @@ expand_debug_expr (tree exp)
 						   GET_MODE_INNER (mode)));
       else
 	{
-	  machine_mode imode = GET_MODE_INNER (mode);
+	  scalar_mode imode = GET_MODE_INNER (mode);
 	  rtx re, im;
 
 	  if (MEM_P (op0))
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 9981f55..283f73c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -10823,7 +10823,7 @@ aarch64_simd_container_mode (machine_mode mode, unsigned width)
 
 /* Return 128-bit container as the preferred SIMD mode for MODE.  */
 static machine_mode
-aarch64_preferred_simd_mode (machine_mode mode)
+aarch64_preferred_simd_mode (scalar_mode mode)
 {
   return aarch64_simd_container_mode (mode, 128);
 }
@@ -11555,7 +11555,7 @@ void
 aarch64_expand_vector_init (rtx target, rtx vals)
 {
   machine_mode mode = GET_MODE (target);
-  machine_mode inner_mode = GET_MODE_INNER (mode);
+  scalar_mode inner_mode = GET_MODE_INNER (mode);
   /* The number of vector elements.  */
   int n_elts = GET_MODE_NUNITS (mode);
   /* The number of vector elements which are not constant.  */
@@ -14575,7 +14575,7 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
    if MODE is HFmode, and punt to the generic implementation otherwise.  */
 
 static bool
-aarch64_scalar_mode_supported_p (machine_mode mode)
+aarch64_scalar_mode_supported_p (scalar_mode mode)
 {
   return (mode == HFmode
 	  ? true
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 620a442..b40bbbb 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -688,7 +688,7 @@ resolve_reload_operand (rtx op)
    indicates only DFmode.  */
 
 static bool
-alpha_scalar_mode_supported_p (machine_mode mode)
+alpha_scalar_mode_supported_p (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index bc5c031..ae97ec2 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -273,7 +273,7 @@ arc_vector_mode_supported_p (machine_mode mode)
 /* Implements target hook TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
 
 static machine_mode
-arc_preferred_simd_mode (machine_mode mode)
+arc_preferred_simd_mode (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 45c08bf..f99700f 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -248,7 +248,7 @@ static bool arm_output_addr_const_extra (FILE *, rtx);
 static bool arm_allocate_stack_slots_for_args (void);
 static bool arm_warn_func_return (tree);
 static tree arm_promoted_type (const_tree t);
-static bool arm_scalar_mode_supported_p (machine_mode);
+static bool arm_scalar_mode_supported_p (scalar_mode);
 static bool arm_frame_pointer_required (void);
 static bool arm_can_eliminate (const int, const int);
 static void arm_asm_trampoline_template (FILE *);
@@ -260,7 +260,7 @@ static bool xscale_sched_adjust_cost (rtx_insn *, int, rtx_insn *, int *);
 static bool fa726te_sched_adjust_cost (rtx_insn *, int, rtx_insn *, int *);
 static bool arm_array_mode_supported_p (machine_mode,
 					unsigned HOST_WIDE_INT);
-static machine_mode arm_preferred_simd_mode (machine_mode);
+static machine_mode arm_preferred_simd_mode (scalar_mode);
 static bool arm_class_likely_spilled_p (reg_class_t);
 static HOST_WIDE_INT arm_vector_alignment (const_tree type);
 static bool arm_vector_alignment_reachable (const_tree type, bool is_packed);
@@ -23317,7 +23317,7 @@ arm_promoted_type (const_tree t)
    special-cased in the default hook.  */
 
 static bool
-arm_scalar_mode_supported_p (machine_mode mode)
+arm_scalar_mode_supported_p (scalar_mode mode)
 {
   if (mode == HFmode)
     return (arm_fp16_format != ARM_FP16_FORMAT_NONE);
@@ -26633,7 +26633,7 @@ arm_array_mode_supported_p (machine_mode mode,
    widths are supported properly by the middle-end.  */
 
 static machine_mode
-arm_preferred_simd_mode (machine_mode mode)
+arm_preferred_simd_mode (scalar_mode mode)
 {
   if (TARGET_NEON)
     switch (mode)
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 105ceb1..935a6f4 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -874,7 +874,7 @@ avr_regno_reg_class (int r)
 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'.  */
 
 static bool
-avr_scalar_mode_supported_p (machine_mode mode)
+avr_scalar_mode_supported_p (scalar_mode mode)
 {
   if (ALL_FIXED_POINT_MODE_P (mode))
     return true;
@@ -8922,7 +8922,7 @@ avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
 const char*
 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
 {
-  machine_mode mode = GET_MODE (xop[0]);
+  scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
   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);
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 7e059b2..968f469 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -6236,7 +6236,7 @@ c6x_vector_mode_supported_p (machine_mode mode)
 
 /* Implements TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
 static machine_mode
-c6x_preferred_simd_mode (machine_mode mode)
+c6x_preferred_simd_mode (scalar_mode mode)
 {
   switch (mode)
     {
@@ -6253,7 +6253,7 @@ c6x_preferred_simd_mode (machine_mode mode)
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
 
 static bool
-c6x_scalar_mode_supported_p (machine_mode mode)
+c6x_scalar_mode_supported_p (scalar_mode mode)
 {
   if (ALL_FIXED_POINT_MODE_P (mode)
       && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index a1fe09c..3cec031 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -2773,7 +2773,7 @@ epiphany_min_divisions_for_recip_mul (machine_mode mode)
 }
 
 static machine_mode
-epiphany_preferred_simd_mode (machine_mode mode ATTRIBUTE_UNUSED)
+epiphany_preferred_simd_mode (scalar_mode mode ATTRIBUTE_UNUSED)
 {
   return TARGET_VECT_DOUBLE ? DImode : SImode;
 }
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4d74bc4..b825f3b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -44075,7 +44075,7 @@ ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
 \f
 /* Target hook for scalar_mode_supported_p.  */
 static bool
-ix86_scalar_mode_supported_p (machine_mode mode)
+ix86_scalar_mode_supported_p (scalar_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
@@ -50266,7 +50266,7 @@ ix86_reassociation_width (unsigned int, machine_mode mode)
    place emms and femms instructions.  */
 
 static machine_mode
-ix86_preferred_simd_mode (machine_mode mode)
+ix86_preferred_simd_mode (scalar_mode mode)
 {
   if (!TARGET_SSE)
     return word_mode;
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 91bf0a0..3507151 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -309,7 +309,7 @@ static tree ia64_handle_version_id_attribute (tree *, tree, tree, int, bool *);
 static void ia64_encode_section_info (tree, rtx, int);
 static rtx ia64_struct_value_rtx (tree, int);
 static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
-static bool ia64_scalar_mode_supported_p (machine_mode mode);
+static bool ia64_scalar_mode_supported_p (scalar_mode mode);
 static bool ia64_vector_mode_supported_p (machine_mode mode);
 static bool ia64_legitimate_constant_p (machine_mode, rtx);
 static bool ia64_legitimate_address_p (machine_mode, rtx, bool);
@@ -10963,7 +10963,7 @@ ia64_struct_value_rtx (tree fntype,
 }
 
 static bool
-ia64_scalar_mode_supported_p (machine_mode mode)
+ia64_scalar_mode_supported_p (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ae93ddb..a48c4b5 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -13304,7 +13304,7 @@ mips_vector_mode_supported_p (machine_mode mode)
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
 
 static bool
-mips_scalar_mode_supported_p (machine_mode mode)
+mips_scalar_mode_supported_p (scalar_mode mode)
 {
   if (ALL_FIXED_POINT_MODE_P (mode)
       && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
@@ -13316,7 +13316,7 @@ mips_scalar_mode_supported_p (machine_mode mode)
 /* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
 
 static machine_mode
-mips_preferred_simd_mode (machine_mode mode)
+mips_preferred_simd_mode (scalar_mode mode)
 {
   if (TARGET_PAIRED_SINGLE_FLOAT
       && mode == SFmode)
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 3711e45..b003d70 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -864,7 +864,7 @@ msp430_option_override (void)
 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
 
 static bool
-msp430_scalar_mode_supported_p (machine_mode m)
+msp430_scalar_mode_supported_p (scalar_mode m)
 {
   if (m == PSImode && msp430x)
     return true;
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 6300a42..2cf0ea2 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -142,7 +142,7 @@ static rtx pa_expand_builtin (tree, rtx, rtx, machine_mode mode, int);
 static rtx hppa_builtin_saveregs (void);
 static void hppa_va_start (tree, rtx);
 static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *);
-static bool pa_scalar_mode_supported_p (machine_mode);
+static bool pa_scalar_mode_supported_p (scalar_mode);
 static bool pa_commutative_p (const_rtx x, int outer_code);
 static void copy_fp_args (rtx_insn *) ATTRIBUTE_UNUSED;
 static int length_fp_args (rtx_insn *) ATTRIBUTE_UNUSED;
@@ -6398,7 +6398,7 @@ hppa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
    2 * BITS_PER_WORD isn't equal LONG_LONG_TYPE_SIZE.  */
 
 static bool
-pa_scalar_mode_supported_p (machine_mode mode)
+pa_scalar_mode_supported_p (scalar_mode mode)
 {
   int precision = GET_MODE_PRECISION (mode);
 
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index 8e2de14..b0931bf 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -160,7 +160,7 @@ static void pdp11_function_arg_advance (cumulative_args_t,
 static void pdp11_conditional_register_usage (void);
 static bool pdp11_legitimate_constant_p (machine_mode, rtx);
 
-static bool pdp11_scalar_mode_supported_p (machine_mode);
+static bool pdp11_scalar_mode_supported_p (scalar_mode);
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_BYTE_OP
@@ -1909,7 +1909,7 @@ pdp11_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
 
 static bool
-pdp11_scalar_mode_supported_p (machine_mode mode)
+pdp11_scalar_mode_supported_p (scalar_mode mode)
 {
   /* Support SFmode even with -mfloat64.  */
   if (mode == SFmode)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ac48e44..0aed9dc 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -5465,7 +5465,7 @@ rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
 /* Implement targetm.vectorize.preferred_simd_mode.  */
 
 static machine_mode
-rs6000_preferred_simd_mode (machine_mode mode)
+rs6000_preferred_simd_mode (scalar_mode mode)
 {
   if (TARGET_VSX)
     switch (mode)
@@ -37651,7 +37651,7 @@ rs6000_eh_return_filter_mode (void)
 
 /* Target hook for scalar_mode_supported_p.  */
 static bool
-rs6000_scalar_mode_supported_p (machine_mode mode)
+rs6000_scalar_mode_supported_p (scalar_mode mode)
 {
   /* -m32 does not support TImode.  This is the default, from
      default_scalar_mode_supported_p.  For -m32 -mpowerpc64 we want the
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3862c15..962f078 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1188,7 +1188,7 @@ s390_unwind_word_mode (void)
 
 /* Return true if the back end supports mode MODE.  */
 static bool
-s390_scalar_mode_supported_p (machine_mode mode)
+s390_scalar_mode_supported_p (scalar_mode mode)
 {
   /* In contrast to the default implementation reject TImode constants on 31bit
      TARGET_ZARCH for ABI compliance.  */
@@ -15204,7 +15204,7 @@ s390_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
 /* Return the vector mode to be used for inner mode MODE when doing
    vectorization.  */
 static machine_mode
-s390_preferred_simd_mode (machine_mode mode)
+s390_preferred_simd_mode (scalar_mode mode)
 {
   if (TARGET_VX)
     switch (mode)
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index e152d62..af548dc 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -637,7 +637,7 @@ static void sparc_conditional_register_usage (void);
 static const char *sparc_mangle_type (const_tree);
 #endif
 static void sparc_trampoline_init (rtx, tree, rtx);
-static machine_mode sparc_preferred_simd_mode (machine_mode);
+static machine_mode sparc_preferred_simd_mode (scalar_mode);
 static reg_class_t sparc_preferred_reload_class (rtx x, reg_class_t rclass);
 static bool sparc_lra_p (void);
 static bool sparc_print_operand_punct_valid_p (unsigned char);
@@ -7549,7 +7549,7 @@ sparc_vector_mode_supported_p (machine_mode mode)
 /* Implement the TARGET_VECTORIZE_PREFERRED_SIMD_MODE target hook.  */
 
 static machine_mode
-sparc_preferred_simd_mode (machine_mode mode)
+sparc_preferred_simd_mode (scalar_mode mode)
 {
   if (TARGET_VIS)
     switch (mode)
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 565533e..c6c2157 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -287,7 +287,7 @@ spu_option_override (void)
    be manipulated in non-trivial ways.  In particular, this means all
    the arithmetic is supported.  */
 static bool
-spu_scalar_mode_supported_p (machine_mode mode)
+spu_scalar_mode_supported_p (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 9705e23..2cd2607 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -106,7 +106,7 @@ tilegx_option_override (void)
 
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
 static bool
-tilegx_scalar_mode_supported_p (machine_mode mode)
+tilegx_scalar_mode_supported_p (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index c63c348..a4f3ba8 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -83,7 +83,7 @@ tilepro_option_override (void)
 
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
 static bool
-tilepro_scalar_mode_supported_p (machine_mode mode)
+tilepro_scalar_mode_supported_p (scalar_mode mode)
 {
   switch (mode)
     {
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 5073f35..0fdd025 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -56,9 +56,11 @@ struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
 class machine_mode;
+class scalar_mode;
 class scalar_int_mode;
 class scalar_float_mode;
 template<typename> class opt_mode;
+typedef opt_mode<scalar_mode> opt_scalar_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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 68fe19e..9afa4d0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4866,8 +4866,8 @@ cp_build_binary_op (location_t location,
 	    }
 
 	  /* Always construct signed integer vector type.  */
-	  intt = c_common_type_for_size (GET_MODE_BITSIZE
-					   (TYPE_MODE (TREE_TYPE (type0))), 0);
+	  intt = c_common_type_for_size
+	    (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type0))), 0);
 	  if (!intt)
 	    {
 	      if (complain & tf_error)
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cc747ea..3d77184 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4204,7 +4204,7 @@ hook returns true for both @code{ptr_mode} and @code{Pmode}.
 Define this to return nonzero if the memory reference @var{ref}  may alias with the system C library errno location.  The default  version of this hook assumes the system C library errno location  is either a declaration of type int or accessed by dereferencing  a pointer to int.
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (machine_mode @var{mode})
+@deftypefn {Target Hook} bool TARGET_SCALAR_MODE_SUPPORTED_P (scalar_mode @var{mode})
 Define this to return nonzero if the port is prepared to handle
 insns involving scalar mode @var{mode}.  For a scalar mode to be
 considered supported, all the basic arithmetic and comparisons
@@ -5787,7 +5787,7 @@ the elements in the vectors should be of type @var{type}.  @var{is_packed}
 parameter is true if the memory access is defined in a packed struct.
 @end deftypefn
 
-@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_PREFERRED_SIMD_MODE (machine_mode @var{mode})
+@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_PREFERRED_SIMD_MODE (scalar_mode @var{mode})
 This hook should return the preferred mode for vectorizing scalar
 mode @var{mode}.  The default is
 equal to @code{word_mode}, because the vectorizer can do some
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ae75e57..f4d8b1b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15665,10 +15665,11 @@ loc_descriptor (rtx rtl, machine_mode mode,
 	     or a floating-point constant.  A CONST_DOUBLE is used whenever
 	     the constant requires more than one word in order to be
 	     adequately represented.  We output CONST_DOUBLEs as blocks.  */
+	  scalar_mode smode = as_a <scalar_mode> (mode);
 	  loc_result = new_loc_descr (DW_OP_implicit_value,
-				      GET_MODE_SIZE (mode), 0);
+				      GET_MODE_SIZE (smode), 0);
 #if TARGET_SUPPORTS_WIDE_INT == 0
-	  if (!SCALAR_FLOAT_MODE_P (mode))
+	  if (!SCALAR_FLOAT_MODE_P (smode))
 	    {
 	      loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
 	      loc_result->dw_loc_oprnd2.v.val_double
@@ -15677,7 +15678,7 @@ loc_descriptor (rtx rtl, machine_mode mode,
 	  else
 #endif
 	    {
-	      unsigned int length = GET_MODE_SIZE (mode);
+	      unsigned int length = GET_MODE_SIZE (smode);
 	      unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
 	      insert_float (rtl, array);
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 7267d06..b90751c 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -599,7 +599,8 @@ rtx
 immed_wide_int_const (const wide_int_ref &v, machine_mode mode)
 {
   unsigned int len = v.get_len ();
-  unsigned int prec = GET_MODE_PRECISION (mode);
+  /* Not scalar_int_mode because we also allow pointer bound modes.  */
+  unsigned int prec = GET_MODE_PRECISION (as_a <scalar_mode> (mode));
 
   /* Allow truncation but not extension since we do not know if the
      number is signed or unsigned.  */
@@ -659,18 +660,10 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, machine_mode mode)
         (i.e., i1 consists only from copies of the sign bit, and sign
 	of i0 and i1 are the same), then we return a CONST_INT for i0.
      3) Otherwise, we create a CONST_DOUBLE for i0 and i1.  */
-  if (mode != VOIDmode)
-    {
-      gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
-		  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
-		  /* We can get a 0 for an error mark.  */
-		  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-		  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
-		  || GET_MODE_CLASS (mode) == MODE_POINTER_BOUNDS);
-
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-	return gen_int_mode (i0, mode);
-    }
+  scalar_mode smode;
+  if (is_a <scalar_mode> (mode, &smode)
+      && GET_MODE_BITSIZE (smode) <= HOST_BITS_PER_WIDE_INT)
+    return gen_int_mode (i0, mode);
 
   /* If this integer fits in one word, return a CONST_INT.  */
   if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0))
@@ -5867,6 +5860,7 @@ init_emit_once (void)
   int i;
   machine_mode mode;
   scalar_float_mode double_mode;
+  opt_scalar_mode smode_iter;
 
   /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
      CONST_FIXED, and memory attribute hash tables.  */
@@ -5981,62 +5975,66 @@ init_emit_once (void)
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_FRACT)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_FRACT)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST0 (mode), mode);
+      scalar_mode smode = *smode_iter;
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_UFRACT)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_UFRACT)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST0 (mode), mode);
+      scalar_mode smode = *smode_iter;
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_ACCUM)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_ACCUM)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST0 (mode), mode);
+      scalar_mode smode = *smode_iter;
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
 
       /* We store the value 1.  */
-      FCONST1 (mode).data.high = 0;
-      FCONST1 (mode).data.low = 0;
-      FCONST1 (mode).mode = mode;
-      FCONST1 (mode).data
-	= double_int_one.lshift (GET_MODE_FBIT (mode),
+      FCONST1 (smode).data.high = 0;
+      FCONST1 (smode).data.low = 0;
+      FCONST1 (smode).mode = smode;
+      FCONST1 (smode).data
+	= double_int_one.lshift (GET_MODE_FBIT (smode),
 				 HOST_BITS_PER_DOUBLE_INT,
-				 SIGNED_FIXED_POINT_MODE_P (mode));
-      const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST1 (mode), mode);
+				 SIGNED_FIXED_POINT_MODE_P (smode));
+      const_tiny_rtx[1][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST1 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_UACCUM)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_UACCUM)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST0 (mode), mode);
+      scalar_mode smode = *smode_iter;
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
 
       /* We store the value 1.  */
-      FCONST1 (mode).data.high = 0;
-      FCONST1 (mode).data.low = 0;
-      FCONST1 (mode).mode = mode;
-      FCONST1 (mode).data
-	= double_int_one.lshift (GET_MODE_FBIT (mode),
+      FCONST1 (smode).data.high = 0;
+      FCONST1 (smode).data.low = 0;
+      FCONST1 (smode).mode = smode;
+      FCONST1 (smode).data
+	= double_int_one.lshift (GET_MODE_FBIT (smode),
 				 HOST_BITS_PER_DOUBLE_INT,
-				 SIGNED_FIXED_POINT_MODE_P (mode));
-      const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-				      FCONST1 (mode), mode);
+				 SIGNED_FIXED_POINT_MODE_P (smode));
+      const_tiny_rtx[1][(int) smode]
+	= CONST_FIXED_FROM_FIXED_VALUE (FCONST1 (smode), smode);
     }
 
   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FRACT)
@@ -6069,10 +6067,11 @@ init_emit_once (void)
   if (STORE_FLAG_VALUE == 1)
     const_tiny_rtx[1][(int) BImode] = const1_rtx;
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_POINTER_BOUNDS)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, 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);
+      scalar_mode smode = *smode_iter;
+      wide_int wi_zero = wi::zero (GET_MODE_PRECISION (smode));
+      const_tiny_rtx[0][smode] = immed_wide_int_const (wi_zero, smode);
     }
 
   pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
diff --git a/gcc/explow.c b/gcc/explow.c
index e615e5b..3b9435e 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -48,14 +48,16 @@ static rtx break_out_memory_refs (rtx);
 HOST_WIDE_INT
 trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode)
 {
-  int width = GET_MODE_PRECISION (mode);
+  /* Not scalar_int_mode because we also allow pointer bound modes.  */
+  scalar_mode smode = as_a <scalar_mode> (mode);
+  int width = GET_MODE_PRECISION (smode);
 
   /* You want to truncate to a _what_?  */
   gcc_assert (SCALAR_INT_MODE_P (mode)
 	      || POINTER_BOUNDS_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
-  if (mode == BImode)
+  if (smode == BImode)
     return c & 1 ? STORE_FLAG_VALUE : 0;
 
   /* Sign-extend for the requested mode.  */
@@ -784,6 +786,7 @@ promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode,
 #ifdef PROMOTE_MODE
   enum tree_code code;
   int unsignedp;
+  scalar_mode smode;
 #endif
 
   /* For libcalls this is invoked without TYPE from the backends
@@ -803,9 +806,11 @@ promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode,
     {
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
     case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
-      PROMOTE_MODE (mode, unsignedp, type);
+      /* Values of these types always have scalar mode.  */
+      smode = as_a <scalar_mode> (mode);
+      PROMOTE_MODE (smode, unsignedp, type);
       *punsignedp = unsignedp;
-      return mode;
+      return smode;
 
 #ifdef POINTERS_EXTEND_UNSIGNED
     case REFERENCE_TYPE:
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 2027d76..0eaf778 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -759,16 +759,16 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Use vec_set patterns for inserting parts of vectors whenever
      available.  */
-  if (VECTOR_MODE_P (GET_MODE (op0))
+  machine_mode outermode = GET_MODE (op0);
+  scalar_mode innermode = GET_MODE_INNER (outermode);
+  if (VECTOR_MODE_P (outermode)
       && !MEM_P (op0)
-      && optab_handler (vec_set_optab, GET_MODE (op0)) != CODE_FOR_nothing
-      && fieldmode == GET_MODE_INNER (GET_MODE (op0))
-      && bitsize == GET_MODE_UNIT_BITSIZE (GET_MODE (op0))
-      && !(bitnum % GET_MODE_UNIT_BITSIZE (GET_MODE (op0))))
+      && optab_handler (vec_set_optab, outermode) != CODE_FOR_nothing
+      && fieldmode == innermode
+      && bitsize == GET_MODE_BITSIZE (innermode)
+      && !(bitnum % GET_MODE_BITSIZE (innermode)))
     {
       struct expand_operand ops[3];
-      machine_mode outermode = GET_MODE (op0);
-      machine_mode innermode = GET_MODE_INNER (outermode);
       enum insn_code icode = optab_handler (vec_set_optab, outermode);
       int pos = bitnum / GET_MODE_BITSIZE (innermode);
 
@@ -1611,15 +1611,15 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Use vec_extract patterns for extracting parts of vectors whenever
      available.  */
-  if (VECTOR_MODE_P (GET_MODE (op0))
+  machine_mode outermode = GET_MODE (op0);
+  scalar_mode innermode = GET_MODE_INNER (outermode);
+  if (VECTOR_MODE_P (outermode)
       && !MEM_P (op0)
-      && optab_handler (vec_extract_optab, GET_MODE (op0)) != CODE_FOR_nothing
-      && ((bitnum + bitsize - 1) / GET_MODE_UNIT_BITSIZE (GET_MODE (op0))
-	  == bitnum / GET_MODE_UNIT_BITSIZE (GET_MODE (op0))))
+      && optab_handler (vec_extract_optab, outermode) != CODE_FOR_nothing
+      && ((bitnum + bitsize - 1) / GET_MODE_BITSIZE (innermode)
+	  == bitnum / GET_MODE_BITSIZE (innermode)))
     {
       struct expand_operand ops[3];
-      machine_mode outermode = GET_MODE (op0);
-      machine_mode innermode = GET_MODE_INNER (outermode);
       enum insn_code icode = optab_handler (vec_extract_optab, outermode);
       unsigned HOST_WIDE_INT pos = bitnum / GET_MODE_BITSIZE (innermode);
 
diff --git a/gcc/expr.c b/gcc/expr.c
index 2376d69..17abee5 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -100,6 +100,7 @@ static rtx const_vector_from_tree (tree);
 static rtx const_scalar_mask_from_tree (scalar_int_mode, tree);
 static tree tree_expr_size (const_tree);
 static HOST_WIDE_INT int_expr_size (tree);
+static void convert_mode_scalar (rtx, rtx, int);
 
 \f
 /* This is run to set up which modes can be used
@@ -214,17 +215,7 @@ convert_move (rtx to, rtx from, int unsignedp)
 {
   machine_mode to_mode = GET_MODE (to);
   machine_mode from_mode = GET_MODE (from);
-  int to_real = SCALAR_FLOAT_MODE_P (to_mode);
-  int from_real = SCALAR_FLOAT_MODE_P (from_mode);
-  enum insn_code code;
-  rtx libcall;
-
-  /* rtx code for making an equivalent value.  */
-  enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
-			      : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
 
-
-  gcc_assert (to_real == from_real);
   gcc_assert (to_mode != BLKmode);
   gcc_assert (from_mode != BLKmode);
 
@@ -275,6 +266,28 @@ convert_move (rtx to, rtx from, int unsignedp)
       return;
     }
 
+  convert_mode_scalar (to, from, unsignedp);
+}
+
+/* Like convert_move, but deals only with scalar modes.  */
+
+static void
+convert_mode_scalar (rtx to, rtx from, int unsignedp)
+{
+  /* Both modes should be scalar types.  */
+  scalar_mode from_mode = as_a <scalar_mode> (GET_MODE (from));
+  scalar_mode to_mode = as_a <scalar_mode> (GET_MODE (to));
+  bool to_real = SCALAR_FLOAT_MODE_P (to_mode);
+  bool from_real = SCALAR_FLOAT_MODE_P (from_mode);
+  enum insn_code code;
+  rtx libcall;
+
+  gcc_assert (to_real == from_real);
+
+  /* rtx code for making an equivalent value.  */
+  enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
+			      : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
+
   if (to_real)
     {
       rtx value;
@@ -411,7 +424,7 @@ convert_move (rtx to, rtx from, int unsignedp)
       rtx fill_value;
       rtx lowfrom;
       int i;
-      machine_mode lowpart_mode;
+      scalar_mode lowpart_mode;
       int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
 
       /* Try converting directly if the insn is supported.  */
@@ -544,23 +557,28 @@ convert_move (rtx to, rtx from, int unsignedp)
 	}
       else
 	{
-	  machine_mode intermediate;
+	  scalar_mode intermediate;
 	  rtx tmp;
 	  int shift_amount;
 
 	  /* Search for a mode to convert via.  */
-	  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)
-		     && TRULY_NOOP_TRUNCATION_MODES_P (to_mode, intermediate)))
-		&& (can_extend_p (intermediate, from_mode, unsignedp)
-		    != CODE_FOR_nothing))
-	      {
-		convert_move (to, convert_to_mode (intermediate, from,
-						   unsignedp), unsignedp);
-		return;
-	      }
+	  opt_scalar_mode intermediate_iter;
+	  FOR_EACH_MODE_FROM (intermediate_iter, from_mode)
+	    {
+	      scalar_mode intermediate = *intermediate_iter;
+	      if (((can_extend_p (to_mode, intermediate, unsignedp)
+		    != CODE_FOR_nothing)
+		   || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
+		       && TRULY_NOOP_TRUNCATION_MODES_P (to_mode,
+							 intermediate)))
+		  && (can_extend_p (intermediate, from_mode, unsignedp)
+		      != CODE_FOR_nothing))
+		{
+		  convert_move (to, convert_to_mode (intermediate, from,
+						     unsignedp), unsignedp);
+		  return;
+		}
+	    }
 
 	  /* No suitable intermediate mode.
 	     Generate what we need with	shifts.  */
@@ -3107,7 +3125,7 @@ void
 write_complex_part (rtx cplx, rtx val, bool imag_p)
 {
   machine_mode cmode;
-  machine_mode imode;
+  scalar_mode imode;
   unsigned ibitsize;
 
   if (GET_CODE (cplx) == CONCAT)
@@ -3168,7 +3186,8 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
 rtx
 read_complex_part (rtx cplx, bool imag_p)
 {
-  machine_mode cmode, imode;
+  machine_mode cmode;
+  scalar_mode imode;
   unsigned ibitsize;
 
   if (GET_CODE (cplx) == CONCAT)
@@ -3364,7 +3383,7 @@ emit_move_resolve_push (machine_mode mode, rtx x)
 rtx_insn *
 emit_move_complex_push (machine_mode mode, rtx x, rtx y)
 {
-  machine_mode submode = GET_MODE_INNER (mode);
+  scalar_mode submode = GET_MODE_INNER (mode);
   bool imag_first;
 
 #ifdef PUSH_ROUNDING
@@ -7764,7 +7783,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, scalar_int_mode tmode,
 	 The expression is therefore always offset by the size of the
 	 scalar type.  */
       offset = 0;
-      bitpos = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)));
+      bitpos = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (exp)));
       inner = TREE_OPERAND (exp, 0);
       break;
 
@@ -9261,7 +9280,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 				      GET_MODE_INNER (GET_MODE (target)), 0);
 	    if (reg_overlap_mentioned_p (temp, op1))
 	      {
-		machine_mode imode = GET_MODE_INNER (GET_MODE (target));
+		scalar_mode imode = GET_MODE_INNER (GET_MODE (target));
 		temp = adjust_address_nv (target, imode,
 					  GET_MODE_SIZE (imode));
 		if (reg_overlap_mentioned_p (temp, op0))
@@ -9368,7 +9387,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 	{
 	  tree sel_type = TREE_TYPE (treeop2);
 	  machine_mode vmode
-	    = mode_for_vector (TYPE_MODE (TREE_TYPE (sel_type)),
+	    = mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),
 			       TYPE_VECTOR_SUBPARTS (sel_type));
 	  gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
 	  op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
diff --git a/gcc/fixed-value.c b/gcc/fixed-value.c
index ddb8ee1..20c5974 100644
--- a/gcc/fixed-value.c
+++ b/gcc/fixed-value.c
@@ -86,7 +86,7 @@ check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, machine_mode mode)
    The bits in PAYLOAD are sign-extended/zero-extended according to MODE.  */
 
 FIXED_VALUE_TYPE
-fixed_from_double_int (double_int payload, machine_mode mode)
+fixed_from_double_int (double_int payload, scalar_mode mode)
 {
   FIXED_VALUE_TYPE value;
 
@@ -108,7 +108,7 @@ fixed_from_double_int (double_int payload, machine_mode mode)
 /* Initialize from a decimal or hexadecimal string.  */
 
 void
-fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, machine_mode mode)
+fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, scalar_mode mode)
 {
   REAL_VALUE_TYPE real_value, fixed_value, base_value;
   unsigned int fbit;
@@ -803,7 +803,7 @@ fixed_compare (int icode, const FIXED_VALUE_TYPE *op0,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert (FIXED_VALUE_TYPE *f, machine_mode mode,
+fixed_convert (FIXED_VALUE_TYPE *f, scalar_mode mode,
                const FIXED_VALUE_TYPE *a, bool sat_p)
 {
   bool overflow_p = false;
@@ -947,7 +947,7 @@ fixed_convert (FIXED_VALUE_TYPE *f, machine_mode mode,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert_from_int (FIXED_VALUE_TYPE *f, machine_mode mode,
+fixed_convert_from_int (FIXED_VALUE_TYPE *f, scalar_mode mode,
 			double_int a, bool unsigned_p, bool sat_p)
 {
   bool overflow_p = false;
@@ -1031,7 +1031,7 @@ fixed_convert_from_int (FIXED_VALUE_TYPE *f, machine_mode mode,
    Return true, if !SAT_P and overflow.  */
 
 bool
-fixed_convert_from_real (FIXED_VALUE_TYPE *f, machine_mode mode,
+fixed_convert_from_real (FIXED_VALUE_TYPE *f, scalar_mode mode,
 			 const REAL_VALUE_TYPE *a, bool sat_p)
 {
   bool overflow_p = false;
@@ -1090,7 +1090,7 @@ fixed_convert_from_real (FIXED_VALUE_TYPE *f, machine_mode mode,
 /* Convert to a new real mode from a fixed-point.  */
 
 void
-real_convert_from_fixed (REAL_VALUE_TYPE *r, machine_mode mode,
+real_convert_from_fixed (REAL_VALUE_TYPE *r, scalar_mode mode,
 			 const FIXED_VALUE_TYPE *f)
 {
   REAL_VALUE_TYPE base_value, fixed_value, real_value;
diff --git a/gcc/fixed-value.h b/gcc/fixed-value.h
index d0d7e63..78df6e6 100644
--- a/gcc/fixed-value.h
+++ b/gcc/fixed-value.h
@@ -47,14 +47,13 @@ extern rtx const_fixed_from_fixed_value (FIXED_VALUE_TYPE, machine_mode);
 
 /* Construct a FIXED_VALUE from a bit payload and machine mode MODE.
    The bits in PAYLOAD are sign-extended/zero-extended according to MODE.  */
-extern FIXED_VALUE_TYPE fixed_from_double_int (double_int,
-						     machine_mode);
+extern FIXED_VALUE_TYPE fixed_from_double_int (double_int, scalar_mode);
 
 /* Return a CONST_FIXED from a bit payload and machine mode MODE.
    The bits in PAYLOAD are sign-extended/zero-extended according to MODE.  */
 static inline rtx
 const_fixed_from_double_int (double_int payload,
-                             machine_mode mode)
+			     scalar_mode mode)
 {
   return
     const_fixed_from_fixed_value (fixed_from_double_int (payload, mode),
@@ -63,25 +62,25 @@ const_fixed_from_double_int (double_int payload,
 
 /* Initialize from a decimal or hexadecimal string.  */
 extern void fixed_from_string (FIXED_VALUE_TYPE *, const char *,
-			       machine_mode);
+			       scalar_mode);
 
 /* In tree.c: wrap up a FIXED_VALUE_TYPE in a tree node.  */
 extern tree build_fixed (tree, FIXED_VALUE_TYPE);
 
 /* Extend or truncate to a new mode.  */
-extern bool fixed_convert (FIXED_VALUE_TYPE *, machine_mode,
+extern bool fixed_convert (FIXED_VALUE_TYPE *, scalar_mode,
 			   const FIXED_VALUE_TYPE *, bool);
 
 /* Convert to a fixed-point mode from an integer.  */
-extern bool fixed_convert_from_int (FIXED_VALUE_TYPE *, machine_mode,
+extern bool fixed_convert_from_int (FIXED_VALUE_TYPE *, scalar_mode,
 				    double_int, bool, bool);
 
 /* Convert to a fixed-point mode from a real.  */
-extern bool fixed_convert_from_real (FIXED_VALUE_TYPE *, machine_mode,
+extern bool fixed_convert_from_real (FIXED_VALUE_TYPE *, scalar_mode,
 				     const REAL_VALUE_TYPE *, bool);
 
 /* Convert to a real mode from a fixed-point.  */
-extern void real_convert_from_fixed (REAL_VALUE_TYPE *, machine_mode,
+extern void real_convert_from_fixed (REAL_VALUE_TYPE *, scalar_mode,
 				     const FIXED_VALUE_TYPE *);
 
 /* Compare two fixed-point objects for bitwise identity.  */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d9ee4fb..3876883 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2025,8 +2025,8 @@ fold_convert_const_fixed_from_fixed (tree type, const_tree arg1)
   tree t;
   bool overflow_p;
 
-  overflow_p = fixed_convert (&value, TYPE_MODE (type), &TREE_FIXED_CST (arg1),
-			      TYPE_SATURATING (type));
+  overflow_p = fixed_convert (&value, SCALAR_TYPE_MODE (type),
+			      &TREE_FIXED_CST (arg1), TYPE_SATURATING (type));
   t = build_fixed (type, value);
 
   /* Propagate overflow flags.  */
@@ -2054,7 +2054,7 @@ fold_convert_const_fixed_from_int (tree type, const_tree arg1)
   else
     di.high = TREE_INT_CST_ELT (arg1, 1);
 
-  overflow_p = fixed_convert_from_int (&value, TYPE_MODE (type), di,
+  overflow_p = fixed_convert_from_int (&value, SCALAR_TYPE_MODE (type), di,
 				       TYPE_UNSIGNED (TREE_TYPE (arg1)),
 				       TYPE_SATURATING (type));
   t = build_fixed (type, value);
@@ -2075,7 +2075,7 @@ fold_convert_const_fixed_from_real (tree type, const_tree arg1)
   tree t;
   bool overflow_p;
 
-  overflow_p = fixed_convert_from_real (&value, TYPE_MODE (type),
+  overflow_p = fixed_convert_from_real (&value, SCALAR_TYPE_MODE (type),
 					&TREE_REAL_CST (arg1),
 					TYPE_SATURATING (type));
   t = build_fixed (type, value);
@@ -6940,7 +6940,7 @@ static int
 native_encode_fixed (const_tree expr, unsigned char *ptr, int len, int off)
 {
   tree type = TREE_TYPE (expr);
-  machine_mode mode = TYPE_MODE (type);
+  scalar_mode mode = SCALAR_TYPE_MODE (type);
   int total_bytes = GET_MODE_SIZE (mode);
   FIXED_VALUE_TYPE value;
   tree i_value, i_type;
@@ -7042,7 +7042,7 @@ native_encode_complex (const_tree expr, unsigned char *ptr, int len, int off)
     return 0;
   part = TREE_IMAGPART (expr);
   if (off != -1)
-    off = MAX (0, off - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (part))));
+    off = MAX (0, off - GET_MODE_SIZE (SCALAR_TYPE_MODE (TREE_TYPE (part))));
   isize = native_encode_expr (part, ptr+rsize, len-rsize, off);
   if (off == -1
       && isize != rsize)
@@ -7066,7 +7066,7 @@ native_encode_vector (const_tree expr, unsigned char *ptr, int len, int off)
   offset = 0;
   count = VECTOR_CST_NELTS (expr);
   itype = TREE_TYPE (TREE_TYPE (expr));
-  size = GET_MODE_SIZE (TYPE_MODE (itype));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (itype));
   for (i = 0; i < count; i++)
     {
       if (off >= size)
@@ -7194,7 +7194,8 @@ native_interpret_int (tree type, const unsigned char *ptr, int len)
 static tree
 native_interpret_fixed (tree type, const unsigned char *ptr, int len)
 {
-  int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
+  scalar_mode mode = SCALAR_TYPE_MODE (type);
+  int total_bytes = GET_MODE_SIZE (mode);
   double_int result;
   FIXED_VALUE_TYPE fixed_value;
 
@@ -7203,7 +7204,7 @@ native_interpret_fixed (tree type, const unsigned char *ptr, int len)
     return NULL_TREE;
 
   result = double_int::from_buffer (ptr, total_bytes);
-  fixed_value = fixed_from_double_int (result, TYPE_MODE (type));
+  fixed_value = fixed_from_double_int (result, mode);
 
   return build_fixed (type, fixed_value);
 }
@@ -7225,7 +7226,6 @@ native_interpret_real (tree type, const unsigned char *ptr, int len)
   REAL_VALUE_TYPE r;
   long tmp[6];
 
-  total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
   if (total_bytes > len || total_bytes > 24)
     return NULL_TREE;
   int words = (32 / BITS_PER_UNIT) / UNITS_PER_WORD;
@@ -7280,7 +7280,7 @@ native_interpret_complex (tree type, const unsigned char *ptr, int len)
   int size;
 
   etype = TREE_TYPE (type);
-  size = GET_MODE_SIZE (TYPE_MODE (etype));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
   if (size * 2 > len)
     return NULL_TREE;
   rpart = native_interpret_expr (etype, ptr, size);
@@ -7305,7 +7305,7 @@ native_interpret_vector (tree type, const unsigned char *ptr, int len)
   tree *elements;
 
   etype = TREE_TYPE (type);
-  size = GET_MODE_SIZE (TYPE_MODE (etype));
+  size = GET_MODE_SIZE (SCALAR_TYPE_MODE (etype));
   count = TYPE_VECTOR_SUBPARTS (type);
   if (size * count > len)
     return NULL_TREE;
diff --git a/gcc/function.c b/gcc/function.c
index 8a887e4..7da0203 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -3371,8 +3371,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
       /* Mark complex types separately.  */
       if (GET_CODE (parmreg) == CONCAT)
 	{
-	  machine_mode submode
-	    = GET_MODE_INNER (GET_MODE (parmreg));
+	  scalar_mode submode = GET_MODE_INNER (GET_MODE (parmreg));
 	  int regnor = REGNO (XEXP (parmreg, 0));
 	  int regnoi = REGNO (XEXP (parmreg, 1));
 	  rtx stackr = adjust_address_nv (data->stack_parm, submode, 0);
@@ -3509,7 +3508,7 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all,
 	  && targetm.calls.split_complex_arg (TREE_TYPE (parm)))
 	{
 	  rtx tmp, real, imag;
-	  machine_mode inner = GET_MODE_INNER (DECL_MODE (parm));
+	  scalar_mode inner = GET_MODE_INNER (DECL_MODE (parm));
 
 	  real = DECL_RTL (fnargs[i]);
 	  imag = DECL_RTL (fnargs[i + 1]);
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 8ee0fae6..4f10632 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1141,6 +1141,13 @@ get_mode_class (struct mode_data *mode)
     case MODE_PARTIAL_INT:
       return "scalar_int_mode";
 
+    case MODE_FRACT:
+    case MODE_UFRACT:
+    case MODE_ACCUM:
+    case MODE_UACCUM:
+    case MODE_POINTER_BOUNDS:
+      return "scalar_mode";
+
     case MODE_FLOAT:
     case MODE_DECIMAL_FLOAT:
       return "scalar_float_mode";
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 696f3c9..1dae146 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -381,6 +381,58 @@ scalar_float_mode::from_int (int i)
   return machine_mode_enum (i);
 }
 
+/* Represents a machine mode that is known to be scalar.  All properties
+   (size, precision, etc.) are compile-time constants.  */
+class scalar_mode
+{
+public:
+  ALWAYS_INLINE scalar_mode () {}
+  ALWAYS_INLINE scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
+  ALWAYS_INLINE scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
+  ALWAYS_INLINE scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+
+  static bool includes_p (machine_mode_enum);
+  static scalar_mode from_int (int);
+
+PROTECT_ENUM_CONVERSION:
+  ALWAYS_INLINE scalar_mode (machine_mode_enum m) : m_mode (m) {}
+
+protected:
+  machine_mode_enum m_mode;
+};
+
+/* Return true if M represents some kind of scalar value.  */
+
+inline bool
+scalar_mode::includes_p (machine_mode_enum m)
+{
+  switch (GET_MODE_CLASS (m))
+    {
+    case MODE_INT:
+    case MODE_PARTIAL_INT:
+    case MODE_FRACT:
+    case MODE_UFRACT:
+    case MODE_ACCUM:
+    case MODE_UACCUM:
+    case MODE_FLOAT:
+    case MODE_DECIMAL_FLOAT:
+    case MODE_POINTER_BOUNDS:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* Return M as a scalar_mode.  This function should only be used by
+   utility functions; general code should use as_a<T> instead.  */
+
+ALWAYS_INLINE scalar_mode
+scalar_mode::from_int (int i)
+{
+  return machine_mode_enum (i);
+}
+
 /* Represents a general machine mode (scalar or non-scalar).  */
 class machine_mode
 {
@@ -434,14 +486,14 @@ mode_to_precision (machine_mode_enum mode)
 
 /* Return the base GET_MODE_NUNITS value for MODE.  */
 
-ALWAYS_INLINE machine_mode
+ALWAYS_INLINE scalar_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]);
+  return scalar_mode::from_int (__builtin_constant_p (mode) ?
+				mode_inner_inline (mode) : mode_inner[mode]);
 #else
-  return (machine_mode_enum) mode_inner[mode];
+  return scalar_mode::from_int (mode_inner[mode]);
 #endif
 }
 
@@ -609,7 +661,7 @@ extern machine_mode bitwise_mode_for_mode (machine_mode);
 /* Return a mode that is suitable for representing a vector,
    or BLKmode on failure.  */
 
-extern machine_mode mode_for_vector (machine_mode, unsigned);
+extern machine_mode mode_for_vector (scalar_mode, unsigned);
 
 /* A class for iterating through possible bitfield modes.  */
 class bit_field_mode_iterator
@@ -713,6 +765,21 @@ is_int_mode (machine_mode mode, T *int_mode)
   return false;
 }
 
+/* Return true if MODE has class MODE_FLOAT, storing it as a
+   scalar_float_mode in *FLOAT_MODE if so.  */
+
+template<typename T>
+inline bool
+is_float_mode (machine_mode mode, T *float_mode)
+{
+  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+    {
+      *float_mode = scalar_float_mode::from_int (mode);
+      return true;
+    }
+  return false;
+}
+
 namespace mode_iterator
 {
   /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */
@@ -777,6 +844,13 @@ namespace mode_iterator
   /* Set mode iterator *ITER to the mode that is two times wider than the
      current one, if such a mode exists.  */
 
+  template<typename T>
+  inline void
+  get_2xwider (opt_mode<T> *iter)
+  {
+    *iter = GET_MODE_2XWIDER_MODE (**iter);
+  }
+
   inline void
   get_2xwider (machine_mode *iter)
   {
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 13f3435..f9b2e88 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4300,16 +4300,18 @@ omp_clause_aligned_alignment (tree clause)
 
   /* Otherwise return implementation defined alignment.  */
   unsigned int al = 1;
-  machine_mode mode, vmode;
+  opt_scalar_mode mode_iter;
   int vs = targetm.vectorize.autovectorize_vector_sizes ();
   if (vs)
     vs = 1 << floor_log2 (vs);
   static enum mode_class classes[]
     = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
   for (int i = 0; i < 4; i += 2)
-    FOR_EACH_MODE_IN_CLASS (mode, classes[i])
+    /* The for loop above dictates that we only walk through scalar classes.  */
+    FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
       {
-	vmode = targetm.vectorize.preferred_simd_mode (mode);
+	scalar_mode mode = *mode_iter;
+	machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
 	if (GET_MODE_CLASS (vmode) != classes[i + 1])
 	  continue;
 	while (vs
@@ -12781,18 +12783,20 @@ expand_omp_atomic (struct omp_region *region)
       /* __sync builtins require strict data alignment.  */
       if (exact_log2 (align) >= index)
 	{
+	  scalar_mode mode;
+
 	  /* Atomic load.  */
 	  if (loaded_val == stored_val
-	      && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
-		  || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
-	      && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+	      && (is_int_mode (TYPE_MODE (type), &mode)
+		  || is_float_mode (TYPE_MODE (type), &mode))
+	      && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD
 	      && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
 	    return;
 
 	  /* Atomic store.  */
-	  if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
-	       || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
-	      && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
+	  if ((is_int_mode (TYPE_MODE (type), &mode)
+	       || is_float_mode (TYPE_MODE (type), &mode))
+	      && GET_MODE_BITSIZE (mode) <= BITS_PER_WORD
 	      && store_bb == single_succ (load_bb)
 	      && first_stmt (store_bb) == store
 	      && expand_omp_atomic_store (load_bb, addr, loaded_val,
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index 7b8d2a9..5e5b006 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -496,7 +496,7 @@ simd_clone_adjust_return_type (struct cgraph_node *node)
     veclen = node->simdclone->vecsize_int;
   else
     veclen = node->simdclone->vecsize_float;
-  veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
+  veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t));
   if (veclen > node->simdclone->simdlen)
     veclen = node->simdclone->simdlen;
   if (POINTER_TYPE_P (t))
@@ -606,7 +606,7 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
 	    veclen = sc->vecsize_int;
 	  else
 	    veclen = sc->vecsize_float;
-	  veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
+	  veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type));
 	  if (veclen > sc->simdlen)
 	    veclen = sc->simdlen;
 	  adj.arg_prefix = "simd";
@@ -650,7 +650,7 @@ simd_clone_adjust_argument_types (struct cgraph_node *node)
 	veclen = sc->vecsize_int;
       else
 	veclen = sc->vecsize_float;
-      veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
+      veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type));
       if (veclen > sc->simdlen)
 	veclen = sc->simdlen;
       if (sc->mask_mode != VOIDmode)
@@ -792,8 +792,8 @@ simd_clone_init_simd_arrays (struct cgraph_node *node,
 		  arg = DECL_CHAIN (arg);
 		  j++;
 		}
-	      elemsize
-		= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
+	      tree elemtype = TREE_TYPE (TREE_TYPE (arg));
+	      elemsize = GET_MODE_SIZE (SCALAR_TYPE_MODE (elemtype));
 	      tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
 			       build_int_cst (ptype, k * elemsize));
 	      t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
@@ -1227,7 +1227,7 @@ simd_clone_adjust (struct cgraph_node *node)
 			      mask_array, iter1, NULL, NULL);
 	  g = gimple_build_assign (mask, aref);
 	  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-	  int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
+	  int bitsize = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (aref)));
 	  if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
 	    {
 	      aref = build1 (VIEW_CONVERT_EXPR,
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index 6541f07..4d1510f 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -524,7 +524,11 @@ can_vec_mask_load_store_p (machine_mode mode,
 
   /* See if there is any chance the mask load or store might be
      vectorized.  If not, punt.  */
-  vmode = targetm.vectorize.preferred_simd_mode (mode);
+  scalar_mode smode;
+  if (!is_a <scalar_mode> (mode, &smode))
+    return false;
+
+  vmode = targetm.vectorize.preferred_simd_mode (smode);
   if (!VECTOR_MODE_P (vmode))
     return false;
 
@@ -541,9 +545,9 @@ can_vec_mask_load_store_p (machine_mode mode,
     {
       unsigned int cur = 1 << floor_log2 (vector_sizes);
       vector_sizes &= ~cur;
-      if (cur <= GET_MODE_SIZE (mode))
+      if (cur <= GET_MODE_SIZE (smode))
 	continue;
-      vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
+      vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));
       mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
 						   cur);
       if (VECTOR_MODE_P (vmode)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 6aa5de1..55beb22 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1228,7 +1228,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
 	{
 	  /* The scalar may have been extended to be too wide.  Truncate
 	     it back to the proper size to fit in the broadcast vector.  */
-	  machine_mode inner_mode = GET_MODE_INNER (mode);
+	  scalar_mode inner_mode = GET_MODE_INNER (mode);
 	  if (!CONST_INT_P (op1)
 	      && (GET_MODE_BITSIZE (as_a <scalar_int_mode> (GET_MODE (op1)))
 		  > GET_MODE_BITSIZE (inner_mode)))
@@ -4612,6 +4612,7 @@ expand_float (rtx to, rtx from, int unsignedp)
 {
   enum insn_code icode;
   rtx target = to;
+  scalar_mode from_mode, to_mode;
   machine_mode fmode, imode;
   bool can_do_signed = false;
 
@@ -4661,8 +4662,12 @@ expand_float (rtx to, rtx from, int unsignedp)
 
   /* Unsigned integer, and no way to convert directly.  Convert as signed,
      then unconditionally adjust the result.  */
-  if (unsignedp && can_do_signed)
+  if (unsignedp
+      && can_do_signed
+      && is_a <scalar_mode> (GET_MODE (to), &to_mode)
+      && is_a <scalar_mode> (GET_MODE (from), &from_mode))
     {
+      opt_scalar_mode fmode_iter;
       rtx_code_label *label = gen_label_rtx ();
       rtx temp;
       REAL_VALUE_TYPE offset;
@@ -4671,19 +4676,21 @@ 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_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)
+      FOR_EACH_MODE_FROM (fmode_iter, to_mode)
+	if (GET_MODE_PRECISION (from_mode) < GET_MODE_BITSIZE (*fmode_iter)
+	    && can_float_p (*fmode_iter, from_mode, 0) != CODE_FOR_nothing)
 	  break;
 
-      if (fmode == VOIDmode)
+      if (fmode_iter.exists ())
+	fmode = *fmode_iter;
+      else
 	{
 	  /* There is no such mode.  Pretend the target is wide enough.  */
-	  fmode = GET_MODE (to);
+	  fmode = to_mode;
 
 	  /* Avoid double-rounding when TO is narrower than FROM.  */
 	  if ((significand_size (fmode) + 1)
-	      < GET_MODE_PRECISION (GET_MODE (from)))
+	      < GET_MODE_PRECISION (from_mode))
 	    {
 	      rtx temp1;
 	      rtx_code_label *neglabel = gen_label_rtx ();
@@ -4695,7 +4702,7 @@ expand_float (rtx to, rtx from, int unsignedp)
 		  || GET_MODE (target) != fmode)
 		target = gen_reg_rtx (fmode);
 
-	      imode = GET_MODE (from);
+	      imode = from_mode;
 	      do_pending_stack_adjust ();
 
 	      /* Test whether the sign bit is set.  */
@@ -4735,7 +4742,7 @@ expand_float (rtx to, rtx from, int unsignedp)
       /* If we are about to do some arithmetic to correct for an
 	 unsigned operand, do it in a pseudo-register.  */
 
-      if (GET_MODE (to) != fmode
+      if (to_mode != fmode
 	  || !REG_P (to) || REGNO (to) < FIRST_PSEUDO_REGISTER)
 	target = gen_reg_rtx (fmode);
 
@@ -4746,11 +4753,11 @@ expand_float (rtx to, rtx from, int unsignedp)
 	 correct its value by 2**bitwidth.  */
 
       do_pending_stack_adjust ();
-      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
+      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, from_mode,
 			       0, label);
 
 
-      real_2expN (&offset, GET_MODE_PRECISION (GET_MODE (from)), fmode);
+      real_2expN (&offset, GET_MODE_PRECISION (from_mode), fmode);
       temp = expand_binop (fmode, add_optab, target,
 			   const_double_from_real_value (offset, fmode),
 			   target, 0, OPTAB_LIB_WIDEN);
@@ -4811,6 +4818,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
   enum insn_code icode;
   rtx target = to;
   machine_mode fmode, imode;
+  opt_scalar_mode fmode_iter;
   bool must_trunc = false;
 
   /* We first try to find a pair of modes, one real and one integer, at
@@ -4878,67 +4886,74 @@ expand_fix (rtx to, rtx from, int unsignedp)
      2^63.  The subtraction of 2^63 should not generate any rounding as it
      simply clears out that bit.  The rest is trivial.  */
 
-  if (unsignedp && GET_MODE_PRECISION (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
-    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))))
-	{
-	  int bitsize;
-	  REAL_VALUE_TYPE offset;
-	  rtx limit;
-	  rtx_code_label *lab1, *lab2;
-	  rtx_insn *insn;
-
-	  bitsize = GET_MODE_PRECISION (GET_MODE (to));
-	  real_2expN (&offset, bitsize - 1, fmode);
-	  limit = const_double_from_real_value (offset, fmode);
-	  lab1 = gen_label_rtx ();
-	  lab2 = gen_label_rtx ();
-
-	  if (fmode != GET_MODE (from))
-	    from = convert_to_mode (fmode, from, 0);
-
-	  /* See if we need to do the subtraction.  */
-	  do_pending_stack_adjust ();
-	  emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
-				   0, lab1);
-
-	  /* If not, do the signed "fix" and branch around fixup code.  */
-	  expand_fix (to, from, 0);
-	  emit_jump_insn (targetm.gen_jump (lab2));
-	  emit_barrier ();
-
-	  /* Otherwise, subtract 2**(N-1), convert to signed number,
-	     then add 2**(N-1).  Do the addition using XOR since this
-	     will often generate better code.  */
-	  emit_label (lab1);
-	  target = expand_binop (GET_MODE (from), sub_optab, from, limit,
-				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
-	  expand_fix (to, target, 0);
-	  target = expand_binop (GET_MODE (to), xor_optab, to,
-				 gen_int_mode
-				 (HOST_WIDE_INT_1 << (bitsize - 1),
-				  GET_MODE (to)),
-				 to, 1, OPTAB_LIB_WIDEN);
-
-	  if (target != to)
-	    emit_move_insn (to, target);
-
-	  emit_label (lab2);
-
-	  if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
-	    {
-	      /* Make a place for a REG_NOTE and add it.  */
-	      insn = emit_move_insn (to, to);
-	      set_dst_reg_note (insn, REG_EQUAL,
-				gen_rtx_fmt_e (UNSIGNED_FIX, GET_MODE (to),
-					       copy_rtx (from)),
-				to);
-	    }
+  scalar_int_mode to_mode;
+  if (unsignedp
+      && is_a <scalar_int_mode> (GET_MODE (to), &to_mode)
+      && HWI_COMPUTABLE_MODE_P (to_mode))
+    FOR_EACH_MODE_FROM (fmode_iter, as_a <scalar_mode> (GET_MODE (from)))
+      {
+	scalar_mode fmode = *fmode_iter;
+	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 (to_mode))))
+	  {
+	    int bitsize;
+	    REAL_VALUE_TYPE offset;
+	    rtx limit;
+	    rtx_code_label *lab1, *lab2;
+	    rtx_insn *insn;
+
+	    bitsize = GET_MODE_PRECISION (to_mode);
+	    real_2expN (&offset, bitsize - 1, fmode);
+	    limit = const_double_from_real_value (offset, fmode);
+	    lab1 = gen_label_rtx ();
+	    lab2 = gen_label_rtx ();
 
-	  return;
-	}
+	    if (fmode != GET_MODE (from))
+	      from = convert_to_mode (fmode, from, 0);
+
+	    /* See if we need to do the subtraction.  */
+	    do_pending_stack_adjust ();
+	    emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX,
+				     GET_MODE (from), 0, lab1);
+
+	    /* If not, do the signed "fix" and branch around fixup code.  */
+	    expand_fix (to, from, 0);
+	    emit_jump_insn (targetm.gen_jump (lab2));
+	    emit_barrier ();
+
+	    /* Otherwise, subtract 2**(N-1), convert to signed number,
+	       then add 2**(N-1).  Do the addition using XOR since this
+	       will often generate better code.  */
+	    emit_label (lab1);
+	    target = expand_binop (GET_MODE (from), sub_optab, from, limit,
+				   NULL_RTX, 0, OPTAB_LIB_WIDEN);
+	    expand_fix (to, target, 0);
+	    target = expand_binop (GET_MODE (to), xor_optab, to,
+				   gen_int_mode
+				   (HOST_WIDE_INT_1 << (bitsize - 1),
+				    GET_MODE (to)),
+				   to, 1, OPTAB_LIB_WIDEN);
+
+	    if (target != to)
+	      emit_move_insn (to, target);
+
+	    emit_label (lab2);
+
+	    if (optab_handler (mov_optab, GET_MODE (to)) != CODE_FOR_nothing)
+	      {
+		/* Make a place for a REG_NOTE and add it.  */
+		insn = emit_move_insn (to, to);
+		set_dst_reg_note (insn, REG_EQUAL,
+				  gen_rtx_fmt_e (UNSIGNED_FIX, GET_MODE (to),
+						 copy_rtx (from)),
+				  to);
+	      }
+
+	    return;
+	  }
+      }
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 35cfbe6..91545c5 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2120,8 +2120,7 @@ namespace wi
 inline unsigned int
 wi::int_traits <rtx_mode_t>::get_precision (const rtx_mode_t &x)
 {
-  gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode);
-  return GET_MODE_PRECISION (x.second);
+  return GET_MODE_PRECISION (as_a <scalar_mode> (x.second));
 }
 
 inline wi::storage_ref
@@ -2166,7 +2165,7 @@ namespace wi
 inline wi::hwi_with_prec
 wi::shwi (HOST_WIDE_INT val, machine_mode_enum mode)
 {
-  return shwi (val, GET_MODE_PRECISION (mode));
+  return shwi (val, GET_MODE_PRECISION (as_a <scalar_mode> (mode)));
 }
 
 /* Produce the smallest number that is represented in MODE.  The precision
@@ -2174,7 +2173,7 @@ wi::shwi (HOST_WIDE_INT val, machine_mode_enum mode)
 inline wide_int
 wi::min_value (machine_mode_enum mode, signop sgn)
 {
-  return min_value (GET_MODE_PRECISION (mode), sgn);
+  return min_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
 }
 
 /* Produce the largest number that is represented in MODE.  The precision
@@ -2182,7 +2181,7 @@ wi::min_value (machine_mode_enum mode, signop sgn)
 inline wide_int
 wi::max_value (machine_mode_enum mode, signop sgn)
 {
-  return max_value (GET_MODE_PRECISION (mode), sgn);
+  return max_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
 }
 
 extern void init_rtlanal (void);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index e47c50d..e74dd95 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3612,7 +3612,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
     {
       nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
       unsigned int nunits = GET_MODE_NUNITS (xmode);
-      machine_mode xmode_unit = GET_MODE_INNER (xmode);
+      scalar_mode xmode_unit = GET_MODE_INNER (xmode);
       gcc_assert (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode_unit));
       gcc_assert (nregs_xmode
 		  == (nunits
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index 71b46d0..2ca6e5c 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -1277,11 +1277,15 @@ sdbout_parms (tree parms)
 		   the parm with the variable's declared type, and adjust
 		   the address if the least significant bytes (which we are
 		   using) are not the first ones.  */
+		scalar_mode from_mode, to_mode;
 		if (BYTES_BIG_ENDIAN
-		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
-		  current_sym_value +=
-		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
-		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
+		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)
+		    && is_a <scalar_mode> (TYPE_MODE (DECL_ARG_TYPE (parms)),
+					   &from_mode)
+		    && is_a <scalar_mode> (GET_MODE (DECL_RTL (parms)),
+					   &to_mode))
+		  current_sym_value += (GET_MODE_SIZE (from_mode)
+					- GET_MODE_SIZE (to_mode));
 
 		if (MEM_P (DECL_RTL (parms))
 		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 465e02a..2433fbf 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -5732,7 +5732,7 @@ simplify_immed_subreg (machine_mode outermode, rtx op,
   rtx result_s;
   rtvec result_v = NULL;
   enum mode_class outer_class;
-  machine_mode outer_submode;
+  scalar_mode outer_submode;
   int max_bitsize;
 
   /* Some ports misuse CCmode.  */
@@ -5798,7 +5798,7 @@ simplify_immed_subreg (machine_mode outermode, rtx op,
 
 	case CONST_WIDE_INT:
 	  {
-	    rtx_mode_t val = rtx_mode_t (el, innermode);
+	    rtx_mode_t val = rtx_mode_t (el, GET_MODE_INNER (innermode));
 	    unsigned char extend = wi::sign_mask (val);
 	    int prec = wi::get_precision (val);
 
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 48634d9..f16c826 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -478,7 +478,7 @@ bitwise_type_for_mode (machine_mode mode)
    is no suitable mode.  */
 
 machine_mode
-mode_for_vector (machine_mode innermode, unsigned nunits)
+mode_for_vector (scalar_mode innermode, unsigned nunits)
 {
   machine_mode mode;
 
@@ -2145,10 +2145,13 @@ layout_type (tree type)
       }
 
    case FIXED_POINT_TYPE:
-     /* TYPE_MODE (type) has been set already.  */
-     TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-     TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
-     break;
+     {
+       /* TYPE_MODE (type) has been set already.  */
+       scalar_mode mode = SCALAR_TYPE_MODE (type);
+       TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+       break;
+     }
 
     case COMPLEX_TYPE:
       TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
@@ -2169,7 +2172,8 @@ layout_type (tree type)
 	/* Find an appropriate mode for the vector type.  */
 	if (TYPE_MODE (type) == VOIDmode)
 	  SET_TYPE_MODE (type,
-			 mode_for_vector (TYPE_MODE (innertype), nunits));
+			 mode_for_vector (SCALAR_TYPE_MODE (innertype),
+					  nunits));
 
 	TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
diff --git a/gcc/target.def b/gcc/target.def
index 25473c6..978916b 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1839,7 +1839,7 @@ mode @var{mode}.  The default is\n\
 equal to @code{word_mode}, because the vectorizer can do some\n\
 transformations even in absence of specialized @acronym{SIMD} hardware.",
  machine_mode,
- (machine_mode mode),
+ (scalar_mode mode),
  default_preferred_simd_mode)
 
 /* Returns a mask of vector sizes to iterate over when auto-vectorizing
@@ -3295,7 +3295,7 @@ The default version of this hook returns true for any mode\n\
 required to handle the basic C types (as defined by the port).\n\
 Included here are the double-word arithmetic supported by the\n\
 code in @file{optabs.c}.",
- bool, (machine_mode mode),
+ bool, (scalar_mode mode),
  default_scalar_mode_supported_p)
 
 /* Similarly for vector modes.  "Supported" here is less strict.  At
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index df76ba1..5e5db10 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -393,7 +393,7 @@ default_mangle_assembler_name (const char *name ATTRIBUTE_UNUSED)
    supported by optabs.c.  */
 
 bool
-default_scalar_mode_supported_p (machine_mode mode)
+default_scalar_mode_supported_p (scalar_mode mode)
 {
   int precision = GET_MODE_PRECISION (mode);
 
@@ -1163,7 +1163,7 @@ default_builtin_support_vector_misalignment (machine_mode mode,
    possibly adds/subtracts using bit-twiddling.  */
 
 machine_mode
-default_preferred_simd_mode (machine_mode mode ATTRIBUTE_UNUSED)
+default_preferred_simd_mode (scalar_mode)
 {
   return word_mode;
 }
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index c182e45..dcca186 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -71,7 +71,7 @@ extern void default_print_operand_address (FILE *, machine_mode, rtx);
 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_scalar_mode_supported_p (scalar_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);
@@ -100,7 +100,7 @@ extern bool
 default_builtin_support_vector_misalignment (machine_mode mode,
 					     const_tree,
 					     int, bool);
-extern machine_mode default_preferred_simd_mode (machine_mode mode);
+extern machine_mode default_preferred_simd_mode (scalar_mode mode);
 extern unsigned int default_autovectorize_vector_sizes (void);
 extern machine_mode default_get_mask_mode (unsigned, unsigned);
 extern void *default_init_cost (struct loop *);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index d83c405..636b3d5 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4147,7 +4147,7 @@ verify_gimple_assign_ternary (gassign *stmt)
 
       if (TREE_CODE (TREE_TYPE (rhs3_type)) != INTEGER_TYPE
 	  || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (rhs3_type)))
-	     != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type))))
+	     != GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (rhs1_type))))
 	{
 	  error ("invalid mask type in vector permute expression");
 	  debug_generic_expr (lhs_type);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 0de0b89..5c1f494 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3846,7 +3846,7 @@ estimate_move_cost (tree type, bool ARG_UNUSED (speed_p))
 
   if (TREE_CODE (type) == VECTOR_TYPE)
     {
-      machine_mode inner = TYPE_MODE (TREE_TYPE (type));
+      scalar_mode inner = SCALAR_TYPE_MODE (TREE_TYPE (type));
       machine_mode simd
 	= targetm.vectorize.preferred_simd_mode (inner);
       int simd_mode_size = GET_MODE_SIZE (simd);
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 4d6e4d9..ebee053 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -3227,7 +3227,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple *stmt,
   optab this_optab;
   enum tree_code wmult_code;
   enum insn_code handler;
-  machine_mode to_mode, from_mode, actual_mode;
+  scalar_mode to_mode, from_mode;
+  machine_mode actual_mode;
   location_t loc = gimple_location (stmt);
   int actual_precision;
   bool from_unsigned1, from_unsigned2;
@@ -3323,8 +3324,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple *stmt,
   else
     return false;
 
-  to_mode = TYPE_MODE (type);
-  from_mode = TYPE_MODE (type1);
+  to_mode = SCALAR_TYPE_MODE (type);
+  from_mode = SCALAR_TYPE_MODE (type1);
   from_unsigned1 = TYPE_UNSIGNED (type1);
   from_unsigned2 = TYPE_UNSIGNED (type2);
   optype = type1;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 4280914..0f03eaa 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -4740,7 +4740,8 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs, gimple *stmt,
 	(index_vec_type);
 
       /* Get an unsigned integer version of the type of the data vector.  */
-      int scalar_precision = GET_MODE_PRECISION (TYPE_MODE (scalar_type));
+      int scalar_precision
+	= GET_MODE_PRECISION (SCALAR_TYPE_MODE (scalar_type));
       tree scalar_type_unsigned = make_unsigned_type (scalar_precision);
       tree vectype_unsigned = build_vector_type
 	(scalar_type_unsigned, TYPE_VECTOR_SUBPARTS (vectype));
@@ -5981,7 +5982,8 @@ vectorizable_reduction (gimple *stmt, gimple_stmt_iterator *gsi,
     }
   else
     {
-      int scalar_precision = GET_MODE_PRECISION (TYPE_MODE (scalar_type));
+      int scalar_precision
+	= GET_MODE_PRECISION (SCALAR_TYPE_MODE (scalar_type));
       cr_index_scalar_type = make_unsigned_type (scalar_precision);
       cr_index_vector_type = build_vector_type
 	(cr_index_scalar_type, TYPE_VECTOR_SUBPARTS (vectype_out));
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index e677238..3df9a9d 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -939,7 +939,7 @@ vect_recog_widen_mult_pattern (vec<gimple *> *stmts,
   tree itype = type;
   if (TYPE_PRECISION (type) > TYPE_PRECISION (half_type0) * 2)
     itype = build_nonstandard_integer_type
-              (GET_MODE_BITSIZE (TYPE_MODE (half_type0)) * 2,
+	      (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (half_type0)) * 2,
                TYPE_UNSIGNED (type));
 
   /* Pattern detected.  */
@@ -3083,7 +3083,7 @@ vect_recog_mixed_size_cond_pattern (vec<gimple *> *stmts, tree *type_in,
   					    TYPE_UNSIGNED (type));
 
   if (itype == NULL_TREE
-      || GET_MODE_BITSIZE (TYPE_MODE (itype)) != cmp_mode_size)
+      || GET_MODE_BITSIZE (SCALAR_TYPE_MODE (itype)) != cmp_mode_size)
     return NULL;
 
   vecitype = get_vectype_for_scalar_type (itype);
@@ -3202,7 +3202,7 @@ check_bool_pattern (tree var, vec_info *vinfo, hash_set<gimple *> &stmts)
 
 	  if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE)
 	    {
-	      machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+	      scalar_mode mode = SCALAR_TYPE_MODE (TREE_TYPE (rhs1));
 	      tree itype
 		= build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
 	      vecitype = get_vectype_for_scalar_type (itype);
@@ -3324,7 +3324,7 @@ adjust_bool_pattern (tree var, tree out_type,
 	  irhs1 = *defs.get (rhs1);
 	  tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
 	  if (TYPE_PRECISION (TREE_TYPE (irhs1))
-	      == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+	      == GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (def_rhs1))))
 	    {
 	      rhs_code = def_rhs_code;
 	      rhs1 = def_rhs1;
@@ -3343,7 +3343,7 @@ adjust_bool_pattern (tree var, tree out_type,
 	  irhs2 = *defs.get (rhs2);
 	  tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
 	  if (TYPE_PRECISION (TREE_TYPE (irhs2))
-	      == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+	      == GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (def_rhs1))))
 	    {
 	      rhs_code = def_rhs_code;
 	      rhs1 = def_rhs1;
@@ -3393,7 +3393,7 @@ adjust_bool_pattern (tree var, tree out_type,
 	  || (TYPE_PRECISION (TREE_TYPE (rhs1))
 	      != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1)))))
 	{
-	  machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+	  scalar_mode mode = SCALAR_TYPE_MODE (TREE_TYPE (rhs1));
 	  itype
 	    = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
 	}
@@ -3548,7 +3548,7 @@ search_type_for_mask_1 (tree var, vec_info *vinfo,
 	  if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
 	      || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
 	    {
-	      machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+	      scalar_mode mode = SCALAR_TYPE_MODE (TREE_TYPE (rhs1));
 	      res = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
 	    }
 	  else
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index de5c2c0..c4066fa 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3704,7 +3704,7 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
 	  v1 = SLP_TREE_VEC_STMTS (node).copy ();
 	  SLP_TREE_VEC_STMTS (node).truncate (0);
 	  tree meltype = build_nonstandard_integer_type
-	      (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (vectype))), 1);
+	      (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (vectype))), 1);
 	  tree mvectype = get_same_sized_vectype (meltype, vectype);
 	  unsigned k = 0, l;
 	  for (j = 0; j < v0.length (); ++j)
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index d6b281d..937b348 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4036,7 +4036,6 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
   vec<tree> interm_types = vNULL;
   tree last_oprnd, intermediate_type, cvt_type = NULL_TREE;
   int op_type;
-  machine_mode rhs_mode;
   unsigned short fltsz;
 
   /* Is STMT a vectorizable conversion?   */
@@ -4182,6 +4181,11 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
   gcc_assert (ncopies >= 1);
 
   /* Supportable by target?  */
+  bool found_mode = false;
+  scalar_mode lhs_mode = SCALAR_TYPE_MODE (lhs_type);
+  scalar_mode rhs_mode = SCALAR_TYPE_MODE (rhs_type);
+  opt_scalar_mode rhs_mode_iter;
+
   switch (modifier)
     {
     case NONE:
@@ -4209,13 +4213,13 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
 	}
 
       if (code != FLOAT_EXPR
-	  || (GET_MODE_SIZE (TYPE_MODE (lhs_type))
-	      <= GET_MODE_SIZE (TYPE_MODE (rhs_type))))
+	  || GET_MODE_SIZE (lhs_mode) <= GET_MODE_SIZE (rhs_mode))
 	goto unsupported;
 
-      fltsz = GET_MODE_SIZE (TYPE_MODE (lhs_type));
-      FOR_EACH_2XWIDER_MODE (rhs_mode, TYPE_MODE (rhs_type))
+      fltsz = GET_MODE_SIZE (lhs_mode);
+      FOR_EACH_2XWIDER_MODE (rhs_mode_iter, rhs_mode)
 	{
+	  rhs_mode = *rhs_mode_iter;
 	  if (GET_MODE_SIZE (rhs_mode) > fltsz)
 	    break;
 
@@ -4242,10 +4246,13 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
 	  if (supportable_widening_operation (NOP_EXPR, stmt, cvt_type,
 					      vectype_in, &code1, &code2,
 					      &multi_step_cvt, &interm_types))
-	    break;
+	    {
+	      found_mode = true;
+	      break;
+	    }
 	}
 
-      if (rhs_mode == VOIDmode || GET_MODE_SIZE (rhs_mode) > fltsz)
+      if (!found_mode)
 	goto unsupported;
 
       if (GET_MODE_SIZE (rhs_mode) == fltsz)
@@ -4266,11 +4273,9 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
 	break;
 
       if (code != FIX_TRUNC_EXPR
-	  || (GET_MODE_SIZE (TYPE_MODE (lhs_type))
-	      >= GET_MODE_SIZE (TYPE_MODE (rhs_type))))
+	  || GET_MODE_SIZE (lhs_mode) >= GET_MODE_SIZE (rhs_mode))
 	goto unsupported;
 
-      rhs_mode = TYPE_MODE (rhs_type);
       cvt_type
 	= build_nonstandard_integer_type (GET_MODE_BITSIZE (rhs_mode), 0);
       cvt_type = get_same_sized_vectype (cvt_type, vectype_in);
@@ -8859,18 +8864,16 @@ free_stmt_vec_info (gimple *stmt)
 static tree
 get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
 {
-  machine_mode inner_mode = TYPE_MODE (scalar_type);
+  scalar_mode inner_mode;
   machine_mode simd_mode;
-  unsigned int nbytes = GET_MODE_SIZE (inner_mode);
   int nunits;
   tree vectype;
 
-  if (nbytes == 0)
+  if (!is_int_mode (TYPE_MODE (scalar_type), &inner_mode)
+      && !is_float_mode (TYPE_MODE (scalar_type), &inner_mode))
     return NULL_TREE;
 
-  if (GET_MODE_CLASS (inner_mode) != MODE_INT
-      && GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
-    return NULL_TREE;
+  unsigned int nbytes = GET_MODE_SIZE (inner_mode);
 
   /* For vector types of elements whose mode precision doesn't
      match their types precision we use a element type of mode
diff --git a/gcc/tree.c b/gcc/tree.c
index d7bbcb3..a668e31 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2130,8 +2130,9 @@ build_minus_one_cst (tree type)
     case FIXED_POINT_TYPE:
       /* We can only generate 1 for accum types.  */
       gcc_assert (ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)));
-      return build_fixed (type, fixed_from_double_int (double_int_minus_one,
-						       TYPE_MODE (type)));
+      return build_fixed (type,
+			  fixed_from_double_int (double_int_minus_one,
+						 SCALAR_TYPE_MODE (type)));
 
     case VECTOR_TYPE:
       {
diff --git a/gcc/tree.h b/gcc/tree.h
index 1c2f71f..68de7f4 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_TYPE_MODE(NODE) \
+  (as_a <scalar_mode> (TYPE_CHECK (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) \
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 10f3eaa..5ec2844 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -120,7 +120,8 @@ tree
 ubsan_encode_value (tree t, bool in_expand_p)
 {
   tree type = TREE_TYPE (t);
-  const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
+  scalar_mode mode = SCALAR_TYPE_MODE (type);
+  const unsigned int bitsize = GET_MODE_BITSIZE (mode);
   if (bitsize <= POINTER_SIZE)
     switch (TREE_CODE (type))
       {
@@ -147,10 +148,8 @@ ubsan_encode_value (tree t, bool in_expand_p)
 	  tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
 	  if (in_expand_p)
 	    {
-	      rtx mem
-		= assign_stack_temp_for_type (TYPE_MODE (type),
-					      GET_MODE_SIZE (TYPE_MODE (type)),
-					      type);
+	      rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
+						    type);
 	      SET_DECL_RTL (var, mem);
 	      expand_assignment (var, t, false);
 	      return build_fold_addr_expr (var);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index b9206b8..a181cde 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3853,7 +3853,7 @@ output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
     case MODE_VECTOR_UACCUM:
       {
 	int i, units;
-        machine_mode submode = GET_MODE_INNER (mode);
+	scalar_mode submode = GET_MODE_INNER (mode);
 	unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode));
 
 	gcc_assert (GET_CODE (x) == CONST_VECTOR);
@@ -4831,7 +4831,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
 	  break;
 	case VECTOR_CST:
 	  {
-	    machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
+	    scalar_mode inner = SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
 	    unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
 	    int elt_size = GET_MODE_SIZE (inner);
 	    output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align,

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

* [67/67] Add a complex_mode class
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (66 preceding siblings ...)
  2016-12-09 13:40 ` [64/67] Add a scalar_mode class Richard Sandiford
@ 2016-12-09 13:41 ` Richard Sandiford
  2016-12-09 18:20 ` [0/67] Add wrapper classes for machine_modes Sandra Loosemore
  2017-05-05  7:08 ` Jeff Law
  69 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:41 UTC (permalink / raw)
  To: gcc-patches

This patch adds another machine_mode_enum wrapper for modes
that are known to be COMPLEX_MODE_P.  There aren't yet many
places that make use of it, but that might change in future.

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

	* coretypes.h (complex_mode): New type.
	(opt_complex_mode): New typedef.
	* machmode.h (complex_mode): New class.
	(complex_mode::includes_p): New function.
	(complex_mode::from_int): Likewise.
	(is_complex_int_mode): Likewise.
	* genmodes.c (get_mode_class): Handle complex mode classes.
	* function.c (expand_function_end): Use is_complex_int_mode.

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 564d7fe..276127f 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -59,10 +59,12 @@ class machine_mode;
 class scalar_mode;
 class scalar_int_mode;
 class scalar_float_mode;
+class complex_mode;
 template<typename> class opt_mode;
 typedef opt_mode<scalar_mode> opt_scalar_mode;
 typedef opt_mode<scalar_int_mode> opt_scalar_int_mode;
 typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
+typedef opt_mode<complex_mode> opt_complex_mode;
 template<typename> class pod_mode;
 typedef pod_mode<scalar_mode> scalar_mode_pod;
 typedef pod_mode<scalar_int_mode> scalar_int_mode_pod;
diff --git a/gcc/function.c b/gcc/function.c
index 7da0203..9d2f6bb 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5502,6 +5502,7 @@ expand_function_end (void)
 	  : DECL_REGISTER (decl_result))
 	{
 	  rtx real_decl_rtl = crtl->return_rtx;
+	  complex_mode cmode;
 
 	  /* This should be set in assign_parms.  */
 	  gcc_assert (REG_FUNCTION_VALUE_P (real_decl_rtl));
@@ -5542,8 +5543,8 @@ expand_function_end (void)
 	     need to generate some non-trivial bitfield insertions.  Do that
 	     on a pseudo and not the hard register.  */
 	  else if (GET_CODE (decl_rtl) == CONCAT
-		   && GET_MODE_CLASS (GET_MODE (decl_rtl)) == MODE_COMPLEX_INT
-		   && GET_MODE_BITSIZE (GET_MODE (decl_rtl)) <= BITS_PER_WORD)
+		   && is_complex_int_mode (GET_MODE (decl_rtl), &cmode)
+		   && GET_MODE_BITSIZE (cmode) <= BITS_PER_WORD)
 	    {
 	      int old_generating_concat_p;
 	      rtx tmp;
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index 4f10632..05376ca 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -1152,6 +1152,10 @@ get_mode_class (struct mode_data *mode)
     case MODE_DECIMAL_FLOAT:
       return "scalar_float_mode";
 
+    case MODE_COMPLEX_INT:
+    case MODE_COMPLEX_FLOAT:
+      return "complex_mode";
+
     default:
       return NULL;
     }
diff --git a/gcc/machmode.h b/gcc/machmode.h
index fe62965..fd93cb0 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -433,6 +433,40 @@ scalar_mode::from_int (int i)
   return machine_mode_enum (i);
 }
 
+/* Represents a machine mode that is known to be a COMPLEX_MODE_P.  */
+class complex_mode
+{
+public:
+  ALWAYS_INLINE complex_mode () {}
+  ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+
+  static bool includes_p (machine_mode_enum);
+  static complex_mode from_int (int);
+
+PROTECT_ENUM_CONVERSION:
+  ALWAYS_INLINE complex_mode (machine_mode_enum m) : m_mode (m) {}
+
+protected:
+  machine_mode_enum m_mode;
+};
+
+/* Return true if M is a complex_mode.  */
+
+inline bool
+complex_mode::includes_p (machine_mode_enum m)
+{
+  return COMPLEX_MODE_P (m);
+}
+
+/* Return M as a complex_mode.  This function should only be used by
+   utility functions; general code should use as_a<T> instead.  */
+
+ALWAYS_INLINE complex_mode
+complex_mode::from_int (int i)
+{
+  return machine_mode_enum (i);
+}
+
 /* Represents a general machine mode (scalar or non-scalar).  */
 class machine_mode
 {
@@ -780,6 +814,21 @@ is_float_mode (machine_mode mode, T *float_mode)
   return false;
 }
 
+/* Return true if MODE has class MODE_COMPLEX_INT, storing it as
+   a complex_mode in *CMODE if so.  */
+
+template<typename T>
+inline bool
+is_complex_int_mode (machine_mode mode, T *cmode)
+{
+  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+    {
+      *cmode = complex_mode::from_int (mode);
+      return true;
+    }
+  return false;
+}
+
 namespace mode_iterator
 {
   /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */

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

* Re: [0/67] Add wrapper classes for machine_modes
  2016-12-09 13:00 ` [0/67] Add wrapper classes for machine_modes Richard Biener
@ 2016-12-09 13:54   ` Richard Sandiford
  0 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 13:54 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

Richard Biener <richard.guenther@gmail.com> writes:
> 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?

That's what the third paragraph onwards was addressing.  It uses
static type checking to avoid a relatively common source of bugs,
with the "proof" being that we'd accidentally fixed at least three
PRs without knowing about it.  Note that the final two of the patches
I linked to above were only from the end of last month.

There's also the beneefit that it's overall a slight compile-time
improvement.

Thanks,
Richard

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

* Re: [7/67] Add scalar_float_mode
  2016-12-09 12:57 ` [7/67] Add scalar_float_mode Richard Sandiford
@ 2016-12-09 14:19   ` David Malcolm
  2016-12-09 14:30     ` Richard Sandiford
  0 siblings, 1 reply; 79+ messages in thread
From: David Malcolm @ 2016-12-09 14:19 UTC (permalink / raw)
  To: Richard Sandiford, gcc-patches

On Fri, 2016-12-09 at 12:56 +0000, Richard Sandiford wrote:
> 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.

[...]

> 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

Should this be a subclass of machine_mode?  Or does this lead to name
clashes? (e.g. for "from_int")

(Similar questions for the other more specialized wrapper classes; it
looks like you have a set of independent wrapper classes around the
machine_mode_enum, without using inheritance, with a trip through the
enum needed to convert between wrappers)

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

Should this ctor have some kind of:
  gcc_checking_assert (SCALAR_FLOAT_MODE_P (m));
or somesuch?  (or does that slow down the debug build too much?)

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

...or put an assertion in here?  (I *think* it's the only public
function that can (implicitly) call the ctor without checking the
invariant)

[...]


Hope this is constructive
Dave

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

* Re: [7/67] Add scalar_float_mode
  2016-12-09 14:19   ` David Malcolm
@ 2016-12-09 14:30     ` Richard Sandiford
  0 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 14:30 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

David Malcolm <dmalcolm@redhat.com> writes:
> On Fri, 2016-12-09 at 12:56 +0000, Richard Sandiford wrote:
>> 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.
>
> [...]
>
>> 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
>
> Should this be a subclass of machine_mode?  Or does this lead to name
> clashes? (e.g. for "from_int")
>
> (Similar questions for the other more specialized wrapper classes; it
> looks like you have a set of independent wrapper classes around the
> machine_mode_enum, without using inheritance, with a trip through the
> enum needed to convert between wrappers)

Making it a subclass would be the natural thing to do if the class
actually defined the mode (and if we for example used pointers to
the definitions to represent the mode).  With wrappers it's kind-of
the "wrong way round" though: having scalar_int_mode a subclass of
machine_mode would allow things like:

  void foo (machine_mode *x) { *x = SFmode; }
  void bar () { scalar_int_mode y; foo (&y); ... }

and so isn't type-safe.

>> +{
>> +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)
>> {}
>
> Should this ctor have some kind of:
>   gcc_checking_assert (SCALAR_FLOAT_MODE_P (m));
> or somesuch?  (or does that slow down the debug build too much?)

The idea was to have the asserts in as_a <> calls instead, which is
the point at which forcible conversion occurs.  These routines are for
cases where we've already done the check or know due to static type
checking that a check isn't needed.

>> +
>> +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);
>> +}
>
> ...or put an assertion in here?  (I *think* it's the only public
> function that can (implicitly) call the ctor without checking the
> invariant)

Same idea here: this should only be called when no check is needed,
and like you say shouldn't have an assert for speed reasons.  The
number of callers to from_int is small and so it's relatively easy
to check that the calls are safe.

> Hope this is constructive

Yeah, definitely :-)

Thanks,
Richard

^ 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:22   ` Richard Biener
@ 2016-12-09 14:42     ` Richard Sandiford
  0 siblings, 0 replies; 79+ messages in thread
From: Richard Sandiford @ 2016-12-09 14:42 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

Richard Biener <richard.guenther@gmail.com> writes:
> 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.

Checking against BLKmode is still valid.  The patch is just rewriting
the check into an alternative form.  The end goal is to operate on
scalar_int_modes in cases where we know the mode is an integer.

In this case the mode we're checking is the result of a type_for_size
call, which is defined to always return an integer type:

  /* Given PRECISION and UNSIGNEDP, return a suitable type-tree for an
     integer type with at least that precision.  */

TBH I was a bit surprised we could see a BLKmode integer type; I thought
we disallowed types that didn't have a suitable scalar_mode_supported_p
mode.  But assuming that the check is necessary, the only thing it
lets through are scalar integer modes.

Thanks,
Richard

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

* Re: [0/67] Add wrapper classes for machine_modes
  2016-12-09 12:48 [0/67] Add wrapper classes for machine_modes Richard Sandiford
                   ` (67 preceding siblings ...)
  2016-12-09 13:41 ` [67/67] Add a complex_mode class Richard Sandiford
@ 2016-12-09 18:20 ` Sandra Loosemore
  2017-05-05  7:08 ` Jeff Law
  69 siblings, 0 replies; 79+ messages in thread
From: Sandra Loosemore @ 2016-12-09 18:20 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 12/09/2016 05:48 AM, Richard Sandiford 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.  [snip]
>
> 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.

I have no power to approve or reject this patch series....  but, just as 
an engineering process matter, I don't think this belongs in Stage 3: 
"During this two-month period, the only (non-documentation) changes that 
may be made are changes that fix bugs or new ports which do not require 
changes to other parts of the compiler. New functionality may not be 
introduced during this period."

I don't think a 67-part patch series whose existence was revealed only 3 
days before the close of stage 1 and were not actually posted qualifies 
for the "Patches posted early enough during Stage 1 and not yet fully 
reviewed may still get in early in Stage 3." exception either.

Richard, I appreciate that you are very methodical in your work and 
careful to test it thoroughly.  But IMO a patch series this invasive is 
likely to disrupt other people who are trying to fix bugs at this time 
to improve the 7.0 release quality.

-Sandra

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

* Re: [2/67] Make machine_mode a class
  2016-12-09 12:52 ` [2/67] Make machine_mode a class Richard Sandiford
@ 2016-12-15 22:34   ` Trevor Saunders
  0 siblings, 0 replies; 79+ messages in thread
From: Trevor Saunders @ 2016-12-15 22:34 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On Fri, Dec 09, 2016 at 12:52:03PM +0000, Richard Sandiford wrote:
> 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.

We should probably add a GCC_CONSTEXPR macro so we can get that
advantage without having to play games like this, but this case doesn't
seem like too big of a deal.

Trev

^ 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
                   ` (68 preceding siblings ...)
  2016-12-09 18:20 ` [0/67] Add wrapper classes for machine_modes Sandra Loosemore
@ 2017-05-05  7:08 ` Jeff Law
  2017-05-24 14:33   ` Richard Sandiford
  69 siblings, 1 reply; 79+ messages in thread
From: Jeff Law @ 2017-05-05  7:08 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 12/09/2016 05:48 AM, Richard Sandiford 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
So can we get the discussion around the prerequisite restarted -- I like 
the core ideas around building wrapper classes around machine modes, but 
obviously we can't really move forward on this without the prereqs.

jeff

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

* Re: [0/67] Add wrapper classes for machine_modes
  2017-05-05  7:08 ` Jeff Law
@ 2017-05-24 14:33   ` Richard Sandiford
  2017-06-28 17:27     ` Jeff Law
  0 siblings, 1 reply; 79+ messages in thread
From: Richard Sandiford @ 2017-05-24 14:33 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

Jeff Law <law@redhat.com> writes:
> On 12/09/2016 05:48 AM, Richard Sandiford 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
> So can we get the discussion around the prerequisite restarted -- I like 
> the core ideas around building wrapper classes around machine modes, but 
> obviously we can't really move forward on this without the prereqs.

Finally got back to this, sorry for the delay.  I think the only
remaining prerequisite is the coretypes.h reorg patch.  I'll post
an updated version of that in a sec.

I've also rebased and retested the patch series itself.  Should I repost
it in one go, or split it up further?  The original idea was to show that
this wasn't a half-transition and that the series on its own leaves things
in a sensible state.  But it's also true that there are no forward
dependencies, so it'd also be possible to commit the patches in stages.

Thanks,
Richard

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

* Re: [0/67] Add wrapper classes for machine_modes
  2017-05-24 14:33   ` Richard Sandiford
@ 2017-06-28 17:27     ` Jeff Law
  0 siblings, 0 replies; 79+ messages in thread
From: Jeff Law @ 2017-06-28 17:27 UTC (permalink / raw)
  To: gcc-patches, richard.sandiford

On 05/24/2017 08:27 AM, Richard Sandiford wrote:
> Jeff Law <law@redhat.com> writes:
>> On 12/09/2016 05:48 AM, Richard Sandiford 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
>> So can we get the discussion around the prerequisite restarted -- I like 
>> the core ideas around building wrapper classes around machine modes, but 
>> obviously we can't really move forward on this without the prereqs.
> 
> Finally got back to this, sorry for the delay.  I think the only
> remaining prerequisite is the coretypes.h reorg patch.  I'll post
> an updated version of that in a sec.
Oh the irony.  I ping you, then have to disappear into the land of
stack-clash :(


> 
> I've also rebased and retested the patch series itself.  Should I repost
> it in one go, or split it up further?  The original idea was to show that
> this wasn't a half-transition and that the series on its own leaves things
> in a sensible state.  But it's also true that there are no forward
> dependencies, so it'd also be possible to commit the patches in stages.
I think in one go -- my recollection was that I already worked through
much of it without seeing anything particularly worrisome.  So in theory
it shouldn't take much to swap that state back in.

jeff

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

end of thread, other threads:[~2017-06-28 17:27 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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-15 22:34   ` Trevor Saunders
2016-12-09 12:53 ` [3/67] Add GDB pretty printer for machine mode classes Richard Sandiford
2016-12-09 12:54 ` [4/67] Add FOR_EACH iterators for modes Richard Sandiford
2016-12-09 12:55 ` [5/67] Small tweak to array_value_type Richard Sandiford
2016-12-09 12:55 ` [6/67] Make GET_MODE_WIDER return an opt_mode Richard Sandiford
2016-12-09 12:57 ` [8/67] Simplify gen_trunc/extend_conv_libfunc Richard Sandiford
2016-12-09 12:57 ` [7/67] Add scalar_float_mode Richard Sandiford
2016-12-09 14:19   ` David Malcolm
2016-12-09 14:30     ` Richard Sandiford
2016-12-09 12:58 ` [9/67] Add SCALAR_FLOAT_TYPE_MODE Richard Sandiford
2016-12-09 12:59 ` [10/67] Make assemble_real take a scalar_float_mode Richard Sandiford
2016-12-09 13:00 ` [12/67] Use opt_scalar_float_mode when iterating over float modes Richard Sandiford
2016-12-09 13:00 ` [11/67] Add a float_mode_for_size helper function Richard Sandiford
2016-12-09 13:00 ` [0/67] Add wrapper classes for machine_modes Richard Biener
2016-12-09 13:54   ` Richard Sandiford
2016-12-09 13:01 ` [13/67] Make floatn_mode return an opt_scalar_float_mode Richard Sandiford
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 ` [15/67] Add scalar_int_mode Richard Sandiford
2016-12-09 13:03 ` [16/67] Add scalar_int_mode_pod Richard Sandiford
2016-12-09 13:04 ` [17/67] Add an int_mode_for_size helper function Richard Sandiford
2016-12-09 13:05 ` [18/67] Make int_mode_for_mode return an opt_scalar_int_mode Richard Sandiford
2016-12-09 13:05 ` [19/67] Add a smallest_int_mode_for_size helper function Richard Sandiford
2016-12-09 13:06 ` [20/67] Replace MODE_INT checks with is_int_mode Richard Sandiford
2016-12-09 13:07 ` [22/67] Replace !VECTOR_MODE_P with is_a <scalar_int_mode> Richard Sandiford
2016-12-09 13:07 ` [21/67] Replace SCALAR_INT_MODE_P checks " Richard Sandiford
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
2016-12-09 13:08 ` [23/67] Replace != VOIDmode checks " Richard Sandiford
2016-12-09 13:09 ` [25/67] Use is_a <scalar_int_mode> for bitmask optimisations Richard Sandiford
2016-12-09 13:10 ` [26/67] Use is_a <scalar_int_mode> in subreg/extract simplifications Richard Sandiford
2016-12-09 13:10 ` [27/67] Use is_a <scalar_int_mode> before LOAD_EXTEND_OP Richard Sandiford
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 ` [30/67] Use scalar_int_mode for doubleword splits Richard Sandiford
2016-12-09 13:12 ` [29/67] Make some *_loc_descriptor helpers take scalar_int_mode Richard Sandiford
2016-12-09 13:13 ` [31/67] Use scalar_int_mode for move2add Richard Sandiford
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 ` [33/67] Add a NARROWEST_INT_MODE macro Richard Sandiford
2016-12-09 13:15 ` [34/67] Add a SCALAR_INT_TYPE_MODE macro Richard Sandiford
2016-12-09 13:16 ` [35/67] Add uses of as_a <scalar_int_mode> Richard Sandiford
2016-12-09 13:16 ` [36/67] Use scalar_int_mode in the RTL iv routines Richard Sandiford
2016-12-09 13:17 ` [38/67] Move SCALAR_INT_MODE_P out of strict_volatile_bitfield_p Richard Sandiford
2016-12-09 13:17 ` [37/67] Use scalar_int_mode when emitting cstores Richard Sandiford
2016-12-09 13:18 ` [39/67] Two changes to the get_best_mode interface Richard Sandiford
2016-12-09 13:19 ` [40/67] Use scalar_int_mode for extraction_insn fields Richard Sandiford
2016-12-09 13:20 ` [42/67] Use scalar_int_mode in simplify_shift_const_1 Richard Sandiford
2016-12-09 13:20 ` [41/67] Split scalar integer handling out of force_to_mode Richard Sandiford
2016-12-09 13:22 ` [44/67] Make simplify_and_const_int take a scalar_int_mode Richard Sandiford
2016-12-09 13:22 ` [43/67] Use scalar_int_mode in simplify_comparison Richard Sandiford
2016-12-09 13:23 ` [46/67] Make widest_int_mode_for_size return a scalar_int_mode Richard Sandiford
2016-12-09 13:23 ` [45/67] Make extract_left_shift take " Richard Sandiford
2016-12-09 13:24 ` [47/67] Make subroutines of nonzero_bits operate on scalar_int_mode Richard Sandiford
2016-12-09 13:25 ` [48/67] Make subroutines of num_sign_bit_copies " Richard Sandiford
2016-12-09 13:25 ` [49/67] Simplify nonzero/num_sign_bits hooks Richard Sandiford
2016-12-09 13:28 ` [50/67] Add helper routines for SUBREG_PROMOTED_VAR_P subregs Richard Sandiford
2016-12-09 13:30 ` [52/67] Use scalar_int_mode in extract/store_bit_field Richard Sandiford
2016-12-09 13:30 ` [51/67] Use opt_scalar_int_mode when iterating over integer modes Richard Sandiford
2016-12-09 13:31 ` [53/67] Pass a mode to const_scalar_mask_from_tree Richard Sandiford
2016-12-09 13:31 ` [54/67] Add explicit int checks for alternative optab implementations Richard Sandiford
2016-12-09 13:33 ` [55/67] Use scalar_int_mode in simplify_const_unary_operation Richard Sandiford
2016-12-09 13:33 ` [56/67] Use the more specific type when two modes are known to be equal Richard Sandiford
2016-12-09 13:34 ` [57/67] Use scalar_int_mode in expand_expr_addr_expr Richard Sandiford
2016-12-09 13:35 ` [58/67] Use scalar_int_mode in a try_combine optimisation Richard Sandiford
2016-12-09 13:36 ` [59/67] Add a rtx_jump_table_data::get_data_mode helper Richard Sandiford
2016-12-09 13:36 ` [60/67] Pass scalar_int_modes to do_jump_by_parts_* Richard Sandiford
2016-12-09 13:37 ` [61/67] Use scalar_int_mode in the AArch64 port Richard Sandiford
2016-12-09 13:38 ` [62/67] Big machine_mode to scalar_int_mode replacement Richard Sandiford
2016-12-09 13:38 ` [63/67] Simplifications after type switch Richard Sandiford
2016-12-09 13:40 ` [66/67] Add a scalar_mode_pod class Richard Sandiford
2016-12-09 13:40 ` [65/67] Use scalar_mode in the AArch64 port Richard Sandiford
2016-12-09 13:40 ` [64/67] Add a scalar_mode class Richard Sandiford
2016-12-09 13:41 ` [67/67] Add a complex_mode class Richard Sandiford
2016-12-09 18:20 ` [0/67] Add wrapper classes for machine_modes Sandra Loosemore
2017-05-05  7:08 ` Jeff Law
2017-05-24 14:33   ` Richard Sandiford
2017-06-28 17:27     ` Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).