Skip to content

Commit

Permalink
[arm-fast-isel] Add support for shl, lshr, and ashr.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161230 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jush31666 committed Aug 3, 2012
1 parent 8b52c85 commit 2946549
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
62 changes: 62 additions & 0 deletions lib/Target/ARM/ARMFastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<ConstantInt>(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) {

Expand Down Expand Up @@ -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;
Expand Down
50 changes: 50 additions & 0 deletions test/CodeGen/ARM/fast-isel-shifter.ll
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 2946549

Please sign in to comment.