[LLVMdev] Register Pairing

Jeff Kunkel jdkunk3 at gmail.com
Mon Nov 29 10:16:09 PST 2010

Can this not be done with a pattern? In <name>InstrInfo.td one could build a
pattern in functional pseudocode like

def Mov8Mov8ToMov16 : (8 bit register move, r1, r2), (8 bit register move,
r3, r4) may be reduced to (16 bit register move, r1,r2, r3,r4).

However, your case is a bit more complicated than the generic case. The
pattern would have to have a constraint. So it may be worth extending
patterns one is able to define in <..>InstrInfo.td to allow for conditional

def Mov8Mov8ToMov16 : (8 bit register move, r1, r2), (8 bit register move,
r3, r4) may be reduced to (16 bit register move, r1,r2, r3,r4) if the
conditional <function name> is satisfied. Where the function name takes in
as many parameters as there are inputs. For this case the function would
take 6 parameters (first reg class, r1, r2, second reg class, r3, r4 ).

- My 2 cents
- Jeff Kunkel

On Sat, Nov 27, 2010 at 11:56 AM, Borja Ferrer <borja.ferav at gmail.com>wrote:

> Hello, some months ago i wrote to the mailing list asking some questions
> about register pairing, i've been experimenting several things with the help
> i got back then.
> Some background first: this issue is for a backend for an 8bit
> microcontroller with only 8bit regs, however it has a few 16bit instructions
> that only work with fixed register pairs, so it doesnt allow all
> combinations of regs. This introduces some problems because if data wider
> than 8bits is expanded into 8bit operations the 16bit instructions never get
> selected, also the reg allocator should allocate adjacent regs to form the
> pairs. The most important 16 bit instruction is data movement, this
> instruction can move register pairs in a single cycle, doing something like
> this:
> mov r25, r23
> mov r24, r22
> into:
> movw r25:r24, r23:r22
> The key point here is that the movw instruction can only move data of fixed
> pairs in this way. movw Rdest+1:Rdest, Rorig+1:Rorig, so movw R25:R23,
> R21:R18 is illegal because registers pairs aren't adjacent.
> Explaining this as if it was for x86 may make things more clear. Suppose we
> only have 8bit regs (ah, al, cl, ch, bl, bh, etc...) with 8 bit instructions
> and a few 16 bit instrs that only work with ax, bx, cx,.... We could pair
> ah:al to form ax, and so on. Then we have a movw instruction that is able to
> work with reg pairs, such as ax, bx, cx, etc... This way if we store a short
> in ah:al we could copy it into another pair, but storing it into al:cl would
> be bad because movw wouldnt be emitted. Also these reg pairs would be stored
> in a pseudo reg class so the 16 bit intrs would be emitted, otherwise none
> of them would be produced.
> Going back to my case I want to favor storing 16bit or wider data in
> adjacent regs to favor the insertion of this instruction like
> HARD_REGNO_MODE_OK in gcc. To overcome this problem and to select 16bit
> instructions automatically by LLVM i thought on working always with 16 bit
> register pairs. I created a pseudo reg class that contains the reg pairs
> marking each pair with its 2 subregs of 8 bits. Then i marked the i16 type
> legal with addRegisterClass(), although this is nearly a lie because i16 is
> only legal in a few specific cases, it makes LLVM think that working with
> the pairs is fine.
> Now for example to perform a 16 bit sum consider this code:
> typedef unsigned short t;
> t foo(t a, t b, t c)
> {
>     return a+b;
> }
> Incoming args come in register pairs, split them into the 8bit subregs
> perform the addition and combine them again into the pair ready for the next
> operation, in this case we're returning the result. This gives me this code
> before instr sel:
> # Machine code for function foo:
> Function Live Ins: %R25R24 in reg%16384, %R23R22 in reg%16385
> Function Live Outs: %R25R24
> BB#0: derived from LLVM BB %entry
>     Live Ins: %R25R24 %R23R22
>     %reg16385<def> = COPY %R23R22; WDREGS:%reg16385 // COPY B
>     %reg16384<def> = COPY %R25R24; WDREGS:%reg16384  //  COPY A
>     %reg16387<def> = COPY %reg16384:ssub_0; GPR8:%reg16387 WDREGS:%reg16384
>     %reg16388<def> = COPY %reg16385:ssub_0; GPR8:%reg16388 WDREGS:%reg16385
>     %reg16389<def> = COPY %reg16384:ssub_1; GPR8:%reg16389 WDREGS:%reg16384
>     %reg16390<def> = COPY %reg16385:ssub_1; GPR8:%reg16390 WDREGS:%reg16385
>     %reg16391<def> = ADDRdRr %reg16388, %reg16387<kill>, %SREG<imp-def>;
> GPR8:%reg16391,16388,16387 // ADD LO BYTES
>     %reg16392<def> = ADCRdRr %reg16390, %reg16389<kill>,
> %SREG<imp-def,dead>, %SREG<imp-use>; GPR8:%reg16392,16390,16389 // ADDC HI
>     %reg16393<def> = REG_SEQUENCE %reg16391<kill>, ssub_0, %reg16392<kill>,
> ssub_1; WDREGS:%reg16393 GPR8:%reg16391,16392 // COMBINE INTO REG PAIR AGAIN
>     %R25R24<def> = COPY %reg16393; WDREGS:%reg16393 // COPY REG PAIR INTO
>     RET
> This is fine until we get to the register allocation stage, there it does:
> BB#0: derived from LLVM BB %entry
>     Live Ins: %R25R24 %R23R22
>     %R18<def> = COPY %R24
>     %R19<def> = COPY %R25
>     %R24<def> = COPY %R22<kill>, %R25R24<imp-def>
>     %R24<def> = ADDRdRr %R24, %R18<kill>, %SREG<imp-def>
>     %R25<def> = COPY %R23<kill>
>     %R25<def> = ADCRdRr %R25, %R19<kill>, %SREG<imp-def,dead>,
> %SREG<imp-use,kill>
>     RET %R25R24<imp-use,kill>
> Here instead of splitting the pair into its own subregs, it's copying each
> subreg into r18 and r19 making useless movements.
> The optimal code should be:
> add r24, r22
> adc r25, r23
> So my first question would be how to solve this?
> And going on further, is this the correct way to model the pairs to get the
> behaviour i need, or is there a better and direct way of handling this? You
> can think of the x86 example i wrote before.
> Thanks for your help.
> _______________________________________________
> 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/20101129/07dc2903/attachment.html>

More information about the llvm-dev mailing list