[llvm] 0a9b1c5 - [PowerPC][GISel]support for float point and integer convertion

Chen Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 4 19:22:21 PST 2022


Author: Chen Zheng
Date: 2022-12-04T22:21:57-05:00
New Revision: 0a9b1c59f000cab21afc0c19df0f635445826422

URL: https://github.com/llvm/llvm-project/commit/0a9b1c59f000cab21afc0c19df0f635445826422
DIFF: https://github.com/llvm/llvm-project/commit/0a9b1c59f000cab21afc0c19df0f635445826422.diff

LOG: [PowerPC][GISel]support for float point and integer convertion

Add support for fptosi,fptoui,sitofp,uitofp

For now only handle 64 bit integer to make it does not depend on
any other patches. 32 bit integer needs handling for G_SEXT/G_ZEXT.

Reviewed By: arsenm

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

Added: 
    llvm/test/CodeGen/PowerPC/GlobalISel/float-integer-conv.ll

Modified: 
    llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
    llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp
    llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
index d3e3fb1528ba3..e3f4ccd9e9f60 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
@@ -10,6 +10,7 @@
 /// PowerPC.
 //===----------------------------------------------------------------------===//
 
+#include "PPC.h"
 #include "PPCInstrInfo.h"
 #include "PPCRegisterBankInfo.h"
 #include "PPCSubtarget.h"
@@ -43,6 +44,12 @@ class PPCInstructionSelector : public InstructionSelector {
   /// selector for the patterns that do not require complex C++.
   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
 
+  bool selectFPToInt(MachineInstr &I, MachineBasicBlock &MBB,
+                  MachineRegisterInfo &MRI) const;
+  bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB,
+                  MachineRegisterInfo &MRI) const;
+
+  const PPCSubtarget &STI;
   const PPCInstrInfo &TII;
   const PPCRegisterInfo &TRI;
   const PPCRegisterBankInfo &RBI;
@@ -65,7 +72,7 @@ class PPCInstructionSelector : public InstructionSelector {
 PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM,
                                                const PPCSubtarget &STI,
                                                const PPCRegisterBankInfo &RBI)
-    : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
+    : STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
 #define GET_GLOBALISEL_PREDICATES_INIT
 #include "PPCGenGlobalISel.inc"
 #undef GET_GLOBALISEL_PREDICATES_INIT
@@ -114,6 +121,63 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
   return true;
 }
 
+bool PPCInstructionSelector::selectIntToFP(MachineInstr &I,
+                                           MachineBasicBlock &MBB,
+                                           MachineRegisterInfo &MRI) const {
+  if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
+    return false;
+
+  const DebugLoc &DbgLoc = I.getDebugLoc();
+  const Register DstReg = I.getOperand(0).getReg();
+  const Register SrcReg = I.getOperand(1).getReg();
+
+  Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
+
+  // For now, only handle the case for 64 bit integer.
+  BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg);
+
+  bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32;
+  bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP;
+  unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP)
+                             : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP);
+
+  MachineInstr *MI =
+      BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg);
+
+  I.eraseFromParent();
+  return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
+}
+
+bool PPCInstructionSelector::selectFPToInt(MachineInstr &I,
+                                           MachineBasicBlock &MBB,
+                                           MachineRegisterInfo &MRI) const {
+  if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
+    return false;
+
+  const DebugLoc &DbgLoc = I.getDebugLoc();
+  const Register DstReg = I.getOperand(0).getReg();
+  const Register SrcReg = I.getOperand(1).getReg();
+
+  Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
+  BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg);
+
+  Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass);
+
+  bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI;
+
+  // single-precision is stored as double-precision on PPC in registers, so
+  // always use double-precision convertions.
+  unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;
+
+  BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg);
+
+  MachineInstr *MI =
+      BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg);
+
+  I.eraseFromParent();
+  return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
+}
+
 bool PPCInstructionSelector::select(MachineInstr &I) {
   auto &MBB = *I.getParent();
   auto &MF = *MBB.getParent();
@@ -128,6 +192,19 @@ bool PPCInstructionSelector::select(MachineInstr &I) {
 
   if (selectImpl(I, *CoverageInfo))
     return true;
+
+  unsigned Opcode = I.getOpcode();
+
+  switch (Opcode) {
+  default:
+    return false;
+  case TargetOpcode::G_SITOFP:
+  case TargetOpcode::G_UITOFP:
+    return selectIntToFP(I, MBB, MRI);
+  case TargetOpcode::G_FPTOSI:
+  case TargetOpcode::G_FPTOUI:
+    return selectFPToInt(I, MBB, MRI);
+  }
   return false;
 }
 

diff  --git a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp
index 86dd11d3e572a..2d30b38bddc63 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp
@@ -35,5 +35,11 @@ PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) {
   getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
       .legalFor({S32, S64});
 
+  getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
+      .legalForCartesianProduct({S64}, {S32, S64});
+
+  getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
+      .legalForCartesianProduct({S32, S64}, {S64});
+
   getLegacyLegalizerInfo().computeTables();
 }

