Can this not be done with a pattern? In <name>InstrInfo.td one could build a pattern in functional pseudocode like<div><br></div><div>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). </div>
<div><br></div><div>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 cases. </div>
<div><div><br></div><div>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 ).</div>
<div><br></div><div>- My 2 cents</div><div>- Jeff Kunkel</div><div><br><div><br><div class="gmail_quote">On Sat, Nov 27, 2010 at 11:56 AM, Borja Ferrer <span dir="ltr"><<a href="mailto:borja.ferav@gmail.com">borja.ferav@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">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. <br>
<br>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:<br>

mov r25, r23<br>mov r24, r22<br>into:<br>movw r25:r24, r23:r22<br>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.<br>

<br>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.<br>

<br>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. <br>

Now for example to perform a 16 bit sum consider this code:<br>typedef unsigned short t;<br>t foo(t a, t b, t c)<br>{<br>    return a+b;<br>}<br>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:<br>

# Machine code for function foo:<br>Function Live Ins: %R25R24 in reg%16384, %R23R22 in reg%16385<br>Function Live Outs: %R25R24<br><br>BB#0: derived from LLVM BB %entry<br>    Live Ins: %R25R24 %R23R22<br>    %reg16385<def> = COPY %R23R22; WDREGS:%reg16385 // COPY B<br>

    %reg16384<def> = COPY %R25R24; WDREGS:%reg16384  //  COPY A<br>    %reg16387<def> = COPY %reg16384:ssub_0; GPR8:%reg16387 WDREGS:%reg16384 // EXTRACT LO BYTE OF A<br>    %reg16388<def> = COPY %reg16385:ssub_0; GPR8:%reg16388 WDREGS:%reg16385 // EXTRACT LO BYTE OF B<br>

    %reg16389<def> = COPY %reg16384:ssub_1; GPR8:%reg16389 WDREGS:%reg16384 // EXTRACT HI BYTE OF A<br>    %reg16390<def> = COPY %reg16385:ssub_1; GPR8:%reg16390 WDREGS:%reg16385 // EXTRACT HI BYTE OF B<br>    %reg16391<def> = ADDRdRr %reg16388, %reg16387<kill>, %SREG<imp-def>; GPR8:%reg16391,16388,16387 // ADD LO BYTES<br>

    %reg16392<def> = ADCRdRr %reg16390, %reg16389<kill>, %SREG<imp-def,dead>, %SREG<imp-use>; GPR8:%reg16392,16390,16389 // ADDC HI BYTES<br>    %reg16393<def> = REG_SEQUENCE %reg16391<kill>, ssub_0, %reg16392<kill>, ssub_1; WDREGS:%reg16393 GPR8:%reg16391,16392 // COMBINE INTO REG PAIR AGAIN<br>

    %R25R24<def> = COPY %reg16393; WDREGS:%reg16393 // COPY REG PAIR INTO RETURN REG.<br>    RET<br><br>This is fine until we get to the register allocation stage, there it does:<br>BB#0: derived from LLVM BB %entry<br>

    Live Ins: %R25R24 %R23R22<br>    %R18<def> = COPY %R24<br>    %R19<def> = COPY %R25<br>    %R24<def> = COPY %R22<kill>, %R25R24<imp-def><br>    %R24<def> = ADDRdRr %R24, %R18<kill>, %SREG<imp-def><br>

    %R25<def> = COPY %R23<kill><br>    %R25<def> = ADCRdRr %R25, %R19<kill>, %SREG<imp-def,dead>, %SREG<imp-use,kill><br>    RET %R25R24<imp-use,kill><br><br>Here instead of splitting the pair into its own subregs, it's copying each subreg into r18 and r19 making useless movements.<br>

The optimal code should be:<br>add r24, r22<br>adc r25, r23<br><br>So my first question would be how to solve this?<br>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.<br>

<br>Thanks for your help.<br><br>
<br>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu" target="_blank">http://llvm.cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br>
<br></blockquote></div><br></div></div></div>