Hello, 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/d104ea7 1/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? -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150713/53c50017/attachment.html>
On 13 Jul 2015, at 14:19, Artyom Skrobov <artyom.skrobov at arm.com> wrote:> > 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?The MIPS back end also includes a lot of hacks along this and basically follows James’ suggestion: almost every instruction is defined twice, once for 32-bit and once for 64-bit operations. Having some mechanism in TableGen that would allow a register class used by instructions to be parameterised would simplify this a lot. It would also simplify the C code if we could just ask for the definition of Mips::ADD (for example) for the current target, where currently we have a load of things like ABI.IsN64() ? Mips::AND64 : Mips::AND scattered about the place. David
> And are there any other cases where the definition of a register class depends on target attributes?As David mentioned, a few instructions (bitwise operations, and comparisons) are register-width operations and we therefore have definitions that differ only by register class. Being able to specify one class that is 32-bit or 64-bit registers as appropriate for the subtarget would be useful. We'd also need a special type in SelectionDAG patterns for register-width integers (similar to iPTR) to be able to reduce the definitions but that's a separate topic. Another case that comes up in the Mips backend is that subregisters depend on target attributes. Our FPU implementation consists of 3 classes: * FGR32 - 32-bit FPU registers * AFGR64 - 64-bit FPU registers on a 32-bit FPU. They are composed of odd/even pairs of 32-bit subregisters. * FGR64 - 64-bit FPU registers on a 64-bit FPU. They are composed of 32-bit subregisters and a 32-bit subregister representing the additional bits. The double-precision FPU instructions are defined for both AFGR64 and FGR64. However, the only difference between them is the subregister that is used for bits 32-63 is either an additional 32-bits subregister or the 32-bits from the neighbouring odd-numbered FPU register. ________________________________________ From: llvmdev-bounces at cs.uiuc.edu [llvmdev-bounces at cs.uiuc.edu] on behalf of David Chisnall [David.Chisnall at cl.cam.ac.uk] Sent: 13 July 2015 14:34 To: Artyom Skrobov Cc: llvmdev at cs.uiuc.edu Subject: Re: [LLVMdev] [RFC] Conditional RegClass membership On 13 Jul 2015, at 14:19, Artyom Skrobov <artyom.skrobov at arm.com> wrote:> > 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?The MIPS back end also includes a lot of hacks along this and basically follows James’ suggestion: almost every instruction is defined twice, once for 32-bit and once for 64-bit operations. Having some mechanism in TableGen that would allow a register class used by instructions to be parameterised would simplify this a lot. It would also simplify the C code if we could just ask for the definition of Mips::ADD (for example) for the current target, where currently we have a load of things like ABI.IsN64() ? Mips::AND64 : Mips::AND scattered about the place. David _______________________________________________ LLVM Developers mailing list LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev