Implement floating point to integer conversion in mips fast-isel

Summary: Add the ability to convert 64 or 32 bit floating point values to integer in mips fast-isel

Test Plan:
fpintconv.ll
ran 4 flavors of test-suite with no errors, misp32 r1/r2 O0/O2

Reviewers: dsanders

Reviewed By: dsanders

Subscribers: llvm-commits, rfuhler, mcrosier

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219511 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reed Kotler 2014-10-10 17:00:46 +00:00
parent 68084538cb
commit f6e11eacdd
2 changed files with 104 additions and 1 deletions

View File

@ -48,6 +48,7 @@ class MipsFastISel final : public FastISel {
LLVMContext *Context;
bool TargetSupported;
bool UnsupportedFPMode;
public:
explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
@ -63,6 +64,7 @@ public:
TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
((Subtarget->hasMips32r2() || Subtarget->hasMips32()) &&
(Subtarget->isABI_O32())));
UnsupportedFPMode = Subtarget->isFP64bit();
}
bool fastSelectInstruction(const Instruction *I) override;
@ -82,6 +84,7 @@ private:
bool SelectTrunc(const Instruction *I);
bool SelectFPExt(const Instruction *I);
bool SelectFPTrunc(const Instruction *I);
bool SelectFPToI(const Instruction *I, bool IsSigned);
bool isTypeLegal(Type *Ty, MVT &VT);
bool isLoadTypeLegal(Type *Ty, MVT &VT);
@ -191,11 +194,15 @@ bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
break;
}
case MVT::f32: {
if (UnsupportedFPMode)
return false;
ResultReg = createResultReg(&Mips::FGR32RegClass);
Opc = Mips::LWC1;
break;
}
case MVT::f64: {
if (UnsupportedFPMode)
return false;
ResultReg = createResultReg(&Mips::AFGR64RegClass);
Opc = Mips::LDC1;
break;
@ -218,7 +225,7 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) {
MVT VT = CEVT.getSimpleVT();
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
return MaterializeFP(CFP, VT);
return (UnsupportedFPMode) ? 0 : MaterializeFP(CFP, VT);
else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
return MaterializeGV(GV, VT);
else if (isa<ConstantInt>(C))
@ -244,9 +251,13 @@ bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
Opc = Mips::SW;
break;
case MVT::f32:
if (UnsupportedFPMode)
return false;
Opc = Mips::SWC1;
break;
case MVT::f64:
if (UnsupportedFPMode)
return false;
Opc = Mips::SDC1;
break;
default:
@ -388,6 +399,8 @@ bool MipsFastISel::SelectRet(const Instruction *I) {
// Attempt to fast-select a floating-point extend instruction.
bool MipsFastISel::SelectFPExt(const Instruction *I) {
if (UnsupportedFPMode)
return false;
Value *Src = I->getOperand(0);
EVT SrcVT = TLI.getValueType(Src->getType(), true);
EVT DestVT = TLI.getValueType(I->getType(), true);
@ -409,6 +422,8 @@ bool MipsFastISel::SelectFPExt(const Instruction *I) {
// Attempt to fast-select a floating-point truncate instruction.
bool MipsFastISel::SelectFPTrunc(const Instruction *I) {
if (UnsupportedFPMode)
return false;
Value *Src = I->getOperand(0);
EVT SrcVT = TLI.getValueType(Src->getType(), true);
EVT DestVT = TLI.getValueType(I->getType(), true);
@ -481,6 +496,53 @@ bool MipsFastISel::SelectTrunc(const Instruction *I) {
return true;
}
// Attempt to fast-select a floating-point-to-integer conversion.
bool MipsFastISel::SelectFPToI(const Instruction *I, bool IsSigned) {
if (UnsupportedFPMode)
return false;
MVT DstVT, SrcVT;
if (!IsSigned)
return false; // We don't handle this case yet. There is no native
// instruction for this but it can be synthesized.
Type *DstTy = I->getType();
if (!isTypeLegal(DstTy, DstVT))
return false;
if (DstVT != MVT::i32)
return false;
Value *Src = I->getOperand(0);
Type *SrcTy = Src->getType();
if (!isTypeLegal(SrcTy, SrcVT))
return false;
if (SrcVT != MVT::f32 && SrcVT != MVT::f64)
return false;
unsigned SrcReg = getRegForValue(Src);
if (SrcReg == 0)
return false;
// Determine the opcode for the conversion, which takes place
// entirely within FPRs.
unsigned DestReg = createResultReg(&Mips::GPR32RegClass);
unsigned TempReg = createResultReg(&Mips::FGR32RegClass);
unsigned Opc;
if (SrcVT == MVT::f32)
Opc = Mips::TRUNC_W_S;
else
Opc = Mips::TRUNC_W_D32;
// Generate the convert.
EmitInst(Opc, TempReg).addReg(SrcReg);
EmitInst(Mips::MFC1, DestReg).addReg(TempReg);
updateValueMap(I, DestReg);
return true;
}
bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
if (!TargetSupported)
return false;
@ -502,11 +564,17 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) {
return SelectFPTrunc(I);
case Instruction::FPExt:
return SelectFPExt(I);
case Instruction::FPToSI:
return SelectFPToI(I, /*isSigned*/ true);
case Instruction::FPToUI:
return SelectFPToI(I, /*isSigned*/ false);
}
return false;
}
unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
if (UnsupportedFPMode)
return 0;
int64_t Imm = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (VT == MVT::f32) {
const TargetRegisterClass *RC = &Mips::FGR32RegClass;

View File

@ -0,0 +1,35 @@
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \
; RUN: < %s | FileCheck %s
; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \
; RUN: < %s | FileCheck %s
@f = global float 0x40D6E83280000000, align 4
@d = global double 0x4132D68780000000, align 8
@i_f = common global i32 0, align 4
@i_d = common global i32 0, align 4
@.str = private unnamed_addr constant [5 x i8] c"%i \0A\00", align 1
; Function Attrs: nounwind
define void @ifv() {
entry:
; CHECK-LABEL: .ent ifv
%0 = load float* @f, align 4
%conv = fptosi float %0 to i32
; CHECK: trunc.w.s $f[[REG:[0-9]+]], $f{{[0-9]+}}
; CHECK: mfc1 ${{[0-9]+}}, $f[[REG]]
store i32 %conv, i32* @i_f, align 4
ret void
}
; Function Attrs: nounwind
define void @idv() {
entry:
; CHECK-LABEL: .ent idv
%0 = load double* @d, align 8
%conv = fptosi double %0 to i32
; CHECK: trunc.w.d $f[[REG:[0-9]+]], $f{{[0-9]+}}
; CHECK: mfc1 ${{[0-9]+}}, $f[[REG]]
store i32 %conv, i32* @i_d, align 4
ret void
}