From 7ddd63ce4e601d1339c9ef1acf0423742c16ba93 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 11 Nov 2011 06:20:39 +0000 Subject: [PATCH] Add support for using immediates with select instructions. rdar://10412592 llvm-svn: 144376 --- llvm/lib/Target/ARM/ARMFastISel.cpp | 48 +++++++++-- llvm/test/CodeGen/ARM/fast-isel-select.ll | 99 +++++++++++++++++++++++ 2 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/fast-isel-select.ll diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp index c2f0a7135d9a..de12db7a8fa2 100644 --- a/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -1491,17 +1491,49 @@ bool ARMFastISel::SelectSelect(const Instruction *I) { if (CondReg == 0) return false; unsigned Op1Reg = getRegForValue(I->getOperand(1)); if (Op1Reg == 0) return false; - unsigned Op2Reg = getRegForValue(I->getOperand(2)); - if (Op2Reg == 0) return false; - unsigned CmpOpc = isThumb2 ? ARM::t2TSTri : ARM::TSTri; + // Check to see if we can use an immediate in the conditional move. + int Imm = 0; + bool UseImm = false; + bool isNegativeImm = false; + if (const ConstantInt *ConstInt = dyn_cast(I->getOperand(2))) { + assert (VT == MVT::i32 && "Expecting an i32."); + Imm = (int)ConstInt->getValue().getZExtValue(); + if (Imm < 0) { + isNegativeImm = true; + Imm = ~Imm; + } + UseImm = isThumb2 ? (ARM_AM::getT2SOImmVal(Imm) != -1) : + (ARM_AM::getSOImmVal(Imm) != -1); + } + + unsigned Op2Reg; + if (!UseImm) { + Op2Reg = getRegForValue(I->getOperand(2)); + if (Op2Reg == 0) return false; + } + + unsigned CmpOpc = isThumb2 ? ARM::t2CMPri : ARM::CMPri; AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc)) - .addReg(CondReg).addImm(1)); + .addReg(CondReg).addImm(0)); + + unsigned MovCCOpc; + if (!UseImm) { + MovCCOpc = isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr; + } else { + if (!isNegativeImm) { + MovCCOpc = isThumb2 ? ARM::t2MOVCCi : ARM::MOVCCi; + } else { + MovCCOpc = isThumb2 ? ARM::t2MVNCCi : ARM::MVNCCi; + } + } unsigned ResultReg = createResultReg(RC); - unsigned MovCCOpc = isThumb2 ? ARM::t2MOVCCr : ARM::MOVCCr; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(MovCCOpc), ResultReg) - .addReg(Op1Reg).addReg(Op2Reg) - .addImm(ARMCC::EQ).addReg(ARM::CPSR); + if (!UseImm) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(MovCCOpc), ResultReg) + .addReg(Op2Reg).addReg(Op1Reg).addImm(ARMCC::NE).addReg(ARM::CPSR); + else + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(MovCCOpc), ResultReg) + .addReg(Op1Reg).addImm(Imm).addImm(ARMCC::EQ).addReg(ARM::CPSR); UpdateValueMap(I, ResultReg); return true; } diff --git a/llvm/test/CodeGen/ARM/fast-isel-select.ll b/llvm/test/CodeGen/ARM/fast-isel-select.ll new file mode 100644 index 000000000000..9ac63d623586 --- /dev/null +++ b/llvm/test/CodeGen/ARM/fast-isel-select.ll @@ -0,0 +1,99 @@ +; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-darwin | FileCheck %s --check-prefix=ARM +; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefix=THUMB + +define i32 @t1(i1 %c) nounwind readnone { +entry: +; ARM: t1 +; ARM: movw r{{[1-9]}}, #10 +; ARM: cmp r0, #0 +; ARM: moveq r{{[1-9]}}, #20 +; ARM: mov r0, r{{[1-9]}} +; THUMB: t1 +; THUMB: movs r{{[1-9]}}, #10 +; THUMB: movt r{{[1-9]}}, #0 +; THUMB: cmp r0, #0 +; THUMB: it eq +; THUMB: moveq r{{[1-9]}}, #20 +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 10, i32 20 + ret i32 %0 +} + +define i32 @t2(i1 %c, i32 %a) nounwind readnone { +entry: +; ARM: t2 +; ARM: cmp r0, #0 +; ARM: moveq r{{[1-9]}}, #20 +; ARM: mov r0, r{{[1-9]}} +; THUMB: t2 +; THUMB: cmp r0, #0 +; THUMB: it eq +; THUMB: moveq r{{[1-9]}}, #20 +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 %a, i32 20 + ret i32 %0 +} + +define i32 @t3(i1 %c, i32 %a, i32 %b) nounwind readnone { +entry: +; ARM: t3 +; ARM: cmp r0, #0 +; ARM: movne r{{[1-9]}}, r{{[1-9]}} +; ARM: mov r0, r{{[1-9]}} +; THUMB: t3 +; THUMB: cmp r0, #0 +; THUMB: it ne +; THUMB: movne r{{[1-9]}}, r{{[1-9]}} +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 %a, i32 %b + ret i32 %0 +} + +define i32 @t4(i1 %c) nounwind readnone { +entry: +; ARM: t4 +; ARM: mvn r{{[1-9]}}, #9 +; ARM: cmp r0, #0 +; ARM: mvneq r{{[1-9]}}, #0 +; ARM: mov r0, r{{[1-9]}} +; THUMB: t4 +; THUMB: movw r{{[1-9]}}, #65526 +; THUMB: movt r{{[1-9]}}, #65535 +; THUMB: cmp r0, #0 +; THUMB: it eq +; THUMB: mvneq r{{[1-9]}}, #0 +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 -10, i32 -1 + ret i32 %0 +} + +define i32 @t5(i1 %c, i32 %a) nounwind readnone { +entry: +; ARM: t5 +; ARM: cmp r0, #0 +; ARM: mvneq r{{[1-9]}}, #1 +; ARM: mov r0, r{{[1-9]}} +; THUMB: t5 +; THUMB: cmp r0, #0 +; THUMB: it eq +; THUMB: mvneq r{{[1-9]}}, #1 +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 %a, i32 -2 + ret i32 %0 +} + +; Check one large negative immediates. +define i32 @t6(i1 %c, i32 %a) nounwind readnone { +entry: +; ARM: t6 +; ARM: cmp r0, #0 +; ARM: mvneq r{{[1-9]}}, #978944 +; ARM: mov r0, r{{[1-9]}} +; THUMB: t6 +; THUMB: cmp r0, #0 +; THUMB: it eq +; THUMB: mvneq r{{[1-9]}}, #978944 +; THUMB: mov r0, r{{[1-9]}} + %0 = select i1 %c, i32 %a, i32 -978945 + ret i32 %0 +}