diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 48cd5f4b574..e30cee3dbd4 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -162,7 +162,7 @@ class ARMFastISel : public FastISel { bool SelectFPTrunc(const Instruction *I); bool SelectBinaryOp(const Instruction *I, unsigned ISDOpcode); bool SelectIToFP(const Instruction *I, bool isZExt); - bool SelectFPToSI(const Instruction *I); + bool SelectFPToI(const Instruction *I, bool isZExt); bool SelectSDiv(const Instruction *I); bool SelectSRem(const Instruction *I); bool SelectCall(const Instruction *I, const char *IntrMemName); @@ -1578,7 +1578,7 @@ bool ARMFastISel::SelectIToFP(const Instruction *I, bool isZExt) { return true; } -bool ARMFastISel::SelectFPToSI(const Instruction *I) { +bool ARMFastISel::SelectFPToI(const Instruction *I, bool isZExt) { // Make sure we have VFP. if (!Subtarget->hasVFP2()) return false; @@ -1592,11 +1592,11 @@ bool ARMFastISel::SelectFPToSI(const Instruction *I) { unsigned Opc; Type *OpTy = I->getOperand(0)->getType(); - if (OpTy->isFloatTy()) Opc = ARM::VTOSIZS; - else if (OpTy->isDoubleTy()) Opc = ARM::VTOSIZD; + if (OpTy->isFloatTy()) Opc = isZExt ? ARM::VTOUIZS : ARM::VTOSIZS; + else if (OpTy->isDoubleTy()) Opc = isZExt ? ARM::VTOUIZD : ARM::VTOSIZD; else return false; - // f64->s32 or f32->s32 both need an intermediate f32 reg. + // f64->s32/u32 or f32->s32/u32 both need an intermediate f32 reg. unsigned ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32)); AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), ResultReg) @@ -2453,7 +2453,9 @@ bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { case Instruction::UIToFP: return SelectIToFP(I, /*isZExt*/ true); case Instruction::FPToSI: - return SelectFPToSI(I); + return SelectFPToI(I, /*isZExt*/ false); + case Instruction::FPToUI: + return SelectFPToI(I, /*isZExt*/ true); case Instruction::FAdd: return SelectBinaryOp(I, ISD::FADD); case Instruction::FSub: diff --git a/test/CodeGen/ARM/fast-isel-conversion.ll b/test/CodeGen/ARM/fast-isel-conversion.ll index f33c98d7dfc..686ccad029d 100644 --- a/test/CodeGen/ARM/fast-isel-conversion.ll +++ b/test/CodeGen/ARM/fast-isel-conversion.ll @@ -188,3 +188,55 @@ entry: store double %conv, double* %b.addr, align 8 ret void } + +; Test fptosi + +define void @fptosi_float(float %a) nounwind ssp { +entry: +; ARM: fptosi_float +; ARM: vcvt.s32.f32 s0, s0 +; THUMB: fptosi_float +; THUMB: vcvt.s32.f32 s0, s0 + %b.addr = alloca i32, align 4 + %conv = fptosi float %a to i32 + store i32 %conv, i32* %b.addr, align 4 + ret void +} + +define void @fptosi_double(double %a) nounwind ssp { +entry: +; ARM: fptosi_double +; ARM: vcvt.s32.f64 s0, d16 +; THUMB: fptosi_double +; THUMB: vcvt.s32.f64 s0, d16 + %b.addr = alloca i32, align 8 + %conv = fptosi double %a to i32 + store i32 %conv, i32* %b.addr, align 8 + ret void +} + +; Test fptoui + +define void @fptoui_float(float %a) nounwind ssp { +entry: +; ARM: fptoui_float +; ARM: vcvt.u32.f32 s0, s0 +; THUMB: fptoui_float +; THUMB: vcvt.u32.f32 s0, s0 + %b.addr = alloca i32, align 4 + %conv = fptoui float %a to i32 + store i32 %conv, i32* %b.addr, align 4 + ret void +} + +define void @fptoui_double(double %a) nounwind ssp { +entry: +; ARM: fptoui_double +; ARM: vcvt.u32.f64 s0, d16 +; THUMB: fptoui_double +; THUMB: vcvt.u32.f64 s0, d16 + %b.addr = alloca i32, align 8 + %conv = fptoui double %a to i32 + store i32 %conv, i32* %b.addr, align 8 + ret void +}