]> granicus.if.org Git - llvm/commitdiff
[MIPS GlobalISel] Select float constants
authorPetar Avramovic <Petar.Avramovic@rt-rk.com>
Thu, 28 Mar 2019 16:58:12 +0000 (16:58 +0000)
committerPetar Avramovic <Petar.Avramovic@rt-rk.com>
Thu, 28 Mar 2019 16:58:12 +0000 (16:58 +0000)
Select 32 and 64 bit float constants for MIPS32.

Differential Revision: https://reviews.llvm.org/D59933

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357183 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MipsInstructionSelector.cpp
lib/Target/Mips/MipsLegalizerInfo.cpp
lib/Target/Mips/MipsRegisterBankInfo.cpp
test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir [new file with mode: 0644]
test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir [new file with mode: 0644]
test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll [new file with mode: 0644]
test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir [new file with mode: 0644]

index ded8c1c1fbc0b8ed4eecee9138ee7059ccd7e574..a03e7ef57b7bf26e4290e56af708ead3093dedbb 100644 (file)
@@ -320,6 +320,41 @@ bool MipsInstructionSelector::select(MachineInstr &I,
     I.eraseFromParent();
     return true;
   }
+  case G_FCONSTANT: {
+    const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF();
+    APInt APImm = FPimm.bitcastToAPInt();
+    unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
+
+    if (Size == 32) {
+      unsigned GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+      MachineIRBuilder B(I);
+      if (!materialize32BitImm(GPRReg, APImm, B))
+        return false;
+
+      MachineInstrBuilder MTC1 =
+          B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg});
+      if (!MTC1.constrainAllUses(TII, TRI, RBI))
+        return false;
+    }
+    if (Size == 64) {
+      unsigned GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+      unsigned GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass);
+      MachineIRBuilder B(I);
+      if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B))
+        return false;
+      if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B))
+        return false;
+
+      MachineInstrBuilder PairF64 = B.buildInstr(
+          STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64,
+          {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh});
+      if (!PairF64.constrainAllUses(TII, TRI, RBI))
+        return false;
+    }
+
+    I.eraseFromParent();
+    return true;
+  }
   case G_GLOBAL_VALUE: {
     if (MF.getTarget().isPositionIndependent())
       return false;
index 45f248b6bd232cb8d123cae8b3bfd54eea346fce..23d8eb24d15d589acb6c0ae339a01e7fe7cf5729 100644 (file)
@@ -81,6 +81,9 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
       .legalFor({s32})
       .clampScalar(0, s32, s32);
 
+  getActionDefinitionsBuilder(G_FCONSTANT)
+      .legalFor({s32, s64});
+
   getActionDefinitionsBuilder(G_GEP)
       .legalFor({{p0, s32}});
 
index 08c33a4119ceed9ee2ad0024668915c6931f7a64..2de4e7fd566fa5583b7fcf78aeea143ed50992b7 100644 (file)
@@ -24,22 +24,40 @@ namespace llvm {
 namespace Mips {
 enum PartialMappingIdx {
   PMI_GPR,
+  PMI_SPR,
+  PMI_DPR,
   PMI_Min = PMI_GPR,
 };
 
 RegisterBankInfo::PartialMapping PartMappings[]{
-    {0, 32, GPRBRegBank}
+    {0, 32, GPRBRegBank},
+    {0, 32, FPRBRegBank},
+    {0, 64, FPRBRegBank}
 };
 
-enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1 };
+enum ValueMappingIdx {
+    InvalidIdx = 0,
+    GPRIdx = 1,
+    SPRIdx = 4,
+    DPRIdx = 7
+};
 
 RegisterBankInfo::ValueMapping ValueMappings[] = {
     // invalid
     {nullptr, 0},
-    // 3 operands in GPRs
+    // up to 3 operands in GPRs
+    {&PartMappings[PMI_GPR - PMI_Min], 1},
     {&PartMappings[PMI_GPR - PMI_Min], 1},
     {&PartMappings[PMI_GPR - PMI_Min], 1},
-    {&PartMappings[PMI_GPR - PMI_Min], 1}};
+    // up to 3 ops operands FPRs - single precission
+    {&PartMappings[PMI_SPR - PMI_Min], 1},
+    {&PartMappings[PMI_SPR - PMI_Min], 1},
+    {&PartMappings[PMI_SPR - PMI_Min], 1},
+    // up to 3 ops operands FPRs - double precission
+    {&PartMappings[PMI_DPR - PMI_Min], 1},
+    {&PartMappings[PMI_DPR - PMI_Min], 1},
+    {&PartMappings[PMI_DPR - PMI_Min], 1}
+};
 
 } // end namespace Mips
 } // end namespace llvm
