[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
This commit is contained in:
Jush Lu 2012-08-03 02:37:48 +00:00
parent 8b52c855b3
commit 2946549a28
2 changed files with 112 additions and 0 deletions

View File

@ -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<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) {
@ -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;

View File

@ -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
}