[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