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 @@ -50,6 +50,8 @@ MachineRegisterInfo &MRI) const; bool selectSExt(MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const; + bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB, + MachineRegisterInfo &MRI) const; const PPCInstrInfo &TII; const PPCRegisterInfo &TRI; @@ -87,6 +89,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) @@ -128,6 +132,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: @@ -136,6 +142,8 @@ break; case PPC::FPRRegBankID: switch (OpSize) { + case 32: + return isStore ? PPC::STFS : PPC::LFS; case 64: return isStore ? PPC::STFD : PPC::LFD; default: @@ -244,6 +252,39 @@ 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(); @@ -303,8 +344,11 @@ } case TargetOpcode::G_CONSTANT: return selectConst(I, MBB, MRI); + // G_SEXT will be selected in tb-gen pattern. case TargetOpcode::G_SEXT_INREG: return selectSExt(I, MBB, MRI); + 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 @@ -25,7 +25,7 @@ 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_TRUNC) .legalForCartesianProduct({S8, S16, S32}, {S64}); @@ -47,7 +47,7 @@ // For now only handle 64 bit, we only support 64 bit integer and zext/sext is // not ready. getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalFor({S64}); + .legalFor({S32, S64}); 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 @@ -37,6 +37,9 @@ case PPC::G8RC_and_G8RC_NOX0RegClassID: case PPC::G8pRCRegClassID: case PPC::G8pRC_with_sub_32_in_GPRC_NOR0RegClassID: + 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: @@ -111,8 +114,8 @@ OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); break; case TargetOpcode::G_LOAD: { - assert(MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 64 && - "Unsupported types!\n"); + unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); + assert((Size == 64 || Size == 32) && "Unsupported types!\n"); // Check if that load feeds fp instructions. if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), [&](const MachineInstr &UseMI) { @@ -126,21 +129,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 < %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: + %0 = load i32, ptr %ptr, align 4 + ret i32 %0 +} + +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: + %0 = load i32, ptr %ptr, align 4 + ret i32 %0 +} + +define float @load_float(ptr %ptr) { +; CHECK-LABEL: load_float: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lfs f1, 0(r3) +; CHECK-NEXT: blr +entry: + %0 = load float, ptr %ptr, align 4 + ret float %0 +} + +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 +}