mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
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 llvm-svn: 219511
This commit is contained in:
parent
9cbee3a665
commit
7c9f20a7a1
@ -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;
|
||||
|
35
test/CodeGen/Mips/Fast-ISel/fpintconv.ll
Normal file
35
test/CodeGen/Mips/Fast-ISel/fpintconv.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user