ARM Backend: Emit conditional move

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

Hi Robert,

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.

Correction to the MOVi BuildMI call:

          .add(predOps(ARMCC::EQ)

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

Tim.