I am trying to add support for select_cc. In ARM it can be implemented with: mov $dst, $falseVal cmp $a, $b moveq $dst, $trueVal My current strategy is to expand select_cc in two ARM nodes: ARM::SELECT and ARM::CMP. The two nodes would be connected by a flag edge. ARM::CMP would then expand to "cmp $a, $b". This instruction has no results. It only alters the CPSR (current program status register). ARM::SELECT would expand to a conditional move (moveq for example). Something similar is done by the Alpha backend: --------------------------------------------------------------------------------------------- def CMOVEQ : OForm4< 0x11, 0x24, "cmoveq $RCOND,$RTRUE,$RDEST", [(set GPRC:$RDEST, (select (seteq GPRC:$RCOND, 0), GPRC:$RTRUE, GPRC:$RFALSE))], s_cmov>; ---------------------------------------------------------------------------------------------- One thing that I don't understand is how the $RFALSE value is used. $RDEST must equal $RFALSE before the cmov is executed. How does the Alpha backend enforces this? Thanks, Rafael
On Mon, 2006-08-21 at 17:09 -0300, Rafael Espíndola wrote:> I am trying to add support for select_cc. In ARM it can be implemented with: > > mov $dst, $falseVal > cmp $a, $b > moveq $dst, $trueVal > > My current strategy is to expand select_cc in two ARM nodes: > ARM::SELECT and ARM::CMP. The two nodes would be connected by a flag > edge. > > ARM::CMP would then expand to "cmp $a, $b". This instruction has no > results. It only alters the CPSR (current program status register). > > ARM::SELECT would expand to a conditional move (moveq for example). > Something similar is done by the Alpha backend: > > --------------------------------------------------------------------------------------------- > def CMOVEQ : OForm4< 0x11, 0x24, "cmoveq $RCOND,$RTRUE,$RDEST", > [(set GPRC:$RDEST, (select (seteq GPRC:$RCOND, 0), > GPRC:$RTRUE, GPRC:$RFALSE))], s_cmov>; > ---------------------------------------------------------------------------------------------- > > One thing that I don't understand is how the $RFALSE value is used. > $RDEST must equal $RFALSE before the cmov is executed. How does the > Alpha backend enforces this?That instruction is marked as a two address instruction (see AlphaInstrFormats.td). This forces the register allocator to allocate the first two virtual registers to the same physical register. The Operand list for that class is defined as: let OperandList = (ops GPRC:$RDEST, GPRC:$RFALSE, GPRC:$RTRUE, GPRC: $RCOND); so along with: let isTwoAddress = 1; RDEST and RFALSE are the same physical register (post allocation). I seem to recall that this is necessary so that a virtual register is not used and defined by the same instruction. Andrew
Hi Rafael,> I am trying to add support for select_cc. In ARM it can be implemented > with: > > mov $dst, $falseVal > cmp $a, $b > moveq $dst, $trueValThe more normal ARM code, as produced by assembly writers and compilers that I've seen, is cmp $a, $b moveq $dst, $trueVal movne $dst, $falseVal e.g. at the end of a function returning r0 orr r0, r0, #0x40 cmp r0, #0xfe moveq r0, #1 movne r0, #0 since only one mov instruction is executed and the logic is clearer to the reader. I may be out of date here, but a skipped instruction takes one S-cycle whereas your always executed mov may take two S-cycles if a register-controlled shift is used, and more if $dst is the PC. Hopefully, it's no more difficult for LLVM to generate. Cheers, Ralph. PS. It's great to see LLVM gaining an ARM backend.
On 8/22/06, Ralph Corderoy <ralph at inputplus.co.uk> wrote:> > Hi Rafael,Hi Ralph,> The more normal ARM code, as produced by assembly writers and compilers > that I've seen, is > > cmp $a, $b > moveq $dst, $trueVal > movne $dst, $falseVal > > e.g. at the end of a function returning r0 > > orr r0, r0, #0x40 > cmp r0, #0xfe > moveq r0, #1 > movne r0, #0 > > since only one mov instruction is executed and the logic is clearer to > the reader. I may be out of date here, but a skipped instruction takes > one S-cycle whereas your always executed mov may take two S-cycles if a > register-controlled shift is used, and more if $dst is the PC.Thanks for the information! I implemented the "mov + moveq" because it was easier to copy from the alpha backend :-) One advantage of using "mov + moveq" is that the mov might be coalesced. I think that we need some benchmark to find the best option.> Hopefully, it's no more difficult for LLVM to generate.It shouldn't be hard. For now, I will add a note to the backend. When it is mature enough to run benchmarks I will come back to it.> Cheers, > > > Ralph.Best Regards, Rafael> PS. It's great to see LLVM gaining an ARM backend.It is very fun to write one :-)
On Mon, Aug 21, 2006 at 05:09:10PM -0300, Rafael Espíndola wrote:> I am trying to add support for select_cc. In ARM it can be implemented > with:[snip] Speaking of new backends, there is a document that lists some architecture docs: http://llvm.org/docs/CompilerWriterInfo.html . There is a link to the GCC library as well, which is rather extensive and may be helpful in writing a new backend. If you find any good references to optimization manuals, etc. that aren't mentioned there, please send them along. -- Misha Brukman :: http://misha.brukman.net
> If you find any good references to optimization manuals, etc. that > aren't mentioned there, please send them along.In http://www.arm.com/products/DevTools/ABI.html there is a collection of documents regarding the ABI for the ARM architecture. Best Regards, Rafael