[llvm-dev] ARM Backend: Emit conditional move

71 views
Skip to first unread message

Robert Schilling via llvm-dev

unread,
Feb 13, 2017, 4:38:09 AM2/13/17
to llvm...@lists.llvm.org
Hi,

I'm trying to emit a conditional move in the ARM backend for a custom
intrinsic. Basically, I want to emit the following the following
instruction sequence:

cmp r0, r1
moveq r2, #1

To implement this, I first emit a compare instruction and then I'm
trying to emit the conditional move, which is failing.

BuildMI(&MBB, DL, TII->get(ARM::CMPrr))
.addReg(MI.getOperand(1).getReg())
.addReg(MI.getOperand(2).getReg())
.addImm(ARMCC::EQ);

BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVr),
MI.getOperand(0).getReg())
.addImm(ARMCC::EQ)
.addImm(1)
.addReg(0); // 's' bit

But with the last conditional move, I am a bit lost. The result of the
condional move should be saved in operand 0. Can someone help on how to
emit this instruction?

Cheers,
Robert
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Tim Northover via llvm-dev

unread,
Feb 13, 2017, 10:42:48 AM2/13/17
to Robert Schilling, LLVM Developers Mailing List
Hi Robert,

On 13 February 2017 at 09:36, Robert Schilling via llvm-dev


<llvm...@lists.llvm.org> wrote:
> BuildMI(&MBB, DL, TII->get(ARM::CMPrr))
> .addReg(MI.getOperand(1).getReg())
> .addReg(MI.getOperand(2).getReg())
> .addImm(ARMCC::EQ);

ARM comparisons don't need to know what kind of comparison they're
actually going to be used for. So that ARMCC::EQ is actually turning
this instruction from a "cmp ..." into a "cmpeq ..." (i.e. only
perform the comparison if a previous compare was "eq").

What you probably want (on trunk LLVM) for that last operand is
"add(predOps(ARMCC::AL))" where "AL" means always.

> BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVr),
> MI.getOperand(0).getReg())
> .addImm(ARMCC::EQ)
> .addImm(1)
> .addReg(0); // 's' bit

MOVr is a move between two registers, you want the "MOVi" (move
immediate) instruction instead. MOVi takes 3 operands relating to the
condition code (all after the immediate):

First, the options for whether this particular move should be
predicated (like the CMPrr) above. There are two of these operands,
first an ARMCC value, and then a register which should be 0 if you're
using ARMCC::AL and ARM::CPSR otherwise (this is used to track which
instructions actually use CPSR, and obviously an instruction that's
always executed doesn't). This is what the predOps does above.

Second, there's another register argument which is set based on
whether this instruction should *set* the CPSR flags register. Since
you don't want this, you should use 0 (== NoReg). In trunk you'd write
"add(condCodeOp())" for that.

Putting it all together I think this last one should be

BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi),
MI.getOperand(0).getReg())
.addImm(1)
.add(predOps(ARMCC::EQ)
.add(condCodeOp());

It's worth noting that this'll only work in ARM mode. Thumb mode has a
completely different set of instructions in LLVM, usually starting
with "t" or "t2".

Hope this helps.

Tim.

Tim Northover via llvm-dev

unread,
Feb 13, 2017, 10:44:06 AM2/13/17
to Robert Schilling, LLVM Developers Mailing List
Correction to the MOVi BuildMI call:

> .add(predOps(ARMCC::EQ)

Sorry, this should be "predOps(ARMCC::EQ, ARM::CPSR)".

Reply all
Reply to author
Forward
0 new messages