diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp index 93bbb9c107577..d3e3fb1528ba3 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp @@ -80,6 +80,12 @@ static const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank *RB) { if (Ty.getSizeInBits() == 64) return &PPC::G8RCRegClass; } + if (RB->getID() == PPC::FPRRegBankID) { + if (Ty.getSizeInBits() == 32) + return &PPC::F4RCRegClass; + if (Ty.getSizeInBits() == 64) + return &PPC::F8RCRegClass; + } llvm_unreachable("Unknown RegBank!"); } diff --git a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp index bbbd211269d42..86dd11d3e572a 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp @@ -19,6 +19,7 @@ using namespace LegalizeActions; PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) { using namespace TargetOpcode; + const LLT S32 = LLT::scalar(32); const LLT S64 = LLT::scalar(64); getActionDefinitionsBuilder(G_IMPLICIT_DEF).legalFor({S64}); getActionDefinitionsBuilder(G_CONSTANT) @@ -30,5 +31,9 @@ PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) { getActionDefinitionsBuilder({G_ADD, G_SUB}) .legalFor({S64}) .clampScalar(0, S64, S64); + + getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV}) + .legalFor({S32, S64}); + getLegacyLegalizerInfo().computeTables(); } diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp index 8a57010299d65..4f31229278a88 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp @@ -36,6 +36,15 @@ PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, case PPC::G8RC_NOX0RegClassID: case PPC::G8RC_and_G8RC_NOX0RegClassID: return getRegBank(PPC::GPRRegBankID); + case PPC::VSFRCRegClassID: + case PPC::SPILLTOVSRRC_and_VSFRCRegClassID: + case PPC::SPILLTOVSRRC_and_VFRCRegClassID: + case PPC::SPILLTOVSRRC_and_F4RCRegClassID: + case PPC::F8RCRegClassID: + case PPC::VFRCRegClassID: + case PPC::VSSRCRegClassID: + case PPC::F4RCRegClassID: + return getRegBank(PPC::FPRRegBankID); default: llvm_unreachable("Unexpected register class"); } @@ -54,6 +63,11 @@ PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { return Mapping; } + const MachineFunction &MF = *MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetSubtargetInfo &STI = MF.getSubtarget(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); + unsigned NumOperands = MI.getNumOperands(); const ValueMapping *OperandsMapping = nullptr; unsigned Cost = 1; @@ -71,6 +85,17 @@ PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { "This code is for instructions with 3 or less operands"); OperandsMapping = getValueMapping(PMI_GPR64); break; + case TargetOpcode::G_FADD: + case TargetOpcode::G_FSUB: + case TargetOpcode::G_FMUL: + case TargetOpcode::G_FDIV: { + Register SrcReg = MI.getOperand(1).getReg(); + unsigned Size = getSizeInBits(SrcReg, MRI, TRI); + + assert((Size == 32 || Size == 64) && "Unsupported floating point types!\n"); + OperandsMapping = getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64); + break; + } case TargetOpcode::G_CONSTANT: OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); break; diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h index 11bdd98cd3b52..40959a3e625e9 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h @@ -29,6 +29,8 @@ class PPCGenRegisterBankInfo : public RegisterBankInfo { enum PartialMappingIdx { PMI_None = -1, PMI_GPR64 = 1, + PMI_FPR32 = 2, + PMI_FPR64 = 3, PMI_Min = PMI_GPR64, }; diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBanks.td b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBanks.td index 771d33e9f3a38..b5f39e4dc618c 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBanks.td +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBanks.td @@ -13,3 +13,5 @@ /// General Purpose Registers def GPRRegBank : RegisterBank<"GPR", [G8RC, G8RC_NOX0]>; +/// Floating point Registers +def FPRRegBank : RegisterBank<"FPR", [VSSRC]>; diff --git a/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def b/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def index 471af5d13d80d..f8c79fb3a1ca9 100644 --- a/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def +++ b/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def @@ -16,6 +16,10 @@ RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{ /* StartIdx, Length, RegBank */ // 0: GPR 64-bit value. {0, 64, PPC::GPRRegBank}, + // 1: FPR 32-bit value + {0, 32, PPC::FPRRegBank}, + // 2: FPR 64-bit value + {0, 64, PPC::FPRRegBank}, }; // ValueMappings. @@ -37,6 +41,14 @@ RegisterBankInfo::ValueMapping PPCGenRegisterBankInfo::ValMappings[]{ {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR64 - PMI_Min], 1}, + // 4: FPR 32-bit value. + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR32 - PMI_Min], 1}, + // 7: FPR 64-bit value. + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_FPR64 - PMI_Min], 1}, }; // TODO Too simple! diff --git a/llvm/test/CodeGen/PowerPC/GlobalISel/float-arithmetic.ll b/llvm/test/CodeGen/PowerPC/GlobalISel/float-arithmetic.ll new file mode 100644 index 0000000000000..185fa4deb6b5b --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/GlobalISel/float-arithmetic.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -o - \ +; RUN: -ppc-vsr-nums-as-vr -ppc-asm-full-reg-names < %s | FileCheck %s + +define float @float_add(float %a, float %b) { +; CHECK-LABEL: float_add: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsaddsp f1, f1, f2 +; CHECK-NEXT: blr +entry: + %add = fadd float %a, %b + ret float %add +} + +define double @double_add(double %a, double %b) { +; CHECK-LABEL: double_add: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsadddp f1, f1, f2 +; CHECK-NEXT: blr +entry: + %add = fadd double %a, %b + ret double %add +} + +define float @float_sub(float %a, float %b) { +; CHECK-LABEL: float_sub: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xssubsp f1, f1, f2 +; CHECK-NEXT: blr +entry: + %sub = fsub float %a, %b + ret float %sub +} + +define float @float_mul(float %a, float %b) { +; CHECK-LABEL: float_mul: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsmulsp f1, f1, f2 +; CHECK-NEXT: blr +entry: + %mul = fmul float %a, %b + ret float %mul +} + +define float @float_div(float %a, float %b) { +; CHECK-LABEL: float_div: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xsdivsp f1, f1, f2 +; CHECK-NEXT: blr +entry: + %div = fdiv float %a, %b + ret float %div +}