@@ -76,6 +94,8 @@ const RegisterBankInfo::InstructionMapping &
 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
 
   unsigned Opc = MI.getOpcode();
+  const MachineFunction &MF = *MI.getParent()->getParent();
+  const MachineRegisterInfo &MRI = MF.getRegInfo();
 
   const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI);
   if (Mapping.isValid())
@@ -109,6 +129,15 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   case G_UREM:
     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
     break;
+  case G_FCONSTANT: {
+    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+    unsigned Size = Ty.getSizeInBits();
+    const RegisterBankInfo::ValueMapping *FPRValueMapping =
+        Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
+                   : &Mips::ValueMappings[Mips::DPRIdx];
+    OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
+    break;
+  }
   case G_CONSTANT:
   case G_FRAME_INDEX:
   case G_GLOBAL_VALUE:
diff --git a/test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir b/test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir
new file mode 100644 (file)
index 0000000..4fa6280
--- /dev/null
@@ -0,0 +1,64 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64
+--- |
+
+  define void @e_single_precision() {entry: ret void}
+  define void @e_double_precision() {entry: ret void}
+
+...
+---
+name:            e_single_precision
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_single_precision
+    ; FP32: [[LUi:%[0-9]+]]:gpr32 = LUi 16429
+    ; FP32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 63572
+    ; FP32: [[MTC1_:%[0-9]+]]:fgr32 = MTC1 [[ORi]]
+    ; FP32: $f0 = COPY [[MTC1_]]
+    ; FP32: RetRA implicit $f0
+    ; FP64-LABEL: name: e_single_precision
+    ; FP64: [[LUi:%[0-9]+]]:gpr32 = LUi 16429
+    ; FP64: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 63572
+    ; FP64: [[MTC1_:%[0-9]+]]:fgr32 = MTC1 [[ORi]]
+    ; FP64: $f0 = COPY [[MTC1_]]
+    ; FP64: RetRA implicit $f0
+    %0:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    $f0 = COPY %0(s32)
+    RetRA implicit $f0
+
+...
+---
+name:            e_double_precision
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_double_precision
+    ; FP32: [[LUi:%[0-9]+]]:gpr32 = LUi 16389
+    ; FP32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 48906
+    ; FP32: [[LUi1:%[0-9]+]]:gpr32 = LUi 35604
+    ; FP32: [[ORi1:%[0-9]+]]:gpr32 = ORi [[LUi1]], 22377
+    ; FP32: [[BuildPairF64_:%[0-9]+]]:afgr64 = BuildPairF64 [[ORi1]], [[ORi]]
+    ; FP32: $d0 = COPY [[BuildPairF64_]]
+    ; FP32: RetRA implicit $d0
+    ; FP64-LABEL: name: e_double_precision
+    ; FP64: [[LUi:%[0-9]+]]:gpr32 = LUi 16389
+    ; FP64: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 48906
+    ; FP64: [[LUi1:%[0-9]+]]:gpr32 = LUi 35604
+    ; FP64: [[ORi1:%[0-9]+]]:gpr32 = ORi [[LUi1]], 22377
+    ; FP64: [[BuildPairF64_64_:%[0-9]+]]:fgr64 = BuildPairF64_64 [[ORi1]], [[ORi]]
+    ; FP64: $d0 = COPY [[BuildPairF64_64_]]
+    ; FP64: RetRA implicit $d0
+    %0:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    $d0 = COPY %0(s64)
+    RetRA implicit $d0
+
+...
+
diff --git a/test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir b/test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir
new file mode 100644 (file)
index 0000000..695a8ff
--- /dev/null
@@ -0,0 +1,49 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64
+
+--- |
+
+  define void @e_single_precision() {entry: ret void}
+  define void @e_double_precision() {entry: ret void}
+
+...
+---
+name:            e_single_precision
+alignment:       2
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_single_precision
+    ; FP32: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    ; FP32: $f0 = COPY [[C]](s32)
+    ; FP32: RetRA implicit $f0
+    ; FP64-LABEL: name: e_single_precision
+    ; FP64: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    ; FP64: $f0 = COPY [[C]](s32)
+    ; FP64: RetRA implicit $f0
+    %0:_(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    $f0 = COPY %0(s32)
+    RetRA implicit $f0
+
+...
+---
+name:            e_double_precision
+alignment:       2
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_double_precision
+    ; FP32: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    ; FP32: $d0 = COPY [[C]](s64)
+    ; FP32: RetRA implicit $d0
+    ; FP64-LABEL: name: e_double_precision
+    ; FP64: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    ; FP64: $d0 = COPY [[C]](s64)
+    ; FP64: RetRA implicit $d0
+    %0:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    $d0 = COPY %0(s64)
+    RetRA implicit $d0
+
+...
+
diff --git a/test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll b/test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll
new file mode 100644 (file)
index 0000000..f4ca9e5
--- /dev/null
@@ -0,0 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP32
+; RUN: llc  -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP64
+
+define float @e_single_precision() {
+; MIPS32-LABEL: e_single_precision:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    lui $1, 16429
+; MIPS32-NEXT:    ori $1, $1, 63572
+; MIPS32-NEXT:    mtc1 $1, $f0
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  ret float 0x4005BF0A80000000
+}
+
+define double @e_double_precision() {
+; FP32-LABEL: e_double_precision:
+; FP32:       # %bb.0: # %entry
+; FP32-NEXT:    lui $1, 16389
+; FP32-NEXT:    ori $1, $1, 48906
+; FP32-NEXT:    lui $2, 35604
+; FP32-NEXT:    ori $2, $2, 22377
+; FP32-NEXT:    mtc1 $2, $f0
+; FP32-NEXT:    mtc1 $1, $f1
+; FP32-NEXT:    jr $ra
+; FP32-NEXT:    nop
+;
+; FP64-LABEL: e_double_precision:
+; FP64:       # %bb.0: # %entry
+; FP64-NEXT:    lui $1, 16389
+; FP64-NEXT:    ori $1, $1, 48906
+; FP64-NEXT:    lui $2, 35604
+; FP64-NEXT:    ori $2, $2, 22377
+; FP64-NEXT:    mtc1 $2, $f0
+; FP64-NEXT:    mthc1 $1, $f0
+; FP64-NEXT:    jr $ra
+; FP64-NEXT:    nop
+entry:
+  ret double 0x4005BF0A8B145769
+}
diff --git a/test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir b/test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir
new file mode 100644 (file)
index 0000000..87b9140
--- /dev/null
@@ -0,0 +1,50 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64
+
+--- |
+
+  define void @e_single_precision() {entry: ret void}
+  define void @e_double_precision() {entry: ret void}
+
+...
+---
+name:            e_single_precision
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_single_precision
+    ; FP32: [[C:%[0-9]+]]:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    ; FP32: $f0 = COPY [[C]](s32)
+    ; FP32: RetRA implicit $f0
+    ; FP64-LABEL: name: e_single_precision
+    ; FP64: [[C:%[0-9]+]]:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    ; FP64: $f0 = COPY [[C]](s32)
+    ; FP64: RetRA implicit $f0
+    %0:_(s32) = G_FCONSTANT float 0x4005BF0A80000000
+    $f0 = COPY %0(s32)
+    RetRA implicit $f0
+
+...
+---
+name:            e_double_precision
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    ; FP32-LABEL: name: e_double_precision
+    ; FP32: [[C:%[0-9]+]]:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    ; FP32: $d0 = COPY [[C]](s64)
+    ; FP32: RetRA implicit $d0
+    ; FP64-LABEL: name: e_double_precision
+    ; FP64: [[C:%[0-9]+]]:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    ; FP64: $d0 = COPY [[C]](s64)
+    ; FP64: RetRA implicit $d0
+    %0:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769
+    $d0 = COPY %0(s64)
+    RetRA implicit $d0
+
+...