[LLVMdev] Register design decision for backend

Borja Ferrer borja.ferav at gmail.com
Tue Aug 31 13:06:41 PDT 2010

Hello Jeff, you're the first one to reply to my question :)
I got a bit confused with the fact you said that the subregister class is
larger than the superregister class. As far as i understood or what i tried
to do with my code is to define a register pair composed of two 8 bit
registers the way i described in my previous message. So R1R0 in WDREGS is
directly mapped into R0 and R1 of GPR8. Meaning that 2 GPR8 = 1 WDREG. Also,
R1R0 is the superreg of R1 and R0?

Incase i wasnt clear enough i'll expose a simple example using the common
known x86 arch.
AX is composed by AL and AH (AX and AH are subregs of AX), now assume x86
can only add regs of 8 bits, so if a i16 number is stored in AX it should
get splitted into AL and AH so that the 8 bit addition pattern is matched.

If this is what you meant from a start sorry for the noise, since that wasnt
clear to me. Adding that transform to your reg allocator would be great
since i cant continue writing the backend until this issue is resolved. I
think this case should be handled by all register allocators implemented in
LLVM, so maybe it can be factored out before using an specific allocation
I have noticed that some changes have been done in all
registerinfo.tdbackend files concerning subreg classes and indices
since v2.7, do these
changes fix this problem or they didnt have any functional changes?


2010/8/31 Jeff Kunkel <jdkunk3 at gmail.com>

> Hi, I don't know if anyone else has responded to your question, but I am
> currently in development of a register allocator. Thank you for bringing up
> the fact that sub-register classes may be larger than their super-register.
> If this remains the case, I for one will write a transform for my allocator
> which will make the 16 bit register the super-register with the 8bit as the
> sub. At least for my allocator, this will simplify writing the algorithm
> without changing the mechanics.
> I wonder, how many other targets have sub-registers larger than
> super-registers?
> Thanks,
> Jeff Kunkel
> On Sun, Aug 29, 2010 at 12:04 PM, Borja Ferrer <borja.ferav at gmail.com>wrote:
>> 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.
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100831/b5cb3d2f/attachment.html>

More information about the llvm-dev mailing list