[LLVMdev] Trouble with instructions for lowering load/store.

Tim Northover t.p.northover at gmail.com
Sat Feb 2 10:46:17 PST 2013


Hi Earl,

> Example of some load instructions for Z80 CPU with opcode:
> Opcode          Instruction             node pattern
> 0x46               LD $dst,(HL)        (set GR8:$dst, (load HL))
> 0x0A              LD A,(BC)             (set A, (load BC))
> 0x1A              LD A,(DE)             (set A, (load DE))
> 0x3A              LD A,($src)           (set A, (load i16imm:$src))
>
> Target Description file:
> ...
>   def LD8rm : IRy<0x46, (outs GR8:$dst), (ins),
>     "ld\t{$dst, (hl)}", [(set GR8:$dst, (load HL))]>;
> ...
> GR8 - i8 RegisterClass (contains registers: A, B, C, D, E, H, L)
> GR16 - i16 RegisterClas (contains registers: BC, DE, HL)

The biggest problem I see here is that by giving no input operands,
you've left yourself no way of specifying the address. A must clearly
be from somewhere you're interested in ("HL" is not enough, LLVM has
no idea what's there or why).

It may seem wasteful, but the obvious solution is to create more
registerclasses (each register can be in as many as needed). For the
example quoted, you'd want a register class containing just "HL". What
you name it is personal preference, I'll assume GPR_HL here.

Then you'd define your instruction by:

def LD8rm : IRy<0x46, (outs GR8:$dst), (ins GPR_HL:$addr),
  "ld\t{$dst, ($addr)}". [set GR8:$dst, (load GPR_HL:$addr)]>;

This tells LLVM that the instruction's going to have an operand that
represents the address. Sure it'll always be in HL, but at least LLVM
knows what's going on now.

The register allocator will come along to allocate that register,
obviously give it HL, and then decide of its own accord that it needs
a copy to get the address it's calculated into that register (or even
better to calculate the address there in the first place).

Your other instructions would do similar tricks, both to "ins" and "outs".

> I don't understand how use ComplexPattern in this case.

A ComplexPattern may or may not be necessary here. My feeling is that
it's mostly present in existing targets to deal with the fact that
loads can have rather complicated possible addresses (e.g. register +
12-bit signed immediate shifted by the phase of the moon). In your
case, it appears that an address has to be put into a register, and
that's that (disclaimer: I know no more of Z80 than you've posted
here, I may be wrong).

Also, even with more complicated addressing modes you may be able to
get away without a ComplexPattern for loads/stores. I've recently
committed the AArch64 backend which did away of it in favour of some
TableGen. I'm still in two minds about whether it's a *better*
solution myself, but it is at least possible.

Let us know if you need more help.

Tim.



More information about the llvm-dev mailing list