I just added a new type of MachineOperand to the code generator: MO_RegisterMask.
Register mask operands are used on machine instructions that clobber large sets of registers, typically calls. Instead of a long list of <imp-def> operands, a call now has a single <regmask> operand that contains a pointer to a bit mask of call-preserved registers. This reduces memory usage and improves compile times significantly.
The register mask depends on the current sub-target and the calling convention used in the call. This means that it is no longer necessary for targets to have multiple call opcodes with different sets of clobbered registers.
Currently, only the ARM and X86 targets have been converted to use register masks. Owners of the other targets in the tree should consider converting as well.
The conversion is quite simple, copy from ARM and X86 as needed:
- Move callee saved register lists to *CallingConv.td by defining CalleeSavedRegs instances. TableGen will produce *_SaveList and *_RegMask arrays. Use them to implement the TRI::getCalleeSavedRegs() and TRI::getCallPreservedRegMask() hooks.
- Fix target-dependent code to understand regmask operands. The target-independent passes have already been fixed.
- Update *TargetLowering::LowerCall() to add a RegisterMaskSDNode operand to call SDNodes.
- Update your fast isel call emission to do the same.
- Remove Defs = […] from call instruction definitions. RISC architectures may want to keep a link register def, ARM did.
- Remove duplicate call opcodes that are no longer necessary.