From 2946549a2817681f9117662139cc0f2241939965 Mon Sep 17 00:00:00 2001 From: Jush Lu Date: Fri, 3 Aug 2012 02:37:48 +0000 Subject: [PATCH] [arm-fast-isel] Add support for shl, lshr, and ashr. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161230 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMFastISel.cpp | 62 +++++++++++++++++++++++++++++++++++ test/CodeGen/ARM/fast-isel-shifter.ll | 50 ++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 test/CodeGen/ARM/fast-isel-shifter.ll diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index ca8ffea9fc0..29f90b768ee 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -167,6 +167,7 @@ class ARMFastISel : public FastISel { bool SelectRet(const Instruction *I); bool SelectTrunc(const Instruction *I); bool SelectIntExt(const Instruction *I); + bool SelectShift(const Instruction *I, ARM_AM::ShiftOpc ShiftTy); // Utility routines. private: @@ -2613,6 +2614,61 @@ bool ARMFastISel::SelectIntExt(const Instruction *I) { return true; } +bool ARMFastISel::SelectShift(const Instruction *I, + ARM_AM::ShiftOpc ShiftTy) { + // We handle thumb2 mode by target independent selector + // or SelectionDAG ISel. + if (isThumb2) + return false; + + // Only handle i32 now. + EVT DestVT = TLI.getValueType(I->getType(), true); + if (DestVT != MVT::i32) + return false; + + unsigned Opc = ARM::MOVsr; + unsigned ShiftImm; + Value *Src2Value = I->getOperand(1); + if (const ConstantInt *CI = dyn_cast(Src2Value)) { + ShiftImm = CI->getZExtValue(); + + // Fall back to selection DAG isel if the shift amount + // is zero or greater than the width of the value type. + if (ShiftImm == 0 || ShiftImm >=32) + return false; + + Opc = ARM::MOVsi; + } + + Value *Src1Value = I->getOperand(0); + unsigned Reg1 = getRegForValue(Src1Value); + if (Reg1 == 0) return false; + + unsigned Reg2; + if (Opc == ARM::MOVsr) { + Reg2 = getRegForValue(Src2Value); + if (Reg2 == 0) return false; + } + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(MVT::i32)); + if(ResultReg == 0) return false; + + MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg) + .addReg(Reg1); + + if (Opc == ARM::MOVsi) + MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, ShiftImm)); + else if (Opc == ARM::MOVsr) { + MIB.addReg(Reg2); + MIB.addImm(ARM_AM::getSORegOpc(ShiftTy, 0)); + } + + AddOptionalDefs(MIB); + UpdateValueMap(I, ResultReg); + return true; +} + // TODO: SoftFP support. bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { @@ -2673,6 +2729,12 @@ bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { case Instruction::ZExt: case Instruction::SExt: return SelectIntExt(I); + case Instruction::Shl: + return SelectShift(I, ARM_AM::lsl); + case Instruction::LShr: + return SelectShift(I, ARM_AM::lsr); + case Instruction::AShr: + return SelectShift(I, ARM_AM::asr); default: break; } return false; diff --git a/test/CodeGen/ARM/fast-isel-shifter.ll b/test/CodeGen/ARM/fast-isel-shifter.ll new file mode 100644 index 00000000000..111818b289e --- /dev/null +++ b/test/CodeGen/ARM/fast-isel-shifter.ll @@ -0,0 +1,50 @@ +; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARM + +define i32 @shl() nounwind ssp { +entry: +; ARM: shl +; ARM: lsl r0, r0, #2 + %shl = shl i32 -1, 2 + ret i32 %shl +} + +define i32 @shl_reg(i32 %src1, i32 %src2) nounwind ssp { +entry: +; ARM: shl_reg +; ARM: lsl r0, r0, r1 + %shl = shl i32 %src1, %src2 + ret i32 %shl +} + +define i32 @lshr() nounwind ssp { +entry: +; ARM: lshr +; ARM: lsr r0, r0, #2 + %lshr = lshr i32 -1, 2 + ret i32 %lshr +} + +define i32 @lshr_reg(i32 %src1, i32 %src2) nounwind ssp { +entry: +; ARM: lshr_reg +; ARM: lsr r0, r0, r1 + %lshr = lshr i32 %src1, %src2 + ret i32 %lshr +} + +define i32 @ashr() nounwind ssp { +entry: +; ARM: ashr +; ARM: asr r0, r0, #2 + %ashr = ashr i32 -1, 2 + ret i32 %ashr +} + +define i32 @ashr_reg(i32 %src1, i32 %src2) nounwind ssp { +entry: +; ARM: ashr_reg +; ARM: asr r0, r0, r1 + %ashr = ashr i32 %src1, %src2 + ret i32 %ashr +} + -- 2.11.0