| //===-- SIRegisterInfo.h - SI Register Info Interface ----------*- C++ -*--===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file |
| /// Interface definition for SIRegisterInfo |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_TARGET_AMDGPU_SIREGISTERINFO_H |
| #define LLVM_LIB_TARGET_AMDGPU_SIREGISTERINFO_H |
| |
| #define GET_REGINFO_HEADER |
| #include "AMDGPUGenRegisterInfo.inc" |
| |
| #include "SIDefines.h" |
| |
| namespace llvm { |
| |
| class GCNSubtarget; |
| class LiveIntervals; |
| class LivePhysRegs; |
| class RegisterBank; |
| struct SGPRSpillBuilder; |
| |
| class SIRegisterInfo final : public AMDGPUGenRegisterInfo { |
| private: |
| const GCNSubtarget &ST; |
| bool SpillSGPRToVGPR; |
| bool isWave32; |
| BitVector RegPressureIgnoredUnits; |
| |
| /// Sub reg indexes for getRegSplitParts. |
| /// First index represents subreg size from 1 to 16 DWORDs. |
| /// The inner vector is sorted by bit offset. |
| /// Provided a register can be fully split with given subregs, |
| /// all elements of the inner vector combined give a full lane mask. |
| static std::array<std::vector<int16_t>, 16> RegSplitParts; |
| |
| // Table representing sub reg of given width and offset. |
| // First index is subreg size: 32, 64, 96, 128, 160, 192, 224, 256, 512. |
| // Second index is 32 different dword offsets. |
| static std::array<std::array<uint16_t, 32>, 9> SubRegFromChannelTable; |
| |
| void reserveRegisterTuples(BitVector &, MCRegister Reg) const; |
| |
| public: |
| SIRegisterInfo(const GCNSubtarget &ST); |
| |
| /// \returns the sub reg enum value for the given \p Channel |
| /// (e.g. getSubRegFromChannel(0) -> AMDGPU::sub0) |
| static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs = 1); |
| |
| bool spillSGPRToVGPR() const { |
| return SpillSGPRToVGPR; |
| } |
| |
| /// Return the end register initially reserved for the scratch buffer in case |
| /// spilling is needed. |
| MCRegister reservedPrivateSegmentBufferReg(const MachineFunction &MF) const; |
| |
| BitVector getReservedRegs(const MachineFunction &MF) const override; |
| |
| const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; |
| const MCPhysReg *getCalleeSavedRegsViaCopy(const MachineFunction *MF) const; |
| const uint32_t *getCallPreservedMask(const MachineFunction &MF, |
| CallingConv::ID) const override; |
| const uint32_t *getNoPreservedMask() const override; |
| |
| // Stack access is very expensive. CSRs are also the high registers, and we |
| // want to minimize the number of used registers. |
| unsigned getCSRFirstUseCost() const override { |
| return 100; |
| } |
| |
| const TargetRegisterClass * |
| getLargestLegalSuperClass(const TargetRegisterClass *RC, |
| const MachineFunction &MF) const override; |
| |
| Register getFrameRegister(const MachineFunction &MF) const override; |
| |
| bool hasBasePointer(const MachineFunction &MF) const; |
| Register getBaseRegister() const; |
| |
| bool shouldRealignStack(const MachineFunction &MF) const override; |
| bool requiresRegisterScavenging(const MachineFunction &Fn) const override; |
| |
| bool requiresFrameIndexScavenging(const MachineFunction &MF) const override; |
| bool requiresFrameIndexReplacementScavenging( |
| const MachineFunction &MF) const override; |
| bool requiresVirtualBaseRegisters(const MachineFunction &Fn) const override; |
| |
| int64_t getScratchInstrOffset(const MachineInstr *MI) const; |
| |
| int64_t getFrameIndexInstrOffset(const MachineInstr *MI, |
| int Idx) const override; |
| |
| bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; |
| |
| Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx, |
| int64_t Offset) const override; |
| |
| void resolveFrameIndex(MachineInstr &MI, Register BaseReg, |
| int64_t Offset) const override; |
| |
| bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg, |
| int64_t Offset) const override; |
| |
| const TargetRegisterClass *getPointerRegClass( |
| const MachineFunction &MF, unsigned Kind = 0) const override; |
| |
| /// Returns a legal register class to copy a register in the specified class |
| /// to or from. If it is possible to copy the register directly without using |
| /// a cross register class copy, return the specified RC. Returns NULL if it |
| /// is not possible to copy between two registers of the specified class. |
| const TargetRegisterClass * |
| getCrossCopyRegClass(const TargetRegisterClass *RC) const override; |
| |
| void buildVGPRSpillLoadStore(SGPRSpillBuilder &SB, int Index, int Offset, |
| bool IsLoad, bool IsKill = true) const; |
| |
| /// If \p OnlyToVGPR is true, this will only succeed if this |
| bool spillSGPR(MachineBasicBlock::iterator MI, |
| int FI, RegScavenger *RS, |
| LiveIntervals *LIS = nullptr, |
| bool OnlyToVGPR = false) const; |
| |
| bool restoreSGPR(MachineBasicBlock::iterator MI, |
| int FI, RegScavenger *RS, |
| LiveIntervals *LIS = nullptr, |
| bool OnlyToVGPR = false) const; |
| |
| bool spillEmergencySGPR(MachineBasicBlock::iterator MI, |
| MachineBasicBlock &RestoreMBB, Register SGPR, |
| RegScavenger *RS) const; |
| |
| void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, |
| unsigned FIOperandNum, |
| RegScavenger *RS) const override; |
| |
| bool eliminateSGPRToVGPRSpillFrameIndex(MachineBasicBlock::iterator MI, |
| int FI, RegScavenger *RS, |
| LiveIntervals *LIS = nullptr) const; |
| |
| StringRef getRegAsmName(MCRegister Reg) const override; |
| |
| // Pseudo regs are not allowed |
| unsigned getHWRegIndex(MCRegister Reg) const { |
| return getEncodingValue(Reg) & 0xff; |
| } |
| |
| LLVM_READONLY |
| const TargetRegisterClass *getVGPRClassForBitWidth(unsigned BitWidth) const; |
| |
| LLVM_READONLY |
| const TargetRegisterClass *getAGPRClassForBitWidth(unsigned BitWidth) const; |
| |
| LLVM_READONLY |
| const TargetRegisterClass * |
| getVectorSuperClassForBitWidth(unsigned BitWidth) const; |
| |
| LLVM_READONLY |
| static const TargetRegisterClass *getSGPRClassForBitWidth(unsigned BitWidth); |
| |
| /// Return the 'base' register class for this register. |
| /// e.g. SGPR0 => SReg_32, VGPR => VGPR_32 SGPR0_SGPR1 -> SReg_32, etc. |
| const TargetRegisterClass *getPhysRegClass(MCRegister Reg) const; |
| |
| /// \returns true if this class contains only SGPR registers |
| static bool isSGPRClass(const TargetRegisterClass *RC) { |
| return !hasVGPRs(RC) && !hasAGPRs(RC); |
| } |
| |
| /// \returns true if this class ID contains only SGPR registers |
| bool isSGPRClassID(unsigned RCID) const { |
| return isSGPRClass(getRegClass(RCID)); |
| } |
| |
| bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const; |
| |
| /// \returns true if this class contains only VGPR registers |
| static bool isVGPRClass(const TargetRegisterClass *RC) { |
| return hasVGPRs(RC) && !hasAGPRs(RC); |
| } |
| |
| /// \returns true if this class contains only AGPR registers |
| static bool isAGPRClass(const TargetRegisterClass *RC) { |
| return hasAGPRs(RC) && !hasVGPRs(RC); |
| } |
| |
| /// \returns true only if this class contains both VGPR and AGPR registers |
| bool isVectorSuperClass(const TargetRegisterClass *RC) const { |
| return hasVGPRs(RC) && hasAGPRs(RC); |
| } |
| |
| /// \returns true if this class contains VGPR registers. |
| static bool hasVGPRs(const TargetRegisterClass *RC) { |
| return RC->TSFlags & SIRCFlags::HasVGPR; |
| } |
| |
| /// \returns true if this class contains AGPR registers. |
| static bool hasAGPRs(const TargetRegisterClass *RC) { |
| return RC->TSFlags & SIRCFlags::HasAGPR; |
| } |
| |
| /// \returns true if this class contains any vector registers. |
| static bool hasVectorRegisters(const TargetRegisterClass *RC) { |
| return hasVGPRs(RC) || hasAGPRs(RC); |
| } |
| |
| /// \returns A VGPR reg class with the same width as \p SRC |
| const TargetRegisterClass * |
| getEquivalentVGPRClass(const TargetRegisterClass *SRC) const; |
| |
| /// \returns An AGPR reg class with the same width as \p SRC |
| const TargetRegisterClass * |
| getEquivalentAGPRClass(const TargetRegisterClass *SRC) const; |
| |
| /// \returns A SGPR reg class with the same width as \p SRC |
| const TargetRegisterClass * |
| getEquivalentSGPRClass(const TargetRegisterClass *VRC) const; |
| |
| /// \returns The canonical register class that is used for a sub-register of |
| /// \p RC for the given \p SubIdx. If \p SubIdx equals NoSubRegister, \p RC |
| /// will be returned. |
| const TargetRegisterClass *getSubRegClass(const TargetRegisterClass *RC, |
| unsigned SubIdx) const; |
| |
| /// Returns a register class which is compatible with \p SuperRC, such that a |
| /// subregister exists with class \p SubRC with subregister index \p |
| /// SubIdx. If this is impossible (e.g., an unaligned subregister index within |
| /// a register tuple), return null. |
| const TargetRegisterClass * |
| getCompatibleSubRegClass(const TargetRegisterClass *SuperRC, |
| const TargetRegisterClass *SubRC, |
| unsigned SubIdx) const; |
| |
| bool shouldRewriteCopySrc(const TargetRegisterClass *DefRC, |
| unsigned DefSubReg, |
| const TargetRegisterClass *SrcRC, |
| unsigned SrcSubReg) const override; |
| |
| /// \returns True if operands defined with this operand type can accept |
| /// a literal constant (i.e. any 32-bit immediate). |
| bool opCanUseLiteralConstant(unsigned OpType) const; |
| |
| /// \returns True if operands defined with this operand type can accept |
| /// an inline constant. i.e. An integer value in the range (-16, 64) or |
| /// -4.0f, -2.0f, -1.0f, -0.5f, 0.0f, 0.5f, 1.0f, 2.0f, 4.0f. |
| bool opCanUseInlineConstant(unsigned OpType) const; |
| |
| MCRegister findUnusedRegister(const MachineRegisterInfo &MRI, |
| const TargetRegisterClass *RC, |
| const MachineFunction &MF, |
| bool ReserveHighestVGPR = false) const; |
| |
| const TargetRegisterClass *getRegClassForReg(const MachineRegisterInfo &MRI, |
| Register Reg) const; |
| bool isVGPR(const MachineRegisterInfo &MRI, Register Reg) const; |
| bool isAGPR(const MachineRegisterInfo &MRI, Register Reg) const; |
| bool isVectorRegister(const MachineRegisterInfo &MRI, Register Reg) const { |
| return isVGPR(MRI, Reg) || isAGPR(MRI, Reg); |
| } |
| |
| bool isConstantPhysReg(MCRegister PhysReg) const override; |
| |
| bool isDivergentRegClass(const TargetRegisterClass *RC) const override { |
| return !isSGPRClass(RC); |
| } |
| |
| ArrayRef<int16_t> getRegSplitParts(const TargetRegisterClass *RC, |
| unsigned EltSize) const; |
| |
| bool shouldCoalesce(MachineInstr *MI, |
| const TargetRegisterClass *SrcRC, |
| unsigned SubReg, |
| const TargetRegisterClass *DstRC, |
| unsigned DstSubReg, |
| const TargetRegisterClass *NewRC, |
| LiveIntervals &LIS) const override; |
| |
| unsigned getRegPressureLimit(const TargetRegisterClass *RC, |
| MachineFunction &MF) const override; |
| |
| unsigned getRegPressureSetLimit(const MachineFunction &MF, |
| unsigned Idx) const override; |
| |
| const int *getRegUnitPressureSets(unsigned RegUnit) const override; |
| |
| MCRegister getReturnAddressReg(const MachineFunction &MF) const; |
| |
| const TargetRegisterClass * |
| getRegClassForSizeOnBank(unsigned Size, |
| const RegisterBank &Bank, |
| const MachineRegisterInfo &MRI) const; |
| |
| const TargetRegisterClass * |
| getRegClassForTypeOnBank(LLT Ty, |
| const RegisterBank &Bank, |
| const MachineRegisterInfo &MRI) const { |
| return getRegClassForSizeOnBank(Ty.getSizeInBits(), Bank, MRI); |
| } |
| |
| const TargetRegisterClass * |
| getConstrainedRegClassForOperand(const MachineOperand &MO, |
| const MachineRegisterInfo &MRI) const override; |
| |
| const TargetRegisterClass *getBoolRC() const { |
| return isWave32 ? &AMDGPU::SReg_32RegClass |
| : &AMDGPU::SReg_64RegClass; |
| } |
| |
| const TargetRegisterClass *getWaveMaskRegClass() const { |
| return isWave32 ? &AMDGPU::SReg_32_XM0_XEXECRegClass |
| : &AMDGPU::SReg_64_XEXECRegClass; |
| } |
| |
| // Return the appropriate register class to use for 64-bit VGPRs for the |
| // subtarget. |
| const TargetRegisterClass *getVGPR64Class() const; |
| |
| MCRegister getVCC() const; |
| |
| const TargetRegisterClass *getRegClass(unsigned RCID) const; |
| |
| // Find reaching register definition |
| MachineInstr *findReachingDef(Register Reg, unsigned SubReg, |
| MachineInstr &Use, |
| MachineRegisterInfo &MRI, |
| LiveIntervals *LIS) const; |
| |
| const uint32_t *getAllVGPRRegMask() const; |
| const uint32_t *getAllAGPRRegMask() const; |
| const uint32_t *getAllVectorRegMask() const; |
| const uint32_t *getAllAllocatableSRegMask() const; |
| |
| // \returns number of 32 bit registers covered by a \p LM |
| static unsigned getNumCoveredRegs(LaneBitmask LM) { |
| // The assumption is that every lo16 subreg is an even bit and every hi16 |
| // is an adjacent odd bit or vice versa. |
| uint64_t Mask = LM.getAsInteger(); |
| uint64_t Even = Mask & 0xAAAAAAAAAAAAAAAAULL; |
| Mask = (Even >> 1) | Mask; |
| uint64_t Odd = Mask & 0x5555555555555555ULL; |
| return countPopulation(Odd); |
| } |
| |
| // \returns a DWORD offset of a \p SubReg |
| unsigned getChannelFromSubReg(unsigned SubReg) const { |
| return SubReg ? (getSubRegIdxOffset(SubReg) + 31) / 32 : 0; |
| } |
| |
| // \returns a DWORD size of a \p SubReg |
| unsigned getNumChannelsFromSubReg(unsigned SubReg) const { |
| return getNumCoveredRegs(getSubRegIndexLaneMask(SubReg)); |
| } |
| |
| // For a given 16 bit \p Reg \returns a 32 bit register holding it. |
| // \returns \p Reg otherwise. |
| MCPhysReg get32BitRegister(MCPhysReg Reg) const; |
| |
| // Returns true if a given register class is properly aligned for |
| // the subtarget. |
| bool isProperlyAlignedRC(const TargetRegisterClass &RC) const; |
| |
| /// Return all SGPR128 which satisfy the waves per execution unit requirement |
| /// of the subtarget. |
| ArrayRef<MCPhysReg> getAllSGPR128(const MachineFunction &MF) const; |
| |
| /// Return all SGPR64 which satisfy the waves per execution unit requirement |
| /// of the subtarget. |
| ArrayRef<MCPhysReg> getAllSGPR64(const MachineFunction &MF) const; |
| |
| /// Return all SGPR32 which satisfy the waves per execution unit requirement |
| /// of the subtarget. |
| ArrayRef<MCPhysReg> getAllSGPR32(const MachineFunction &MF) const; |
| |
| // Insert spill or restore instructions. |
| // When lowering spill pseudos, the RegScavenger should be set. |
| // For creating spill instructions during frame lowering, where no scavenger |
| // is available, LiveRegs can be used. |
| void buildSpillLoadStore(MachineBasicBlock &MBB, |
| MachineBasicBlock::iterator MI, const DebugLoc &DL, |
| unsigned LoadStoreOp, int Index, Register ValueReg, |
| bool ValueIsKill, MCRegister ScratchOffsetReg, |
| int64_t InstrOffset, MachineMemOperand *MMO, |
| RegScavenger *RS, |
| LivePhysRegs *LiveRegs = nullptr) const; |
| }; |
| |
| } // End namespace llvm |
| |
| #endif |