[LLVMdev] Register design decision for backend

Borja Ferrer borja.ferav at gmail.com
Sun Aug 29 09:04:23 PDT 2010


Hello everbody,

This is my first email to the list, and hope to write more as i get more
involved in LLVM. I'm currently writing a backend for a 8 bit
microcontroller, and i have arrived to a point where i need to take a design
decision in order to continue the development.
Some background information: The microcontroller only has 8bit registers,
however it has some special instructions that let you work with register
pairs (adjacent registers) such as data movement, or memory operations, but
i would say that 90% of the instruction set work with 8 bit regs
(arithmetic, logical, compares, etc...). So what i did is to define all 8bit
regs inside one regclass of size i8 and then define all reg pairs inside
another regclass of size i16, marking the pairs as subregs of the 8bit regs
this way:

<stripped version of my code)>

// 8 bit regs
def R0 : Register<"r0">, DwarfRegNum<[0]>;
def R1 : Register<"r1">, DwarfRegNum<[1]>;

// reg pairs
def R1R0 : RegisterWithSubRegs<"r0", [R0, R1]>, DwarfRegNum<[0]>;

def GPR8 : RegisterClass<"TEST", [i8], 8,  [R0, R1]>;
def WDREGS : RegisterClass<"TEST", [i16], 16, [R1R0]>
{
    let SubRegClassList = [GPR8, GPR8];
}

This way i could work with register pairs easily, for example storing i16
data inside the WDREGS class or i32 inside 2 WDREGS registers, etc. I
thought everything was going fine until i tried to do a 16 bit addition. The
addition instruction only works with 8 bit regs (GPR8 class), so take this
example code:

short foo(short a, short b)
{
    return a+b;
}

arg a comes in register pair R1:R0 and arg b in R3:R2 of class WDREGS. I
expected LLVM to be able to split the pairs into GPR8 registers from all the
subreg definitions and match the pattern of the GPR8 add instruction to
produce the following asm code:

add r0, r2
addc r1, r3 ; add with carry
ret

however i noticed this doesnt work. As a test, I removed the WDREGS class
and passed everything in GPR8 regs, this way LLVM was able to expand the i16
add instruction into the code above. I first thought on making add16 a
pseudo instr and expand it manually, but i think this is a bad solution
because LLVM would loose a lot of information in such a basic thing like an
addition. Also, i would have to do the same for wider data types and for the
rest of arithmetic and logical instructions, so nearly everything would be
handled in a customized way not allowing LLVM to optimize things. I still
need to work with register pairs for the 16 bit instructions, so i cant
remove the WDREGS class, also 16bit and larger data have to be aligned in
even registers so the 16 bit instructions can manipulate them.

So after all this explanation my question is, how should i proceed? Is there
a way to tell LLVM that the reg pairs can be splitted safely or can you
think of a better solution to handle this? I've looked at other backends but
havent seen this situation happen.
As a side note, im working with the 2.7 code base.

Thanks for your attention.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100829/c832fac9/attachment.html>


More information about the llvm-dev mailing list