[X86][FastIsel] Teach how to select scalar integer to float/double conversions.

This patch teaches fast-isel how to select a (V)CVTSI2SSrr for an integer to 
float conversion, and how to select a (V)CVTSI2SDrr for an integer to double
conversion.

Added test 'fast-isel-int-float-conversion.ll'.

Differential Revision: http://reviews.llvm.org/D7698


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229589 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrea Di Biagio 2015-02-17 23:40:58 +00:00
parent 3b75cfe179
commit b3ff6a88b6
2 changed files with 93 additions and 0 deletions

View File

@ -129,6 +129,7 @@ private:
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 @@ bool X86FastISel::X86SelectSelect(const Instruction *I) {
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 @@ X86FastISel::fastSelectInstruction(const Instruction *I) {
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());

View File

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