Robert Schilling via llvm-dev
2017-Feb-13 09:36 UTC
[llvm-dev] 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
Tim Northover via llvm-dev
2017-Feb-13 15:42 UTC
[llvm-dev] ARM Backend: Emit conditional move
Hi Robert, On 13 February 2017 at 09:36, Robert Schilling via llvm-dev <llvm-dev at 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' bitMOVr 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.