[llvm] r219511 - Implement floating point to integer conversion in mips fast-isel
Reed Kotler
rkotler at mips.com
Fri Oct 10 10:00:46 PDT 2014
Author: rkotler
Date: Fri Oct 10 12:00:46 2014
New Revision: 219511
URL: http://llvm.org/viewvc/llvm-project?rev=219511&view=rev
Log:
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
Added:
llvm/trunk/test/CodeGen/Mips/Fast-ISel/fpintconv.ll
Modified:
llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
Modified: llvm/trunk/lib/Target/Mips/MipsFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsFastISel.cpp?rev=219511&r1=219510&r2=219511&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsFastISel.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsFastISel.cpp Fri Oct 10 12:00:46 2014
@@ -48,6 +48,7 @@ class MipsFastISel final : public FastIS
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, unsi
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::fastMaterializeCo
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, uns
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 Instr
// 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 Ins
// 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 Ins
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
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;
Added: llvm/trunk/test/CodeGen/Mips/Fast-ISel/fpintconv.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/Fast-ISel/fpintconv.ll?rev=219511&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/Fast-ISel/fpintconv.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/Fast-ISel/fpintconv.ll Fri Oct 10 12:00:46 2014
@@ -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
+
+
+ at f = global float 0x40D6E83280000000, align 4
+ at d = global double 0x4132D68780000000, align 8
+ at i_f = common global i32 0, align 4
+ at i_d = common global i32 0, align 4
+ at .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
+}
More information about the llvm-commits
mailing list