selecting select_cc

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:

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, $trueVal

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.

Hopefully, it's no more difficult for LLVM to generate.

Cheers,

Ralph.

PS. It's great to see LLVM gaining an ARM backend.

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 :slight_smile:
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 :slight_smile:

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

If you find any good references to optimization manuals, etc. that
aren't mentioned there, please send them along.

In

there is a collection of documents regarding the ABI for the ARM architecture.

Best Regards,
Rafael

Thanks, added.