About a month ago, I submitted a set of patches for review on llvm-commit. The most controversial of the patches, http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20150622/d104ea71/attachment-0009.obj deals with the fact that before ARMv8, the rGPR RegClass in Thumb encodings didn’t include SP; but from ARMv8 onwards, it does include it.
RegClass membership is currently implemented as entirely static, driven by read-only TableGen’d tables and switch blocks encoding the various classes, subclasses, and their relationships. The approach I had taken in my patch was to include ARMGenInstrInfo.inc for a second time, after re-defining rGPRRegClassID to use a different RegClass in the same instructions. Then, Thumb2InstrInfo constructor overrides the MCInstrInfo that it inherited from ARMBaseInstrInfo with the “patched” one. (This “patching”, still, happens at compile-time.)
As John rightly noted, this approach looks rather hacky and confusing:
This isn’t “rGPR includes SP” it’s “rGPR is #defined to GPRnopc”, which makes things really confusing if you’re just looking at the .td files to figure out what’s what you see instructions that use rGPR, and you see a definition of the rGPR register class, but those instructions may
actually be redefined to use GPRnopc due to something happening elsewhere that you haven’t noticed.
James added, “Given these instructions are no longer unpredictable the rest of the compiler should know about them too, not just the MC layer, so this is even more of a hack,” – and he suggested instead converting every instruction that takes an rGPR operand into a multiclass of two instructions, one predicated on HasV8Ops, and the other on its inverse. This isn’t practical, however: ARMInstrThumb2.td specifies several hundred individual encodings, InstAliases and match patterns that use rGPR, and all these would need to be manually duplicated.
Right now, we’re trying to come up with a more sensible approach, and perhaps one that could be useful for other targets as well.
Any suggestions? And are there any other cases where the definition of a register class depends on target attributes?