25#include "llvm/IR/IntrinsicsPowerPC.h"
28#define DEBUG_TYPE "ppc-gisel"
34#define GET_GLOBALISEL_PREDICATE_BITSET
35#include "PPCGenGlobalISel.inc"
36#undef GET_GLOBALISEL_PREDICATE_BITSET
74#define GET_GLOBALISEL_PREDICATES_DECL
75#include "PPCGenGlobalISel.inc"
76#undef GET_GLOBALISEL_PREDICATES_DECL
78#define GET_GLOBALISEL_TEMPORARIES_DECL
79#include "PPCGenGlobalISel.inc"
80#undef GET_GLOBALISEL_TEMPORARIES_DECL
85#define GET_GLOBALISEL_IMPL
86#include "PPCGenGlobalISel.inc"
87#undef GET_GLOBALISEL_IMPL
92 :
TM(
TM), STI(STI),
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()),
95#include
"PPCGenGlobalISel.inc"
98#include
"PPCGenGlobalISel.inc"
104 if (RB->
getID() == PPC::GPRRegBankID) {
106 return &PPC::G8RCRegClass;
108 return &PPC::GPRCRegClass;
110 if (RB->
getID() == PPC::FPRRegBankID) {
112 return &PPC::F4RCRegClass;
114 return &PPC::F8RCRegClass;
116 if (RB->
getID() == PPC::CRRegBankID) {
118 return &PPC::CRBITRCRegClass;
120 return &PPC::CRRCRegClass;
129 Register DstReg =
I.getOperand(0).getReg();
152 const bool IsStore = GenericOpc == TargetOpcode::G_STORE;
154 case PPC::GPRRegBankID:
157 return IsStore ? PPC::STW : PPC::LWZ;
159 return IsStore ? PPC::STD : PPC::LD;
164 case PPC::FPRRegBankID:
167 return IsStore ? PPC::STFS : PPC::LFS;
169 return IsStore ? PPC::STFD : PPC::LFD;
183 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
186 const DebugLoc &DbgLoc =
I.getDebugLoc();
187 const Register DstReg =
I.getOperand(0).getReg();
188 const Register SrcReg =
I.getOperand(1).getReg();
195 bool IsSingle =
MRI.getType(DstReg).getSizeInBits() == 32;
196 bool IsSigned =
I.getOpcode() == TargetOpcode::G_SITOFP;
197 unsigned ConvOp = IsSingle ? (IsSigned ? PPC::XSCVSXDSP : PPC::XSCVUXDSP)
198 : (IsSigned ? PPC::XSCVSXDDP : PPC::XSCVUXDDP);
210 if (!STI.hasDirectMove() || !STI.isPPC64() || !STI.hasFPCVT())
213 const DebugLoc &DbgLoc =
I.getDebugLoc();
214 const Register DstReg =
I.getOperand(0).getReg();
215 const Register SrcReg =
I.getOperand(1).getReg();
217 Register CopyReg =
MRI.createVirtualRegister(&PPC::VSFRCRegClass);
220 Register ConvReg =
MRI.createVirtualRegister(&PPC::VSFRCRegClass);
222 bool IsSigned =
I.getOpcode() == TargetOpcode::G_FPTOSI;
226 unsigned ConvOp = IsSigned ? PPC::XSCVDPSXDS : PPC::XSCVDPUXDS;
239 const Register DstReg =
I.getOperand(0).getReg();
240 const LLT DstTy =
MRI.getType(DstReg);
243 const Register SrcReg =
I.getOperand(1).getReg();
246 assert(
MRI.getType(SrcReg).getSizeInBits() == 32 &&
"Unexpected src size!");
276 if ((HiTZ + LoLZ) >= Num)
283std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(
MachineInstr &
I,
288 unsigned TZ = llvm::countr_zero<uint64_t>(Imm);
289 unsigned LZ = llvm::countl_zero<uint64_t>(Imm);
290 unsigned TO = llvm::countr_one<uint64_t>(Imm);
291 unsigned LO = llvm::countl_one<uint64_t>(Imm);
306 if (TZ > 15 && (LZ > 32 || LO > 32))
308 .
addImm((Imm >> 16) & 0xffff)
313 assert(LZ < 64 &&
"Unexpected leading zeros here.");
315 unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ);
318 if (isInt<32>(Imm)) {
320 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
321 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
323 .
addImm((Imm >> 16) & 0xffff)
337 if ((LZ + FO + TZ) > 48) {
338 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
340 .
addImm((Imm >> TZ) & 0xffff)
364 if ((LZ + TO) > 48) {
368 assert(LZ <= 32 &&
"Unexpected shift value.");
369 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
371 .
addImm(Imm >> (48 - LZ) & 0xffff)
396 if ((LZ + FO + TO) > 48) {
397 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
399 .
addImm((Imm >> TO) & 0xffff)
412 if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
413 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
444 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
465 if ((LZ + FO + TZ) > 32) {
467 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
468 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
469 Register Tmp2Reg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
476 .
addImm((Imm >> TZ) & 0xffff)
477 .constrainAllUses(
TII,
TRI, RBI))
490 if ((LZ + TO) > 32) {
494 assert(LZ <= 32 &&
"Unexpected shift value.");
495 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
496 Register Tmp2Reg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
498 .
addImm((Imm >> (48 - LZ)) & 0xffff)
503 .
addImm((Imm >> (32 - LZ)) & 0xffff)
518 if ((LZ + FO + TO) > 32) {
519 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
520 Register Tmp2Reg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
522 .
addImm((Imm >> (TO + 16)) & 0xffff)
527 .
addImm((Imm >> TO) & 0xffff)
539 uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
540 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
541 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
542 Register Tmp2Reg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
569 uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;
570 unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
571 Register TmpReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
572 Register Tmp2Reg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
598 assert(
I.getOpcode() == TargetOpcode::G_CONSTANT &&
"Unexpected G code");
600 Register DstReg =
I.getOperand(0).getReg();
601 int64_t
Imm =
I.getOperand(1).getCImm()->getValue().getZExtValue();
614 (Hi16 || Lo16) ?
MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
617 std::optional<bool> Res =
625 Lo16 ?
MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
644bool PPCInstructionSelector::selectConstantPool(
646 const DebugLoc &DbgLoc =
I.getDebugLoc();
653 if (!STI.isPPC64() || !STI.isLittleEndian())
658 const Register DstReg =
I.getOperand(0).getReg();
659 unsigned CPI =
I.getOperand(1).getIndex();
666 "PowerPC doesn't support tiny or kernel code models.");
668 const MCRegister TOCReg = STI.getTOCPointerRegister();
682 Register HaAddrReg =
MRI.createVirtualRegister(&PPC::G8RCRegClass);
705 auto &
MBB = *
I.getParent();
716 if (selectImpl(
I, *CoverageInfo))
719 unsigned Opcode =
I.getOpcode();
724 case TargetOpcode::G_LOAD:
725 case TargetOpcode::G_STORE: {
735 auto SelectLoadStoreAddressingMode = [&]() ->
MachineInstr * {
737 I.getOpcode(), RBI.getRegBank(LdSt.
getReg(0),
MRI,
TRI)->getID(),
740 if (NewOpc ==
I.getOpcode())
745 I.setDesc(
TII.get(NewOpc));
746 Register AddrReg =
I.getOperand(1).getReg();
747 bool IsKill =
I.getOperand(1).isKill();
748 I.getOperand(1).ChangeToImmediate(0);
749 I.addOperand(*
I.getParent()->getParent(),
761 case TargetOpcode::G_SITOFP:
762 case TargetOpcode::G_UITOFP:
763 return selectIntToFP(
I,
MBB,
MRI);
764 case TargetOpcode::G_FPTOSI:
765 case TargetOpcode::G_FPTOUI:
766 return selectFPToInt(
I,
MBB,
MRI);
768 case TargetOpcode::G_ZEXT:
769 return selectZExt(
I,
MBB,
MRI);
770 case TargetOpcode::G_CONSTANT:
772 case TargetOpcode::G_CONSTANT_POOL:
773 return selectConstantPool(
I,
MBB,
MRI);
783 return new PPCInstructionSelector(
TM, Subtarget, RBI);
unsigned const MachineRegisterInfo * MRI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
static SDNode * selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm, unsigned &InstCnt)
static SDNode * selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm, unsigned *InstCnt=nullptr)
static void setUsesTOCBasePtr(MachineFunction &MF)
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num)
static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
This file declares the targeting of the RegisterBankInfo class for PowerPC.
const char LLVMTargetMachineRef TM
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
APInt rotr(unsigned rotateAmt) const
Rotate right by rotateAmt.
Align getPointerABIAlignment(unsigned AS) const
Layout pointer alignment.
Represents any type of generic load or store.
Register getPointerReg() const
Get the source register of the pointer value.
uint64_t getMemSizeInBits() const
Returns the size in bits of the memory access.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
Provides the logic to select generic machine instructions.
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Wrapper class representing physical registers. Should be passed by value.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PPCFunctionInfo - This class is derived from MachineFunction private PowerPC target-specific informat...
Common code between 32-bit and 64-bit PowerPC targets.
Holds all the information related to register banks.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
InstructionSelector * createPPCInstructionSelector(const PPCTargetMachine &TM, const PPCSubtarget &Subtarget, const PPCRegisterBankInfo &RBI)
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.