Index: llvm/trunk/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FastISel.cpp +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp @@ -129,6 +129,7 @@ bool X86SelectFPExt(const Instruction *I); bool X86SelectFPTrunc(const Instruction *I); + bool X86SelectSIToFP(const Instruction *I); const X86InstrInfo *getInstrInfo() const { return Subtarget->getInstrInfo(); @@ -2005,6 +2006,51 @@ return false; } +bool X86FastISel::X86SelectSIToFP(const Instruction *I) { + if (!I->getOperand(0)->getType()->isIntegerTy(32)) + return false; + + // Select integer to float/double conversion. + unsigned OpReg = getRegForValue(I->getOperand(0)); + if (OpReg == 0) + return false; + + bool HasAVX = Subtarget->hasAVX(); + const TargetRegisterClass *RC = nullptr; + unsigned Opcode; + + if (I->getType()->isDoubleTy() && X86ScalarSSEf64) { + // sitofp int -> double + Opcode = HasAVX ? X86::VCVTSI2SDrr : X86::CVTSI2SDrr; + RC = &X86::FR64RegClass; + } else if (I->getType()->isFloatTy() && X86ScalarSSEf32) { + // sitofp int -> float + Opcode = HasAVX ? X86::VCVTSI2SSrr : X86::CVTSI2SSrr; + RC = &X86::FR32RegClass; + } else + return false; + + + unsigned ImplicitDefReg = 0; + if (HasAVX) { + ImplicitDefReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg); + } + + const MCInstrDesc &II = TII.get(Opcode); + OpReg = constrainOperandRegClass(II, OpReg, (HasAVX ? 2 : 1)); + + unsigned ResultReg = createResultReg(RC); + MachineInstrBuilder MIB; + MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg); + if (ImplicitDefReg) + MIB.addReg(ImplicitDefReg, RegState::Kill); + MIB.addReg(OpReg); + updateValueMap(I, ResultReg); + return true; +} + // Helper method used by X86SelectFPExt and X86SelectFPTrunc. bool X86FastISel::X86SelectFPExtOrFPTrunc(const Instruction *I, unsigned TargetOpc, @@ -3055,6 +3101,8 @@ return X86SelectFPExt(I); case Instruction::FPTrunc: return X86SelectFPTrunc(I); + case Instruction::SIToFP: + return X86SelectSIToFP(I); case Instruction::IntToPtr: // Deliberate fall-through. case Instruction::PtrToInt: { EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); Index: llvm/trunk/test/CodeGen/X86/fast-isel-int-float-conversion.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/fast-isel-int-float-conversion.ll +++ llvm/trunk/test/CodeGen/X86/fast-isel-int-float-conversion.ll @@ -0,0 +1,45 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown -mcpu=generic -mattr=+sse2 -O0 --fast-isel-abort < %s | FileCheck %s --check-prefix=ALL --check-prefix=SSE2 +; RUN: llc -mtriple=x86_64-unknown-unknown -mcpu=generic -mattr=+avx -O0 --fast-isel-abort < %s | FileCheck %s --check-prefix=ALL --check-prefix=AVX + + +define double @int_to_double_rr(i32 %a) { +; ALL-LABEL: int_to_double_rr: +; SSE2: cvtsi2sdl %edi, %xmm0 +; AVX: vcvtsi2sdl %edi, %xmm0, %xmm0 +; ALL-NEXT: ret +entry: + %0 = sitofp i32 %a to double + ret double %0 +} + +define double @int_to_double_rm(i32* %a) { +; ALL-LABEL: int_to_double_rm: +; SSE2: cvtsi2sdl (%rdi), %xmm0 +; AVX: vcvtsi2sdl (%rdi), %xmm0, %xmm0 +; ALL-NEXT: ret +entry: + %0 = load i32* %a + %1 = sitofp i32 %0 to double + ret double %1 +} + +define float @int_to_float_rr(i32 %a) { +; ALL-LABEL: int_to_float_rr: +; SSE2: cvtsi2ssl %edi, %xmm0 +; AVX: vcvtsi2ssl %edi, %xmm0, %xmm0 +; ALL-NEXT: ret +entry: + %0 = sitofp i32 %a to float + ret float %0 +} + +define float @int_to_float_rm(i32* %a) { +; ALL-LABEL: int_to_float_rm: +; SSE2: cvtsi2ssl (%rdi), %xmm0 +; AVX: vcvtsi2ssl (%rdi), %xmm0, %xmm0 +; ALL-NEXT: ret +entry: + %0 = load i32* %a + %1 = sitofp i32 %0 to float + ret float %1 +}