On 11 January 2017 at 10:24, Jim Grosbach via llvm-dev <llvm-dev at lists.llvm.org> wrote:> ARM64 is like this. I suggest having a look at that backend (lib/Target/AArch64) and how it deals with implicit zeroing of the upper bits of the X registers.ARM64 has a separate name for the registers as 32-bit values though (W0-W30 rather than X0-X30). I could easily see DAG ISel throwing a fit without that. First thing I'd try would be adding the 64-bit registers as a valid class for i32 ("addRegisterClass(MVT::i32, GPR64)"). If that works, you're good to go; if not, it should be possible add fake 32-bit registers and just print them the same as the 64-bit ones at the end. The nastiest hackery would be in the AsmParser, which may or may not be important. Cheers. Tim.
> So you want to make int 64 bit? Or you want int to stay 32 bit, long to be 64 bit but sign extend int 32 bit to 64?Int is 32, long is 64. Assuming 'int *p' the same HW load instruction covers int = *p and long = *p. I can have separate names for the 32-bit subregisters, but then I think I would need two forms of the load, one to target each. I was hoping the selector would be smart enough to user wider instruction forms for narrower types when the upper bits are unneeded.> ARM64 is like this. I suggest having a look at that backend (lib/Target/AArch64) and how it deals with implicit zeroing of the upper bits of the X registers.I did look a bit at AArch64. The difference is that AArch64 explicitly has 32-bit (W) and 64-bit (X) forms of ldr, and the .td appropriately models them as 2 instructions: ldrw and ldrx. In our case there is one ldw instruction, that loads 32 bits and sign/zero extends it. It would be used for either a 32-bit load, with the upper bits remaining unused, or a 32-to-64 sextload. If possible I'd like to model that with one instruction in the .td. I will spend more time looking at AArch64 though, as I don't yet fully understand all the subtleties of extending, promoting, and so on. -Alan
On 11 January 2017 at 12:04, Davis, Alan via llvm-dev <llvm-dev at lists.llvm.org> wrote:> I did look a bit at AArch64. The difference is that AArch64 explicitly has 32-bit (W) and 64-bit (X) forms of ldr, and the .td appropriately models them as 2 instructions: ldrw and ldrx. In our case there is one ldw instruction, that loads 32 bits and sign/zero extends it. It would be used for either a 32-bit load, with the upper bits remaining unused, or a 32-to-64 sextload. If possible I'd like to model that with one instruction in the .td.I think the AArch64 situation is actually a lot closer than you think. There are 3 relevant variants: * load 32-bits, zero extend into 64-bit register (AArch64 calls this a plain LDRW since it's indistinguishable in effect from that). * load 32-bits, sign extend to 64 (LDRSW on AArch64). * load 64-bits (LDRX on AArch64). The first one is what gets used for an i32 load, though if you wanted to be perverse you could probably use any of them since the difference is unobservable on 32-bits. I assume you've got similar, which would just make it a matter of naming the instructions. If you've actually combined LDRW and LDRSW into a single instruction then presumably there's some second operand that specifies whether to sign/zero extend, and you can set that correctly when writing patterns. The separate registers are definitely a bigger problem though. Mips might actually be a better model there, since from my very hazy memory it spells the 32 & 64-bit versions the same too. It also seems to have separate 64-bit LLVM registers (e.g. V0 and V0_64). Cheers. Tim.