This series is an update of: https://gcc.gnu.org/ml/gcc-patches/2016-12/msg00766.html
It adds a group of wrapper classes around machine_mode for modes that are known to belong to, or need to belong to, a particular mode_class. For example, it adds a scalar_int_mode wrapper for MODE_INT and MODE_PARTIAL_INT modes, a scalar_float_mode wrapper for MODE_FLOAT and MODE_DECIMAL_FLOAT modes, and so on. These wrapper classes aren't meant to form an inheritance tree in the way that rtx_insn or gimple do. They really just bundle a machine_mode with a static assertion that a particular condition holds. In principle there could be a wrapper class for any useful condition. The reason for using wrapper classes is that they provide more build-time checking that modes have the right class. In the best cases they avoid the need for any runtime assertions, but "at worst" they force the assertion further up to the place that derives the mode, often a TYPE_MODE or a GET_MODE. Enforcing the condition at this level should catch mistakes earlier and with less sensitivity to the following code paths. It should also make the basis for the assertion more obvious; e.g. scalar_int_mode uses of TYPE_MODEs are often guarded at some level by an INTEGRAL_TYPE_P test. 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 It also found problems that seemed to be latent, but the fixes for those went into GCC 7, so there are none to go with this iteration of the series. The most common sources of problems seemed to be using VOIDmode or BLKmode where a scalar integer was expected (e.g. when getting the number of bits in the value), and simplifying vector operations in ways that only make sense for scalars. The series is part of the SVE submission and includes most of the changes in group C from: https://gcc.gnu.org/ml/gcc/2016-11/msg00033.html Since SVE has variable-length vectors, the SVE series as a whole needs to change the size of a vector mode from being a known compile-time constant to being (possibly) a run-time invariant. It then needs to do the same for unconstrained machine_modes, which might or might not be vectors. Introducing these new constrained types for scalar and complex modes means that we can continue to treat them as having a constant size. Mostly this is just a tweaked version of the original series, rebased onto current trunk. There is one significant difference though: the first iteration treated machine_mode as an all-encompassing wrapper class whereas this version keeps it as an enum. Treating it as a wrapper class made it consistent with the other classes and meant that it would be easier in future to use member functions to access mode properties (e.g. "mode.size ()" rather than "GET_MODE_SIZE (mode)") if that was thought to be a good thing. However, Martin's recent memset/memcpy warning shows that there are still many places that expect machine_modes to be POD-ish, so in the end it seemed better to leave machine_mode as an enum for now. Also, I've now split the scalar_mode patch into 11 separate patches, since it was very difficult to review/reread in its old form. In terms of compile time, the series is actually a very slight win for --enable-checking=release builds and a more marked win for --enable-checking=yes,rtl. That might seem unlikely, but there are several possible reasons: (1) The series makes 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. (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 a 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, and thus predictable at runtime. However, we can't predict them to be false at compile time without profile feedback, since in other uses of TYPE_MODE the VECTOR_TYPE_P condition can be quite likely or even guaranteed. This means (for example) that call-clobbered registers would usually be treated as clobbered by the condition as a whole. 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 riscv64-elf 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, powerc64-linux-gnu and x86_64-linux-gnu. Thanks, Richard