This is the patch that implements the majority of the parameterized register class information. Most of it is related to type inference in TableGen and to the generation of instruction selection matchers and register class information.
Motivation
The main idea here is to implement register classes where the register size (also spill alignment, etc.) may not be known at the execution time of TableGen. This happens on architectures where the register size is a configurable parameter. And example of that could be the HVX coprocessor on Hexagon: it has two modes, one where the registers are 64 bytes long and one with 128 byte registers. The instruction sets and their encodings for both modes are identical, however since RegisterClass has a fixed size, and a fixed set of value types, two separate register classes are needed to represent the registers in the two modes. This, in turn, requires two separate instruction sets to be defined (and handled) internally by the compiler, which is an unnecessary duplication.
Overview
This patch introduces the concept of a "hardware mode", i.e. HwMode, which serves a similar role to a predicate. A HwMode is defined via a list of target features, which will be checked to determine whether a given hardware mode is active. This check will happen not at the run time of TableGen, but at the run time of the compiler, when the compilation target is known.
TableGen will generate code to perform these checks. There is also a "default" mode, which is active is no other mode is active.
For backends that do not use this feature, the "default" mode will be the only mode. The existence of that mode is mostly transparent (limited to TableGen internals), and requires no changes to these backends.
Within TableGen, information that depends on HwMode is a map of values, where HwMode is the key. One example of that is ValueTypeByHwMode, which is a ValueType dependent on HwMode. For defining register classes, there is RegSizeInfoByHwMode, which associates register size, spill size and alignment, and the set of legal value types with each HwMode. For use with maps, the HwMode is stored as an unsigned value, where 0 represents the default mode.
Type inference
This parameterization of value types for a register class lead to the necessity of having a new type inference that can deal with sets of parameterized value types. Internally, instead of keeping track of a set of individual parameterized value type, type inference has a map (keyed by HwMode) of sets of non-parameterized value types. Type inference succeeds when for each HwMode, the corresponding set has at most one value type in it, and there exists a non-empty set in the map. Allowing empty sets for some HwModes is motivated by intrinsics: argument types of intrinsics are exposed to the front-end (clang), and so they cannot be parameterized (without making this a clang-wide project). An empty set of value types for a particular mode implies that the given intrinsic is not valid for a particular mode.
At the end of type inference, each pattern tree node has a map of value types associated with it. The next step is to generate instruction selection matchers. The feature sets defining each HwMode are used to create selection Predicates, and each pattern tree with parameterized types at each node is replicated into a set of trees, one for each HwMode, where the value types at each node are no longer parameterized individually. For each such pattern tree, a selection Predicate is associated with it, and at this point the existing matcher generating code is used.
Register class information
The register class information is generated as an array of blocks, one block for each HwMode. Each block contains whatever information depends on the HwMode. At the compiler run time, the TargetRegisterInfo's query functions (such as getRegisterSizeInBits) will obtain the active mode, use it as an index into the array of blocks, and return the information from the appropriate block.
Interaction with FastISel and GlobalISel
Both FastISel and GlobalISel can only be used when the parameterized register classes are not used by a given target. This is not an inherent limitation, it's just that non-trivial changes would be needed for them to accommodate the support for parameterization.