diff  --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
index 4f31229278a88..a9154a451ab4c 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
@@ -99,6 +99,26 @@ PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   case TargetOpcode::G_CONSTANT:
     OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
     break;
+  case TargetOpcode::G_FPTOUI:
+  case TargetOpcode::G_FPTOSI: {
+    Register SrcReg = MI.getOperand(1).getReg();
+    unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
+
+    OperandsMapping = getOperandsMapping(
+        {getValueMapping(PMI_GPR64),
+         getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});
+    break;
+  }
+  case TargetOpcode::G_UITOFP:
+  case TargetOpcode::G_SITOFP: {
+    Register SrcReg = MI.getOperand(0).getReg();
+    unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
+
+    OperandsMapping =
+        getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),
+                            getValueMapping(PMI_GPR64)});
+    break;
+  }
   default:
     return getInvalidInstructionMapping();
   }

diff  --git a/llvm/test/CodeGen/PowerPC/GlobalISel/float-integer-conv.ll b/llvm/test/CodeGen/PowerPC/GlobalISel/float-integer-conv.ll
new file mode 100644
index 0000000000000..a495ed7617f41
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/GlobalISel/float-integer-conv.ll
@@ -0,0 +1,92 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel  -ppc-vsr-nums-as-vr \
+; RUN:   -ppc-asm-full-reg-names -verify-machineinstrs -o - < %s | FileCheck %s
+
+define i64 @fptosi_float_i64(float %i) {
+; CHECK-LABEL: fptosi_float_i64:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xscvdpsxds f0, f1
+; CHECK-NEXT:    mffprd r3, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = fptosi float %i to i64
+  ret i64 %conv
+}
+
+define i64 @fptosi_double_i64(double %i) {
+; CHECK-LABEL: fptosi_double_i64:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xscvdpsxds f0, f1
+; CHECK-NEXT:    mffprd r3, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = fptosi double %i to i64
+  ret i64 %conv
+}
+
+define i64 @fptoui_float_i64(float %i) {
+; CHECK-LABEL: fptoui_float_i64:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xscvdpuxds f0, f1
+; CHECK-NEXT:    mffprd r3, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = fptoui float %i to i64
+  ret i64 %conv
+}
+
+define i64 @fptoui_double_i64(double %i) {
+; CHECK-LABEL: fptoui_double_i64:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xscvdpuxds f0, f1
+; CHECK-NEXT:    mffprd r3, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = fptoui double %i to i64
+  ret i64 %conv
+}
+
+define float @sitofp_i64_float(i64 %i) {
+; CHECK-LABEL: sitofp_i64_float:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mtfprd f0, r3
+; CHECK-NEXT:    xscvsxdsp f1, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = sitofp i64 %i to float
+  ret float %conv
+}
+
+define double @sitofp_i64_double(i64 %i) {
+; CHECK-LABEL: sitofp_i64_double:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mtfprd f0, r3
+; CHECK-NEXT:    xscvsxddp f1, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = sitofp i64 %i to double
+  ret double %conv
+}
+
+define float @uitofp_i64_float(i64 %i) {
+; CHECK-LABEL: uitofp_i64_float:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mtfprd f0, r3
+; CHECK-NEXT:    xscvuxdsp f1, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = uitofp i64 %i to float
+  ret float %conv
+}
+
+define double @uitofp_i64_double(i64 %i) {
+; CHECK-LABEL: uitofp_i64_double:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    mtfprd f0, r3
+; CHECK-NEXT:    xscvuxddp f1, f0
+; CHECK-NEXT:    blr
+entry:
+  %conv = uitofp i64 %i to double
+  ret double %conv
+}


        


More information about the llvm-commits mailing list