diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp @@ -52,6 +52,9 @@ bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; + bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) const; + const PPCSubtarget &STI; const PPCInstrInfo &TII; const PPCRegisterInfo &TRI; @@ -89,6 +92,8 @@ if (RB->getID() == PPC::GPRRegBankID) { if (Ty.getSizeInBits() == 64) return &PPC::G8RCRegClass; + if (Ty.getSizeInBits() == 32) + return &PPC::GPRCRegClass; } if (RB->getID() == PPC::FPRRegBankID) { if (Ty.getSizeInBits() == 32) @@ -130,6 +135,8 @@ switch (RegBankID) { case PPC::GPRRegBankID: switch (OpSize) { + case 32: + return IsStore ? PPC::STW : PPC::LWZ; case 64: return IsStore ? PPC::STD : PPC::LD; default: @@ -138,6 +145,8 @@ break; case PPC::FPRRegBankID: switch (OpSize) { + case 32: + return IsStore ? PPC::STFS : PPC::LFS; case 64: return IsStore ? PPC::STFD : PPC::LFD; default: @@ -207,6 +216,40 @@ return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); } +bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) const { + const Register DstReg = I.getOperand(0).getReg(); + const LLT DstTy = MRI.getType(DstReg); + const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI); + + const Register SrcReg = I.getOperand(1).getReg(); + + assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!"); + assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!"); + + Register ImpDefReg = + MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); + BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF), + ImpDefReg); + + Register NewDefReg = + MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); + BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG), + NewDefReg) + .addReg(ImpDefReg) + .addReg(SrcReg) + .addImm(PPC::sub_32); + + MachineInstr *MI = + BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg) + .addReg(NewDefReg) + .addImm(0) + .addImm(32); + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); +} + bool PPCInstructionSelector::select(MachineInstr &I) { auto &MBB = *I.getParent(); auto &MF = *MBB.getParent(); @@ -270,6 +313,9 @@ case TargetOpcode::G_FPTOSI: case TargetOpcode::G_FPTOUI: return selectFPToInt(I, MBB, MRI); + // G_SEXT will be selected in tb-gen pattern. + case TargetOpcode::G_ZEXT: + return selectZExt(I, MBB, MRI); } return false; } diff --git a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp @@ -20,11 +20,16 @@ PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) { using namespace TargetOpcode; const LLT P0 = LLT::pointer(0, 64); + const LLT S8 = LLT::scalar(8); + const LLT S16 = LLT::scalar(16); const LLT S32 = LLT::scalar(32); const LLT S64 = LLT::scalar(64); getActionDefinitionsBuilder(G_IMPLICIT_DEF).legalFor({S64}); getActionDefinitionsBuilder(G_CONSTANT) - .legalFor({S64}) + .legalFor({S32, S64}) + .clampScalar(0, S64, S64); + getActionDefinitionsBuilder({G_ZEXT, G_SEXT}) + .legalForCartesianProduct({S64}, {S8, S16, S32}) .clampScalar(0, S64, S64); getActionDefinitionsBuilder({G_AND, G_OR, G_XOR}) .legalFor({S64}) @@ -42,10 +47,8 @@ getActionDefinitionsBuilder({G_SITOFP, G_UITOFP}) .legalForCartesianProduct({S32, S64}, {S64}); - // For now only handle 64 bit, we only support 64 bit integer and zext/sext is - // not ready. getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForTypesWithMemDesc({{S64, P0, S64, 8}}); + .legalForTypesWithMemDesc({{S64, P0, S64, 8}, {S32, P0, S32, 4}}); getLegacyLegalizerInfo().computeTables(); } diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.h @@ -28,10 +28,11 @@ protected: enum PartialMappingIdx { PMI_None = -1, - PMI_GPR64 = 1, - PMI_FPR32 = 2, - PMI_FPR64 = 3, - PMI_Min = PMI_GPR64, + PMI_GPR32 = 1, + PMI_GPR64 = 2, + PMI_FPR32 = 3, + PMI_FPR64 = 4, + PMI_Min = PMI_GPR32, }; static RegisterBankInfo::PartialMapping PartMappings[]; diff --git a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp --- a/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp @@ -35,6 +35,9 @@ case PPC::G8RCRegClassID: case PPC::G8RC_NOX0RegClassID: case PPC::G8RC_and_G8RC_NOX0RegClassID: + case PPC::GPRCRegClassID: + case PPC::GPRC_NOR0RegClassID: + case PPC::GPRC_and_GPRC_NOR0RegClassID: return getRegBank(PPC::GPRRegBankID); case PPC::VSFRCRegClassID: case PPC::SPILLTOVSRRC_and_VSFRCRegClassID: @@ -81,6 +84,9 @@ case TargetOpcode::G_AND: case TargetOpcode::G_OR: case TargetOpcode::G_XOR: + // Extension ops. + case TargetOpcode::G_SEXT: + case TargetOpcode::G_ZEXT: assert(NumOperands <= 3 && "This code is for instructions with 3 or less operands"); OperandsMapping = getValueMapping(PMI_GPR64); @@ -120,6 +126,7 @@ break; } case TargetOpcode::G_LOAD: { + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); // Check if that load feeds fp instructions. if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), [&](const MachineInstr &UseMI) { @@ -133,21 +140,26 @@ return onlyUsesFP(UseMI, MRI, TRI); })) OperandsMapping = getOperandsMapping( - {getValueMapping(PMI_FPR64), getValueMapping(PMI_GPR64)}); + {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), + getValueMapping(PMI_GPR64)}); else OperandsMapping = getOperandsMapping( - {getValueMapping(PMI_GPR64), getValueMapping(PMI_GPR64)}); + {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), + getValueMapping(PMI_GPR64)}); break; } case TargetOpcode::G_STORE: { // Check if the store is fed by fp instructions. MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg()); + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); if (onlyDefinesFP(*DefMI, MRI, TRI)) OperandsMapping = getOperandsMapping( - {getValueMapping(PMI_FPR64), getValueMapping(PMI_GPR64)}); + {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), + getValueMapping(PMI_GPR64)}); else OperandsMapping = getOperandsMapping( - {getValueMapping(PMI_GPR64), getValueMapping(PMI_GPR64)}); + {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), + getValueMapping(PMI_GPR64)}); break; } default: diff --git a/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def b/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def --- a/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def +++ b/llvm/lib/Target/PowerPC/PPCGenRegisterBankInfo.def @@ -14,11 +14,13 @@ namespace llvm { RegisterBankInfo::PartialMapping PPCGenRegisterBankInfo::PartMappings[]{ /* StartIdx, Length, RegBank */ - // 0: GPR 64-bit value. + // 0: GPR 32-bit value. + {0, 32, PPC::GPRRegBank}, + // 1: GPR 64-bit value. {0, 64, PPC::GPRRegBank}, - // 1: FPR 32-bit value + // 2: FPR 32-bit value {0, 32, PPC::FPRRegBank}, - // 2: FPR 64-bit value + // 3: FPR 64-bit value {0, 64, PPC::FPRRegBank}, }; @@ -37,15 +39,19 @@ /* BreakDown, NumBreakDowns */ // 0: invalid {nullptr, 0}, - // 1: GPR 64-bit value. + // 1: GPR 32-bit value. + {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + {&PPCGenRegisterBankInfo::PartMappings[PMI_GPR32 - PMI_Min], 1}, + // 4: GPR 64-bit value. {&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. + // 7: 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. + // 10: 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}, diff --git a/llvm/test/CodeGen/PowerPC/GlobalISel/load-store-32bit.ll b/llvm/test/CodeGen/PowerPC/GlobalISel/load-store-32bit.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/GlobalISel/load-store-32bit.ll @@ -0,0 +1,54 @@ +; 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 -verify-machineinstrs < %s | FileCheck %s + +define signext i32 @load_signext_i32(ptr %ptr) { +; CHECK-LABEL: load_signext_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lwa r3, 0(r3) +; CHECK-NEXT: blr +entry: + %ret = load i32, ptr %ptr, align 4 + ret i32 %ret +} + +define zeroext i32 @load_zeroext_i32(ptr %ptr) { +; CHECK-LABEL: load_zeroext_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lwz r3, 0(r3) +; CHECK-NEXT: blr +entry: + %ret = load i32, ptr %ptr, align 4 + ret i32 %ret +} + +define float @load_float(ptr %ptr) { +; CHECK-LABEL: load_float: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lfs f1, 0(r3) +; CHECK-NEXT: blr +entry: + %ret = load float, ptr %ptr, align 4 + ret float %ret +} + +define void @store_i32(ptr %p) { +; CHECK-LABEL: store_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li r4, 100 +; CHECK-NEXT: stw r4, 0(r3) +; CHECK-NEXT: blr +entry: + store i32 100, ptr %p, align 4 + ret void +} + +define void @store_float(ptr %ptr, float %a) { +; CHECK-LABEL: store_float: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stfs f1, 0(r3) +; CHECK-NEXT: blr +entry: + store float %a, ptr %ptr, align 4 + ret void +}