1e8d8bef9SDimitry Andric //===- PPCInstructionSelector.cpp --------------------------------*- C++ -*-==// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric /// \file 9e8d8bef9SDimitry Andric /// This file implements the targeting of the InstructionSelector class for 10e8d8bef9SDimitry Andric /// PowerPC. 11e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 12e8d8bef9SDimitry Andric 13bdd1243dSDimitry Andric #include "PPC.h" 14e8d8bef9SDimitry Andric #include "PPCInstrInfo.h" 1506c3fb27SDimitry Andric #include "PPCMachineFunctionInfo.h" 16e8d8bef9SDimitry Andric #include "PPCRegisterBankInfo.h" 17e8d8bef9SDimitry Andric #include "PPCSubtarget.h" 18e8d8bef9SDimitry Andric #include "PPCTargetMachine.h" 1906c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h" 20bdd1243dSDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 21e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 22bdd1243dSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 23bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 24e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 25e8d8bef9SDimitry Andric #include "llvm/IR/IntrinsicsPowerPC.h" 26e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric #define DEBUG_TYPE "ppc-gisel" 29e8d8bef9SDimitry Andric 30e8d8bef9SDimitry Andric using namespace llvm; 31e8d8bef9SDimitry Andric 32e8d8bef9SDimitry Andric namespace { 33e8d8bef9SDimitry Andric 34e8d8bef9SDimitry Andric #define GET_GLOBALISEL_PREDICATE_BITSET 35e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 36e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_PREDICATE_BITSET 37e8d8bef9SDimitry Andric 38e8d8bef9SDimitry Andric class PPCInstructionSelector : public InstructionSelector { 39e8d8bef9SDimitry Andric public: 40e8d8bef9SDimitry Andric PPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &STI, 41e8d8bef9SDimitry Andric const PPCRegisterBankInfo &RBI); 42e8d8bef9SDimitry Andric 43e8d8bef9SDimitry Andric bool select(MachineInstr &I) override; 44e8d8bef9SDimitry Andric static const char *getName() { return DEBUG_TYPE; } 45e8d8bef9SDimitry Andric 46e8d8bef9SDimitry Andric private: 47e8d8bef9SDimitry Andric /// tblgen generated 'select' implementation that is used as the initial 48e8d8bef9SDimitry Andric /// selector for the patterns that do not require complex C++. 49e8d8bef9SDimitry Andric bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; 50e8d8bef9SDimitry Andric 51bdd1243dSDimitry Andric bool selectFPToInt(MachineInstr &I, MachineBasicBlock &MBB, 52bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const; 53bdd1243dSDimitry Andric bool selectIntToFP(MachineInstr &I, MachineBasicBlock &MBB, 54bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const; 55bdd1243dSDimitry Andric 56bdd1243dSDimitry Andric bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB, 57bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const; 5806c3fb27SDimitry Andric bool selectConstantPool(MachineInstr &I, MachineBasicBlock &MBB, 5906c3fb27SDimitry Andric MachineRegisterInfo &MRI) const; 60bdd1243dSDimitry Andric 61bdd1243dSDimitry Andric std::optional<bool> selectI64ImmDirect(MachineInstr &I, 62bdd1243dSDimitry Andric MachineBasicBlock &MBB, 63bdd1243dSDimitry Andric MachineRegisterInfo &MRI, Register Reg, 64bdd1243dSDimitry Andric uint64_t Imm) const; 65bdd1243dSDimitry Andric bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB, 66bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const; 67bdd1243dSDimitry Andric 6806c3fb27SDimitry Andric const PPCTargetMachine &TM; 69bdd1243dSDimitry Andric const PPCSubtarget &STI; 70e8d8bef9SDimitry Andric const PPCInstrInfo &TII; 71e8d8bef9SDimitry Andric const PPCRegisterInfo &TRI; 72e8d8bef9SDimitry Andric const PPCRegisterBankInfo &RBI; 73e8d8bef9SDimitry Andric 74e8d8bef9SDimitry Andric #define GET_GLOBALISEL_PREDICATES_DECL 75e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 76e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_DECL 77e8d8bef9SDimitry Andric 78e8d8bef9SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_DECL 79e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 80e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_DECL 81e8d8bef9SDimitry Andric }; 82e8d8bef9SDimitry Andric 83e8d8bef9SDimitry Andric } // end anonymous namespace 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric #define GET_GLOBALISEL_IMPL 86e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 87e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_IMPL 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM, 90e8d8bef9SDimitry Andric const PPCSubtarget &STI, 91e8d8bef9SDimitry Andric const PPCRegisterBankInfo &RBI) 9206c3fb27SDimitry Andric : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), 9306c3fb27SDimitry Andric RBI(RBI), 94e8d8bef9SDimitry Andric #define GET_GLOBALISEL_PREDICATES_INIT 95e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 96e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_PREDICATES_INIT 97e8d8bef9SDimitry Andric #define GET_GLOBALISEL_TEMPORARIES_INIT 98e8d8bef9SDimitry Andric #include "PPCGenGlobalISel.inc" 99e8d8bef9SDimitry Andric #undef GET_GLOBALISEL_TEMPORARIES_INIT 100e8d8bef9SDimitry Andric { 101e8d8bef9SDimitry Andric } 102e8d8bef9SDimitry Andric 103bdd1243dSDimitry Andric static const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank *RB) { 104bdd1243dSDimitry Andric if (RB->getID() == PPC::GPRRegBankID) { 105bdd1243dSDimitry Andric if (Ty.getSizeInBits() == 64) 106bdd1243dSDimitry Andric return &PPC::G8RCRegClass; 107bdd1243dSDimitry Andric if (Ty.getSizeInBits() <= 32) 108bdd1243dSDimitry Andric return &PPC::GPRCRegClass; 109bdd1243dSDimitry Andric } 110bdd1243dSDimitry Andric if (RB->getID() == PPC::FPRRegBankID) { 111bdd1243dSDimitry Andric if (Ty.getSizeInBits() == 32) 112bdd1243dSDimitry Andric return &PPC::F4RCRegClass; 113bdd1243dSDimitry Andric if (Ty.getSizeInBits() == 64) 114bdd1243dSDimitry Andric return &PPC::F8RCRegClass; 115bdd1243dSDimitry Andric } 11606c3fb27SDimitry Andric if (RB->getID() == PPC::VECRegBankID) { 11706c3fb27SDimitry Andric if (Ty.getSizeInBits() == 128) 11806c3fb27SDimitry Andric return &PPC::VSRCRegClass; 11906c3fb27SDimitry Andric } 120bdd1243dSDimitry Andric if (RB->getID() == PPC::CRRegBankID) { 121bdd1243dSDimitry Andric if (Ty.getSizeInBits() == 1) 122bdd1243dSDimitry Andric return &PPC::CRBITRCRegClass; 123bdd1243dSDimitry Andric if (Ty.getSizeInBits() == 4) 124bdd1243dSDimitry Andric return &PPC::CRRCRegClass; 125bdd1243dSDimitry Andric } 126bdd1243dSDimitry Andric 127bdd1243dSDimitry Andric llvm_unreachable("Unknown RegBank!"); 128bdd1243dSDimitry Andric } 129bdd1243dSDimitry Andric 130bdd1243dSDimitry Andric static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 131bdd1243dSDimitry Andric MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 132bdd1243dSDimitry Andric const RegisterBankInfo &RBI) { 133bdd1243dSDimitry Andric Register DstReg = I.getOperand(0).getReg(); 134bdd1243dSDimitry Andric 135bdd1243dSDimitry Andric if (DstReg.isPhysical()) 136bdd1243dSDimitry Andric return true; 137bdd1243dSDimitry Andric 138bdd1243dSDimitry Andric const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI); 139bdd1243dSDimitry Andric const TargetRegisterClass *DstRC = 140bdd1243dSDimitry Andric getRegClass(MRI.getType(DstReg), DstRegBank); 141bdd1243dSDimitry Andric 142bdd1243dSDimitry Andric // No need to constrain SrcReg. It will get constrained when we hit another of 143bdd1243dSDimitry Andric // its use or its defs. 144bdd1243dSDimitry Andric // Copies do not have constraints. 145bdd1243dSDimitry Andric if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) { 146bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 147bdd1243dSDimitry Andric << " operand\n"); 148bdd1243dSDimitry Andric return false; 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric return true; 152bdd1243dSDimitry Andric } 153bdd1243dSDimitry Andric 154bdd1243dSDimitry Andric static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, 155bdd1243dSDimitry Andric unsigned OpSize) { 156bdd1243dSDimitry Andric const bool IsStore = GenericOpc == TargetOpcode::G_STORE; 157bdd1243dSDimitry Andric switch (RegBankID) { 158bdd1243dSDimitry Andric case PPC::GPRRegBankID: 159bdd1243dSDimitry Andric switch (OpSize) { 160bdd1243dSDimitry Andric case 32: 161bdd1243dSDimitry Andric return IsStore ? PPC::STW : PPC::LWZ; 162bdd1243dSDimitry Andric case 64: 163bdd1243dSDimitry Andric return IsStore ? PPC::STD : PPC::LD; 164bdd1243dSDimitry Andric default: 165bdd1243dSDimitry Andric llvm_unreachable("Unexpected size!"); 166bdd1243dSDimitry Andric } 167bdd1243dSDimitry Andric break; 168bdd1243dSDimitry Andric case PPC::FPRRegBankID: 169bdd1243dSDimitry Andric switch (OpSize) { 170bdd1243dSDimitry Andric case 32: 171bdd1243dSDimitry Andric return IsStore ? PPC::STFS : PPC::LFS; 172bdd1243dSDimitry Andric case 64: 173bdd1243dSDimitry Andric return IsStore ? PPC::STFD : PPC::LFD; 174bdd1243dSDimitry Andric default: 175bdd1243dSDimitry Andric llvm_unreachable("Unexpected size!"); 176bdd1243dSDimitry Andric } 177bdd1243dSDimitry Andric break; 178bdd1243dSDimitry Andric default: 179bdd1243dSDimitry Andric llvm_unreachable("Unexpected register bank!"); 180bdd1243dSDimitry Andric } 181bdd1243dSDimitry Andric return GenericOpc; 182bdd1243dSDimitry Andric } 183bdd1243dSDimitry Andric 184bdd1243dSDimitry Andric bool PPCInstructionSelector::selectIntToFP(MachineInstr &I, 185bdd1243dSDimitry Andric MachineBasicBlock &MBB, 186bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const { 187bdd1243dSDimitry Andric if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT()) 188bdd1243dSDimitry Andric return false; 189bdd1243dSDimitry Andric 190bdd1243dSDimitry Andric const DebugLoc &DbgLoc = I.getDebugLoc(); 191bdd1243dSDimitry Andric const Register DstReg = I.getOperand(0).getReg(); 192bdd1243dSDimitry Andric const Register SrcReg = I.getOperand(1).getReg(); 193bdd1243dSDimitry Andric 194bdd1243dSDimitry Andric Register MoveReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 195bdd1243dSDimitry Andric 196bdd1243dSDimitry Andric // For now, only handle the case for 64 bit integer. 197bdd1243dSDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(PPC::MTVSRD), MoveReg).addReg(SrcReg); 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric bool IsSingle = MRI.getType(DstReg).getSizeInBits() == 32; 200bdd1243dSDimitry Andric bool IsSigned = I.getOpcode() == TargetOpcode::G_SITOFP; 201bdd1243dSDimitry Andric unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP) 202bdd1243dSDimitry Andric : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP); 203bdd1243dSDimitry Andric 204bdd1243dSDimitry Andric MachineInstr *MI = 205bdd1243dSDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), DstReg).addReg(MoveReg); 206bdd1243dSDimitry Andric 207bdd1243dSDimitry Andric I.eraseFromParent(); 208bdd1243dSDimitry Andric return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 209bdd1243dSDimitry Andric } 210bdd1243dSDimitry Andric 211bdd1243dSDimitry Andric bool PPCInstructionSelector::selectFPToInt(MachineInstr &I, 212bdd1243dSDimitry Andric MachineBasicBlock &MBB, 213bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const { 214bdd1243dSDimitry Andric if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT()) 215bdd1243dSDimitry Andric return false; 216bdd1243dSDimitry Andric 217bdd1243dSDimitry Andric const DebugLoc &DbgLoc = I.getDebugLoc(); 218bdd1243dSDimitry Andric const Register DstReg = I.getOperand(0).getReg(); 219bdd1243dSDimitry Andric const Register SrcReg = I.getOperand(1).getReg(); 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric Register CopyReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 222bdd1243dSDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(TargetOpcode::COPY), CopyReg).addReg(SrcReg); 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric Register ConvReg = MRI.createVirtualRegister(&PPC::VSFRCRegClass); 225bdd1243dSDimitry Andric 226bdd1243dSDimitry Andric bool IsSigned = I.getOpcode() == TargetOpcode::G_FPTOSI; 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric // single-precision is stored as double-precision on PPC in registers, so 229bdd1243dSDimitry Andric // always use double-precision convertions. 230bdd1243dSDimitry Andric unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS; 231bdd1243dSDimitry Andric 232bdd1243dSDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(ConvOp), ConvReg).addReg(CopyReg); 233bdd1243dSDimitry Andric 234bdd1243dSDimitry Andric MachineInstr *MI = 235bdd1243dSDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(PPC::MFVSRD), DstReg).addReg(ConvReg); 236bdd1243dSDimitry Andric 237bdd1243dSDimitry Andric I.eraseFromParent(); 238bdd1243dSDimitry Andric return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 239bdd1243dSDimitry Andric } 240bdd1243dSDimitry Andric 241bdd1243dSDimitry Andric bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB, 242bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const { 243bdd1243dSDimitry Andric const Register DstReg = I.getOperand(0).getReg(); 244bdd1243dSDimitry Andric const LLT DstTy = MRI.getType(DstReg); 245bdd1243dSDimitry Andric const RegisterBank *DstRegBank = RBI.getRegBank(DstReg, MRI, TRI); 246bdd1243dSDimitry Andric 247bdd1243dSDimitry Andric const Register SrcReg = I.getOperand(1).getReg(); 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric assert(DstTy.getSizeInBits() == 64 && "Unexpected dest size!"); 250bdd1243dSDimitry Andric assert(MRI.getType(SrcReg).getSizeInBits() == 32 && "Unexpected src size!"); 251bdd1243dSDimitry Andric 252bdd1243dSDimitry Andric Register ImpDefReg = 253bdd1243dSDimitry Andric MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); 254bdd1243dSDimitry Andric BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::IMPLICIT_DEF), 255bdd1243dSDimitry Andric ImpDefReg); 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric Register NewDefReg = 258bdd1243dSDimitry Andric MRI.createVirtualRegister(getRegClass(DstTy, DstRegBank)); 259bdd1243dSDimitry Andric BuildMI(MBB, I, I.getDebugLoc(), TII.get(TargetOpcode::INSERT_SUBREG), 260bdd1243dSDimitry Andric NewDefReg) 261bdd1243dSDimitry Andric .addReg(ImpDefReg) 262bdd1243dSDimitry Andric .addReg(SrcReg) 263bdd1243dSDimitry Andric .addImm(PPC::sub_32); 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric MachineInstr *MI = 266bdd1243dSDimitry Andric BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), DstReg) 267bdd1243dSDimitry Andric .addReg(NewDefReg) 268bdd1243dSDimitry Andric .addImm(0) 269bdd1243dSDimitry Andric .addImm(32); 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric I.eraseFromParent(); 272bdd1243dSDimitry Andric return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 273bdd1243dSDimitry Andric } 274bdd1243dSDimitry Andric 275bdd1243dSDimitry Andric // For any 32 < Num < 64, check if the Imm contains at least Num consecutive 276bdd1243dSDimitry Andric // zeros and return the number of bits by the left of these consecutive zeros. 277bdd1243dSDimitry Andric static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) { 27806c3fb27SDimitry Andric uint32_t HiTZ = llvm::countr_zero<uint32_t>(Hi_32(Imm)); 27906c3fb27SDimitry Andric uint32_t LoLZ = llvm::countl_zero<uint32_t>(Lo_32(Imm)); 280bdd1243dSDimitry Andric if ((HiTZ + LoLZ) >= Num) 281bdd1243dSDimitry Andric return (32 + HiTZ); 282bdd1243dSDimitry Andric return 0; 283bdd1243dSDimitry Andric } 284bdd1243dSDimitry Andric 285bdd1243dSDimitry Andric // Direct materialization of 64-bit constants by enumerated patterns. 286bdd1243dSDimitry Andric // Similar to PPCISelDAGToDAG::selectI64ImmDirect(). 287bdd1243dSDimitry Andric std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I, 288bdd1243dSDimitry Andric MachineBasicBlock &MBB, 289bdd1243dSDimitry Andric MachineRegisterInfo &MRI, 290bdd1243dSDimitry Andric Register Reg, 291bdd1243dSDimitry Andric uint64_t Imm) const { 29206c3fb27SDimitry Andric unsigned TZ = llvm::countr_zero<uint64_t>(Imm); 29306c3fb27SDimitry Andric unsigned LZ = llvm::countl_zero<uint64_t>(Imm); 29406c3fb27SDimitry Andric unsigned TO = llvm::countr_one<uint64_t>(Imm); 29506c3fb27SDimitry Andric unsigned LO = llvm::countl_one<uint64_t>(Imm); 296bdd1243dSDimitry Andric uint32_t Hi32 = Hi_32(Imm); 297bdd1243dSDimitry Andric uint32_t Lo32 = Lo_32(Imm); 298bdd1243dSDimitry Andric uint32_t Shift = 0; 299bdd1243dSDimitry Andric 300bdd1243dSDimitry Andric // Following patterns use 1 instructions to materialize the Imm. 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric // 1-1) Patterns : {zeros}{15-bit valve} 303bdd1243dSDimitry Andric // {ones}{15-bit valve} 304bdd1243dSDimitry Andric if (isInt<16>(Imm)) 305bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg) 306bdd1243dSDimitry Andric .addImm(Imm) 307bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 308bdd1243dSDimitry Andric // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros} 309bdd1243dSDimitry Andric // {ones}{15-bit valve}{16 zeros} 310bdd1243dSDimitry Andric if (TZ > 15 && (LZ > 32 || LO > 32)) 311bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg) 312bdd1243dSDimitry Andric .addImm((Imm >> 16) & 0xffff) 313bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric // Following patterns use 2 instructions to materialize the Imm. 316bdd1243dSDimitry Andric 317bdd1243dSDimitry Andric assert(LZ < 64 && "Unexpected leading zeros here."); 318bdd1243dSDimitry Andric // Count of ones follwing the leading zeros. 31906c3fb27SDimitry Andric unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ); 320bdd1243dSDimitry Andric // 2-1) Patterns : {zeros}{31-bit value} 321bdd1243dSDimitry Andric // {ones}{31-bit value} 322bdd1243dSDimitry Andric if (isInt<32>(Imm)) { 323bdd1243dSDimitry Andric uint64_t ImmHi16 = (Imm >> 16) & 0xffff; 324bdd1243dSDimitry Andric unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 325bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 326bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 327bdd1243dSDimitry Andric .addImm((Imm >> 16) & 0xffff) 328bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 329bdd1243dSDimitry Andric return false; 330bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg) 331bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 332bdd1243dSDimitry Andric .addImm(Imm & 0xffff) 333bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros} 336bdd1243dSDimitry Andric // {zeros}{15-bit value}{zeros} 337bdd1243dSDimitry Andric // {zeros}{ones}{15-bit value} 338bdd1243dSDimitry Andric // {ones}{15-bit value}{zeros} 339bdd1243dSDimitry Andric // We can take advantage of LI's sign-extension semantics to generate leading 340bdd1243dSDimitry Andric // ones, and then use RLDIC to mask off the ones in both sides after rotation. 341bdd1243dSDimitry Andric if ((LZ + FO + TZ) > 48) { 342bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 343bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 344bdd1243dSDimitry Andric .addImm((Imm >> TZ) & 0xffff) 345bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 346bdd1243dSDimitry Andric return false; 347bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg) 348bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 349bdd1243dSDimitry Andric .addImm(TZ) 350bdd1243dSDimitry Andric .addImm(LZ) 351bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 352bdd1243dSDimitry Andric } 353bdd1243dSDimitry Andric // 2-3) Pattern : {zeros}{15-bit value}{ones} 354bdd1243dSDimitry Andric // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value, 355bdd1243dSDimitry Andric // therefore we can take advantage of LI's sign-extension semantics, and then 356bdd1243dSDimitry Andric // mask them off after rotation. 357bdd1243dSDimitry Andric // 358bdd1243dSDimitry Andric // +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+ 359bdd1243dSDimitry Andric // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1| 360bdd1243dSDimitry Andric // +------------------------+ +------------------------+ 361bdd1243dSDimitry Andric // 63 0 63 0 362bdd1243dSDimitry Andric // Imm (Imm >> (48 - LZ) & 0xffff) 363bdd1243dSDimitry Andric // +----sext-----|--16-bit--+ +clear-|-----------------+ 364bdd1243dSDimitry Andric // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111| 365bdd1243dSDimitry Andric // +------------------------+ +------------------------+ 366bdd1243dSDimitry Andric // 63 0 63 0 367bdd1243dSDimitry Andric // LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ 368bdd1243dSDimitry Andric if ((LZ + TO) > 48) { 369bdd1243dSDimitry Andric // Since the immediates with (LZ > 32) have been handled by previous 370bdd1243dSDimitry Andric // patterns, here we have (LZ <= 32) to make sure we will not shift right 371bdd1243dSDimitry Andric // the Imm by a negative value. 372bdd1243dSDimitry Andric assert(LZ <= 32 && "Unexpected shift value."); 373bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 374bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 375bdd1243dSDimitry Andric .addImm(Imm >> (48 - LZ) & 0xffff) 376bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 377bdd1243dSDimitry Andric return false; 378bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 379bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 380bdd1243dSDimitry Andric .addImm(48 - LZ) 381bdd1243dSDimitry Andric .addImm(LZ) 382bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 383bdd1243dSDimitry Andric } 384bdd1243dSDimitry Andric // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones} 385bdd1243dSDimitry Andric // {ones}{15-bit value}{ones} 386bdd1243dSDimitry Andric // We can take advantage of LI's sign-extension semantics to generate leading 387bdd1243dSDimitry Andric // ones, and then use RLDICL to mask off the ones in left sides (if required) 388bdd1243dSDimitry Andric // after rotation. 389bdd1243dSDimitry Andric // 390bdd1243dSDimitry Andric // +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+ 391bdd1243dSDimitry Andric // |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb| 392bdd1243dSDimitry Andric // +------------------------+ +------------------------+ 393bdd1243dSDimitry Andric // 63 0 63 0 394bdd1243dSDimitry Andric // Imm (Imm >> TO) & 0xffff 395bdd1243dSDimitry Andric // +----sext-----|--16-bit--+ +LZ|---------------------+ 396bdd1243dSDimitry Andric // |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111| 397bdd1243dSDimitry Andric // +------------------------+ +------------------------+ 398bdd1243dSDimitry Andric // 63 0 63 0 399bdd1243dSDimitry Andric // LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ 400bdd1243dSDimitry Andric if ((LZ + FO + TO) > 48) { 401bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 402bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 403bdd1243dSDimitry Andric .addImm((Imm >> TO) & 0xffff) 404bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 405bdd1243dSDimitry Andric return false; 406bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 407bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 408bdd1243dSDimitry Andric .addImm(TO) 409bdd1243dSDimitry Andric .addImm(LZ) 410bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 411bdd1243dSDimitry Andric } 412bdd1243dSDimitry Andric // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value} 413bdd1243dSDimitry Andric // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit 414bdd1243dSDimitry Andric // value, we can use LI for Lo16 without generating leading ones then add the 415bdd1243dSDimitry Andric // Hi16(in Lo32). 416bdd1243dSDimitry Andric if (LZ == 32 && ((Lo32 & 0x8000) == 0)) { 417bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 418bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 419bdd1243dSDimitry Andric .addImm(Lo32 & 0xffff) 420bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 421bdd1243dSDimitry Andric return false; 422bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg) 423bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 424bdd1243dSDimitry Andric .addImm(Lo32 >> 16) 425bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 426bdd1243dSDimitry Andric } 427bdd1243dSDimitry Andric // 2-6) Patterns : {******}{49 zeros}{******} 428bdd1243dSDimitry Andric // {******}{49 ones}{******} 429bdd1243dSDimitry Andric // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15 430bdd1243dSDimitry Andric // bits remain on both sides. Rotate right the Imm to construct an int<16> 431bdd1243dSDimitry Andric // value, use LI for int<16> value and then use RLDICL without mask to rotate 432bdd1243dSDimitry Andric // it back. 433bdd1243dSDimitry Andric // 434bdd1243dSDimitry Andric // 1) findContiguousZerosAtLeast(Imm, 49) 435bdd1243dSDimitry Andric // +------|--zeros-|------+ +---ones--||---15 bit--+ 436bdd1243dSDimitry Andric // |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb| 437bdd1243dSDimitry Andric // +----------------------+ +----------------------+ 438bdd1243dSDimitry Andric // 63 0 63 0 439bdd1243dSDimitry Andric // 440bdd1243dSDimitry Andric // 2) findContiguousZerosAtLeast(~Imm, 49) 441bdd1243dSDimitry Andric // +------|--ones--|------+ +---ones--||---15 bit--+ 442bdd1243dSDimitry Andric // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb| 443bdd1243dSDimitry Andric // +----------------------+ +----------------------+ 444bdd1243dSDimitry Andric // 63 0 63 0 445bdd1243dSDimitry Andric if ((Shift = findContiguousZerosAtLeast(Imm, 49)) || 446bdd1243dSDimitry Andric (Shift = findContiguousZerosAtLeast(~Imm, 49))) { 447bdd1243dSDimitry Andric uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue(); 448bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 449bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg) 450bdd1243dSDimitry Andric .addImm(RotImm & 0xffff) 451bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 452bdd1243dSDimitry Andric return false; 453bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 454bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 455bdd1243dSDimitry Andric .addImm(Shift) 456bdd1243dSDimitry Andric .addImm(0) 457bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric // Following patterns use 3 instructions to materialize the Imm. 461bdd1243dSDimitry Andric 462bdd1243dSDimitry Andric // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros} 463bdd1243dSDimitry Andric // {zeros}{31-bit value}{zeros} 464bdd1243dSDimitry Andric // {zeros}{ones}{31-bit value} 465bdd1243dSDimitry Andric // {ones}{31-bit value}{zeros} 466bdd1243dSDimitry Andric // We can take advantage of LIS's sign-extension semantics to generate leading 467bdd1243dSDimitry Andric // ones, add the remaining bits with ORI, and then use RLDIC to mask off the 468bdd1243dSDimitry Andric // ones in both sides after rotation. 469bdd1243dSDimitry Andric if ((LZ + FO + TZ) > 32) { 470bdd1243dSDimitry Andric uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff; 471bdd1243dSDimitry Andric unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 472bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 473bdd1243dSDimitry Andric Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 474bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 475bdd1243dSDimitry Andric .addImm(ImmHi16) 476bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 477bdd1243dSDimitry Andric return false; 478bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 479bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 480bdd1243dSDimitry Andric .addImm((Imm >> TZ) & 0xffff) 481bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 482bdd1243dSDimitry Andric return false; 483bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg) 484bdd1243dSDimitry Andric .addReg(Tmp2Reg, RegState::Kill) 485bdd1243dSDimitry Andric .addImm(TZ) 486bdd1243dSDimitry Andric .addImm(LZ) 487bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 488bdd1243dSDimitry Andric } 489bdd1243dSDimitry Andric // 3-2) Pattern : {zeros}{31-bit value}{ones} 490bdd1243dSDimitry Andric // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits 491bdd1243dSDimitry Andric // value, therefore we can take advantage of LIS's sign-extension semantics, 492bdd1243dSDimitry Andric // add the remaining bits with ORI, and then mask them off after rotation. 493bdd1243dSDimitry Andric // This is similar to Pattern 2-3, please refer to the diagram there. 494bdd1243dSDimitry Andric if ((LZ + TO) > 32) { 495bdd1243dSDimitry Andric // Since the immediates with (LZ > 32) have been handled by previous 496bdd1243dSDimitry Andric // patterns, here we have (LZ <= 32) to make sure we will not shift right 497bdd1243dSDimitry Andric // the Imm by a negative value. 498bdd1243dSDimitry Andric assert(LZ <= 32 && "Unexpected shift value."); 499bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 500bdd1243dSDimitry Andric Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 501bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg) 502bdd1243dSDimitry Andric .addImm((Imm >> (48 - LZ)) & 0xffff) 503bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 504bdd1243dSDimitry Andric return false; 505bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 506bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 507bdd1243dSDimitry Andric .addImm((Imm >> (32 - LZ)) & 0xffff) 508bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 509bdd1243dSDimitry Andric return false; 510bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 511bdd1243dSDimitry Andric .addReg(Tmp2Reg, RegState::Kill) 512bdd1243dSDimitry Andric .addImm(32 - LZ) 513bdd1243dSDimitry Andric .addImm(LZ) 514bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 515bdd1243dSDimitry Andric } 516bdd1243dSDimitry Andric // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones} 517bdd1243dSDimitry Andric // {ones}{31-bit value}{ones} 518bdd1243dSDimitry Andric // We can take advantage of LIS's sign-extension semantics to generate leading 519bdd1243dSDimitry Andric // ones, add the remaining bits with ORI, and then use RLDICL to mask off the 520bdd1243dSDimitry Andric // ones in left sides (if required) after rotation. 521bdd1243dSDimitry Andric // This is similar to Pattern 2-4, please refer to the diagram there. 522bdd1243dSDimitry Andric if ((LZ + FO + TO) > 32) { 523bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 524bdd1243dSDimitry Andric Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 525bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg) 526bdd1243dSDimitry Andric .addImm((Imm >> (TO + 16)) & 0xffff) 527bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 528bdd1243dSDimitry Andric return false; 529bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 530bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 531bdd1243dSDimitry Andric .addImm((Imm >> TO) & 0xffff) 532bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 533bdd1243dSDimitry Andric return false; 534bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 535bdd1243dSDimitry Andric .addReg(Tmp2Reg, RegState::Kill) 536bdd1243dSDimitry Andric .addImm(TO) 537bdd1243dSDimitry Andric .addImm(LZ) 538bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 539bdd1243dSDimitry Andric } 540bdd1243dSDimitry Andric // 3-4) Patterns : High word == Low word 541bdd1243dSDimitry Andric if (Hi32 == Lo32) { 542bdd1243dSDimitry Andric // Handle the first 32 bits. 543bdd1243dSDimitry Andric uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff; 544bdd1243dSDimitry Andric unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 545bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 546bdd1243dSDimitry Andric Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 547bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 548bdd1243dSDimitry Andric .addImm(ImmHi16) 549bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 550bdd1243dSDimitry Andric return false; 551bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 552bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 553bdd1243dSDimitry Andric .addImm(Lo32 & 0xffff) 554bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 555bdd1243dSDimitry Andric return false; 556bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg) 557bdd1243dSDimitry Andric .addReg(Tmp2Reg) 558bdd1243dSDimitry Andric .addReg(Tmp2Reg, RegState::Kill) 559bdd1243dSDimitry Andric .addImm(32) 560bdd1243dSDimitry Andric .addImm(0) 561bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 562bdd1243dSDimitry Andric } 563bdd1243dSDimitry Andric // 3-5) Patterns : {******}{33 zeros}{******} 564bdd1243dSDimitry Andric // {******}{33 ones}{******} 565bdd1243dSDimitry Andric // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31 566bdd1243dSDimitry Andric // bits remain on both sides. Rotate right the Imm to construct an int<32> 567bdd1243dSDimitry Andric // value, use LIS + ORI for int<32> value and then use RLDICL without mask to 568bdd1243dSDimitry Andric // rotate it back. 569bdd1243dSDimitry Andric // This is similar to Pattern 2-6, please refer to the diagram there. 570bdd1243dSDimitry Andric if ((Shift = findContiguousZerosAtLeast(Imm, 33)) || 571bdd1243dSDimitry Andric (Shift = findContiguousZerosAtLeast(~Imm, 33))) { 572bdd1243dSDimitry Andric uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue(); 573bdd1243dSDimitry Andric uint64_t ImmHi16 = (RotImm >> 16) & 0xffff; 574bdd1243dSDimitry Andric unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8; 575bdd1243dSDimitry Andric Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 576bdd1243dSDimitry Andric Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 577bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg) 578bdd1243dSDimitry Andric .addImm(ImmHi16) 579bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 580bdd1243dSDimitry Andric return false; 581bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg) 582bdd1243dSDimitry Andric .addReg(TmpReg, RegState::Kill) 583bdd1243dSDimitry Andric .addImm(RotImm & 0xffff) 584bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 585bdd1243dSDimitry Andric return false; 586bdd1243dSDimitry Andric return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg) 587bdd1243dSDimitry Andric .addReg(Tmp2Reg, RegState::Kill) 588bdd1243dSDimitry Andric .addImm(Shift) 589bdd1243dSDimitry Andric .addImm(0) 590bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI); 591bdd1243dSDimitry Andric } 592bdd1243dSDimitry Andric 593bdd1243dSDimitry Andric // If we end up here then no instructions were inserted. 594bdd1243dSDimitry Andric return std::nullopt; 595bdd1243dSDimitry Andric } 596bdd1243dSDimitry Andric 597bdd1243dSDimitry Andric // Derived from PPCISelDAGToDAG::selectI64Imm(). 598bdd1243dSDimitry Andric // TODO: Add support for prefixed instructions. 599bdd1243dSDimitry Andric bool PPCInstructionSelector::selectI64Imm(MachineInstr &I, 600bdd1243dSDimitry Andric MachineBasicBlock &MBB, 601bdd1243dSDimitry Andric MachineRegisterInfo &MRI) const { 602bdd1243dSDimitry Andric assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code"); 603bdd1243dSDimitry Andric 604bdd1243dSDimitry Andric Register DstReg = I.getOperand(0).getReg(); 605bdd1243dSDimitry Andric int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue(); 606bdd1243dSDimitry Andric // No more than 3 instructions are used if we can select the i64 immediate 607bdd1243dSDimitry Andric // directly. 608bdd1243dSDimitry Andric if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) { 609bdd1243dSDimitry Andric I.eraseFromParent(); 610bdd1243dSDimitry Andric return *Res; 611bdd1243dSDimitry Andric } 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric // Calculate the last bits as required. 614bdd1243dSDimitry Andric uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff; 615bdd1243dSDimitry Andric uint32_t Lo16 = Lo_32(Imm) & 0xffff; 616bdd1243dSDimitry Andric 617bdd1243dSDimitry Andric Register Reg = 618bdd1243dSDimitry Andric (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg; 619bdd1243dSDimitry Andric 620bdd1243dSDimitry Andric // Handle the upper 32 bit value. 621bdd1243dSDimitry Andric std::optional<bool> Res = 622bdd1243dSDimitry Andric selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000); 623bdd1243dSDimitry Andric if (!Res || !*Res) 624bdd1243dSDimitry Andric return false; 625bdd1243dSDimitry Andric 626bdd1243dSDimitry Andric // Add in the last bits as required. 627bdd1243dSDimitry Andric if (Hi16) { 628bdd1243dSDimitry Andric Register TmpReg = 629bdd1243dSDimitry Andric Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg; 630bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg) 631bdd1243dSDimitry Andric .addReg(Reg, RegState::Kill) 632bdd1243dSDimitry Andric .addImm(Hi16) 633bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 634bdd1243dSDimitry Andric return false; 635bdd1243dSDimitry Andric Reg = TmpReg; 636bdd1243dSDimitry Andric } 637bdd1243dSDimitry Andric if (Lo16) { 638bdd1243dSDimitry Andric if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg) 639bdd1243dSDimitry Andric .addReg(Reg, RegState::Kill) 640bdd1243dSDimitry Andric .addImm(Lo16) 641bdd1243dSDimitry Andric .constrainAllUses(TII, TRI, RBI)) 642bdd1243dSDimitry Andric return false; 643bdd1243dSDimitry Andric } 644bdd1243dSDimitry Andric I.eraseFromParent(); 645bdd1243dSDimitry Andric return true; 646bdd1243dSDimitry Andric } 647bdd1243dSDimitry Andric 64806c3fb27SDimitry Andric bool PPCInstructionSelector::selectConstantPool( 64906c3fb27SDimitry Andric MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const { 65006c3fb27SDimitry Andric const DebugLoc &DbgLoc = I.getDebugLoc(); 65106c3fb27SDimitry Andric MachineFunction *MF = MBB.getParent(); 65206c3fb27SDimitry Andric 65306c3fb27SDimitry Andric // TODO: handle 32-bit. 65406c3fb27SDimitry Andric // TODO: Enabling floating point constant pool selection on AIX requires 65506c3fb27SDimitry Andric // global isel on big endian target enabled first. 65606c3fb27SDimitry Andric // See CallLowering::enableBigEndian(). 65706c3fb27SDimitry Andric if (!STI.isPPC64() || !STI.isLittleEndian()) 65806c3fb27SDimitry Andric return false; 65906c3fb27SDimitry Andric 66006c3fb27SDimitry Andric MF->getInfo<PPCFunctionInfo>()->setUsesTOCBasePtr(); 66106c3fb27SDimitry Andric 66206c3fb27SDimitry Andric const Register DstReg = I.getOperand(0).getReg(); 66306c3fb27SDimitry Andric unsigned CPI = I.getOperand(1).getIndex(); 66406c3fb27SDimitry Andric 66506c3fb27SDimitry Andric // Address stored in the TOC entry. This is related to code model and the ABI 66606c3fb27SDimitry Andric // we are currently using. For now we only handle 64-bit Linux LE. PowerPC 66706c3fb27SDimitry Andric // only supports small, medium and large code model. 66806c3fb27SDimitry Andric const CodeModel::Model CModel = TM.getCodeModel(); 66906c3fb27SDimitry Andric assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) && 67006c3fb27SDimitry Andric "PowerPC doesn't support tiny or kernel code models."); 67106c3fb27SDimitry Andric 67206c3fb27SDimitry Andric const MCRegister TOCReg = STI.getTOCPointerRegister(); 67306c3fb27SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 67406c3fb27SDimitry Andric MachinePointerInfo::getGOT(*MF), MachineMemOperand::MOLoad, 67506c3fb27SDimitry Andric MRI.getType(DstReg), MF->getDataLayout().getPointerABIAlignment(0)); 67606c3fb27SDimitry Andric 67706c3fb27SDimitry Andric MachineInstr *MI = nullptr; 67806c3fb27SDimitry Andric // For now we only handle 64-bit Linux. 67906c3fb27SDimitry Andric if (CModel == CodeModel::Small) { 68006c3fb27SDimitry Andric // For small code model, generate LDtocCPT(CPI, X2). 68106c3fb27SDimitry Andric MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocCPT), DstReg) 68206c3fb27SDimitry Andric .addConstantPoolIndex(CPI) 68306c3fb27SDimitry Andric .addReg(TOCReg) 68406c3fb27SDimitry Andric .addMemOperand(MMO); 68506c3fb27SDimitry Andric } else { 68606c3fb27SDimitry Andric Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass); 68706c3fb27SDimitry Andric BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDIStocHA8), HaAddrReg) 68806c3fb27SDimitry Andric .addReg(TOCReg) 68906c3fb27SDimitry Andric .addConstantPoolIndex(CPI); 69006c3fb27SDimitry Andric 69106c3fb27SDimitry Andric if (CModel == CodeModel::Large) 69206c3fb27SDimitry Andric // For large code model, generate LDtocL(CPI, ADDIStocHA8(X2, CPI)) 69306c3fb27SDimitry Andric MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocL), DstReg) 69406c3fb27SDimitry Andric .addConstantPoolIndex(CPI) 69506c3fb27SDimitry Andric .addReg(HaAddrReg) 69606c3fb27SDimitry Andric .addMemOperand(MMO); 69706c3fb27SDimitry Andric else 698*0fca6ea1SDimitry Andric // For medium code model, generate ADDItocL8(CPI, ADDIStocHA8(X2, CPI)) 699*0fca6ea1SDimitry Andric MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL8), DstReg) 70006c3fb27SDimitry Andric .addReg(HaAddrReg) 70106c3fb27SDimitry Andric .addConstantPoolIndex(CPI); 70206c3fb27SDimitry Andric } 70306c3fb27SDimitry Andric 70406c3fb27SDimitry Andric I.eraseFromParent(); 70506c3fb27SDimitry Andric return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); 70606c3fb27SDimitry Andric } 70706c3fb27SDimitry Andric 708e8d8bef9SDimitry Andric bool PPCInstructionSelector::select(MachineInstr &I) { 709bdd1243dSDimitry Andric auto &MBB = *I.getParent(); 710bdd1243dSDimitry Andric auto &MF = *MBB.getParent(); 711bdd1243dSDimitry Andric auto &MRI = MF.getRegInfo(); 712bdd1243dSDimitry Andric 713bdd1243dSDimitry Andric if (!isPreISelGenericOpcode(I.getOpcode())) { 714bdd1243dSDimitry Andric if (I.isCopy()) 715bdd1243dSDimitry Andric return selectCopy(I, TII, MRI, TRI, RBI); 716bdd1243dSDimitry Andric 717bdd1243dSDimitry Andric return true; 718bdd1243dSDimitry Andric } 719bdd1243dSDimitry Andric 720e8d8bef9SDimitry Andric if (selectImpl(I, *CoverageInfo)) 721e8d8bef9SDimitry Andric return true; 722bdd1243dSDimitry Andric 723bdd1243dSDimitry Andric unsigned Opcode = I.getOpcode(); 724bdd1243dSDimitry Andric 725bdd1243dSDimitry Andric switch (Opcode) { 726bdd1243dSDimitry Andric default: 727bdd1243dSDimitry Andric return false; 728bdd1243dSDimitry Andric case TargetOpcode::G_LOAD: 729bdd1243dSDimitry Andric case TargetOpcode::G_STORE: { 730bdd1243dSDimitry Andric GLoadStore &LdSt = cast<GLoadStore>(I); 731bdd1243dSDimitry Andric LLT PtrTy = MRI.getType(LdSt.getPointerReg()); 732bdd1243dSDimitry Andric 733bdd1243dSDimitry Andric if (PtrTy != LLT::pointer(0, 64)) { 734bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Load/Store pointer has type: " << PtrTy 735bdd1243dSDimitry Andric << ", expected: " << LLT::pointer(0, 64) << '\n'); 736bdd1243dSDimitry Andric return false; 737bdd1243dSDimitry Andric } 738bdd1243dSDimitry Andric 739bdd1243dSDimitry Andric auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * { 740bdd1243dSDimitry Andric const unsigned NewOpc = selectLoadStoreOp( 741bdd1243dSDimitry Andric I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(), 742*0fca6ea1SDimitry Andric LdSt.getMemSizeInBits().getValue()); 743bdd1243dSDimitry Andric 744bdd1243dSDimitry Andric if (NewOpc == I.getOpcode()) 745bdd1243dSDimitry Andric return nullptr; 746bdd1243dSDimitry Andric 747bdd1243dSDimitry Andric // For now, simply use DForm with load/store addr as base and 0 as imm. 748bdd1243dSDimitry Andric // FIXME: optimize load/store with some specific address patterns. 749bdd1243dSDimitry Andric I.setDesc(TII.get(NewOpc)); 750bdd1243dSDimitry Andric Register AddrReg = I.getOperand(1).getReg(); 751bdd1243dSDimitry Andric bool IsKill = I.getOperand(1).isKill(); 752bdd1243dSDimitry Andric I.getOperand(1).ChangeToImmediate(0); 753bdd1243dSDimitry Andric I.addOperand(*I.getParent()->getParent(), 754bdd1243dSDimitry Andric MachineOperand::CreateReg(AddrReg, /* isDef */ false, 755bdd1243dSDimitry Andric /* isImp */ false, IsKill)); 756bdd1243dSDimitry Andric return &I; 757bdd1243dSDimitry Andric }; 758bdd1243dSDimitry Andric 759bdd1243dSDimitry Andric MachineInstr *LoadStore = SelectLoadStoreAddressingMode(); 760bdd1243dSDimitry Andric if (!LoadStore) 761bdd1243dSDimitry Andric return false; 762bdd1243dSDimitry Andric 763bdd1243dSDimitry Andric return constrainSelectedInstRegOperands(*LoadStore, TII, TRI, RBI); 764bdd1243dSDimitry Andric } 765bdd1243dSDimitry Andric case TargetOpcode::G_SITOFP: 766bdd1243dSDimitry Andric case TargetOpcode::G_UITOFP: 767bdd1243dSDimitry Andric return selectIntToFP(I, MBB, MRI); 768bdd1243dSDimitry Andric case TargetOpcode::G_FPTOSI: 769bdd1243dSDimitry Andric case TargetOpcode::G_FPTOUI: 770bdd1243dSDimitry Andric return selectFPToInt(I, MBB, MRI); 771bdd1243dSDimitry Andric // G_SEXT will be selected in tb-gen pattern. 772bdd1243dSDimitry Andric case TargetOpcode::G_ZEXT: 773bdd1243dSDimitry Andric return selectZExt(I, MBB, MRI); 774bdd1243dSDimitry Andric case TargetOpcode::G_CONSTANT: 775bdd1243dSDimitry Andric return selectI64Imm(I, MBB, MRI); 77606c3fb27SDimitry Andric case TargetOpcode::G_CONSTANT_POOL: 77706c3fb27SDimitry Andric return selectConstantPool(I, MBB, MRI); 778bdd1243dSDimitry Andric } 779e8d8bef9SDimitry Andric return false; 780e8d8bef9SDimitry Andric } 781e8d8bef9SDimitry Andric 782e8d8bef9SDimitry Andric namespace llvm { 783e8d8bef9SDimitry Andric InstructionSelector * 784e8d8bef9SDimitry Andric createPPCInstructionSelector(const PPCTargetMachine &TM, 785e8d8bef9SDimitry Andric const PPCSubtarget &Subtarget, 786e8d8bef9SDimitry Andric const PPCRegisterBankInfo &RBI) { 787e8d8bef9SDimitry Andric return new PPCInstructionSelector(TM, Subtarget, RBI); 788e8d8bef9SDimitry Andric } 789e8d8bef9SDimitry Andric } // end namespace llvm 790