xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/SIRegisterInfo.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- SIRegisterInfo.h - SI Register Info Interface ----------*- C++ -*--===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Interface definition for SIRegisterInfo
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_SIREGISTERINFO_H
150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_SIREGISTERINFO_H
160b57cec5SDimitry Andric 
17*5f757f3fSDimitry Andric #include "llvm/ADT/BitVector.h"
18*5f757f3fSDimitry Andric 
195ffd83dbSDimitry Andric #define GET_REGINFO_HEADER
205ffd83dbSDimitry Andric #include "AMDGPUGenRegisterInfo.inc"
215ffd83dbSDimitry Andric 
22349cc55cSDimitry Andric #include "SIDefines.h"
23349cc55cSDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class GCNSubtarget;
270b57cec5SDimitry Andric class LiveIntervals;
28*5f757f3fSDimitry Andric class LiveRegUnits;
29e8d8bef9SDimitry Andric class RegisterBank;
30fe6060f1SDimitry Andric struct SGPRSpillBuilder;
310b57cec5SDimitry Andric 
325ffd83dbSDimitry Andric class SIRegisterInfo final : public AMDGPUGenRegisterInfo {
330b57cec5SDimitry Andric private:
348bcb0991SDimitry Andric   const GCNSubtarget &ST;
350b57cec5SDimitry Andric   bool SpillSGPRToVGPR;
360b57cec5SDimitry Andric   bool isWave32;
375ffd83dbSDimitry Andric   BitVector RegPressureIgnoredUnits;
380b57cec5SDimitry Andric 
395ffd83dbSDimitry Andric   /// Sub reg indexes for getRegSplitParts.
405ffd83dbSDimitry Andric   /// First index represents subreg size from 1 to 16 DWORDs.
415ffd83dbSDimitry Andric   /// The inner vector is sorted by bit offset.
425ffd83dbSDimitry Andric   /// Provided a register can be fully split with given subregs,
435ffd83dbSDimitry Andric   /// all elements of the inner vector combined give a full lane mask.
445ffd83dbSDimitry Andric   static std::array<std::vector<int16_t>, 16> RegSplitParts;
455ffd83dbSDimitry Andric 
46e8d8bef9SDimitry Andric   // Table representing sub reg of given width and offset.
47e8d8bef9SDimitry Andric   // First index is subreg size: 32, 64, 96, 128, 160, 192, 224, 256, 512.
48e8d8bef9SDimitry Andric   // Second index is 32 different dword offsets.
49e8d8bef9SDimitry Andric   static std::array<std::array<uint16_t, 32>, 9> SubRegFromChannelTable;
50e8d8bef9SDimitry Andric 
515ffd83dbSDimitry Andric   void reserveRegisterTuples(BitVector &, MCRegister Reg) const;
525ffd83dbSDimitry Andric 
530b57cec5SDimitry Andric public:
540b57cec5SDimitry Andric   SIRegisterInfo(const GCNSubtarget &ST);
550b57cec5SDimitry Andric 
5681ad6265SDimitry Andric   struct SpilledReg {
5781ad6265SDimitry Andric     Register VGPR;
5881ad6265SDimitry Andric     int Lane = -1;
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric     SpilledReg() = default;
6181ad6265SDimitry Andric     SpilledReg(Register R, int L) : VGPR(R), Lane(L) {}
6281ad6265SDimitry Andric 
6381ad6265SDimitry Andric     bool hasLane() { return Lane != -1; }
6481ad6265SDimitry Andric     bool hasReg() { return VGPR != 0; }
6581ad6265SDimitry Andric   };
6681ad6265SDimitry Andric 
675ffd83dbSDimitry Andric   /// \returns the sub reg enum value for the given \p Channel
685ffd83dbSDimitry Andric   /// (e.g. getSubRegFromChannel(0) -> AMDGPU::sub0)
695ffd83dbSDimitry Andric   static unsigned getSubRegFromChannel(unsigned Channel, unsigned NumRegs = 1);
705ffd83dbSDimitry Andric 
710b57cec5SDimitry Andric   bool spillSGPRToVGPR() const {
720b57cec5SDimitry Andric     return SpillSGPRToVGPR;
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric 
7506c3fb27SDimitry Andric   /// Return the largest available SGPR aligned to \p Align for the register
7606c3fb27SDimitry Andric   /// class \p RC.
7706c3fb27SDimitry Andric   MCRegister getAlignedHighSGPRForRC(const MachineFunction &MF,
7806c3fb27SDimitry Andric                                      const unsigned Align,
7906c3fb27SDimitry Andric                                      const TargetRegisterClass *RC) const;
8006c3fb27SDimitry Andric 
810b57cec5SDimitry Andric   /// Return the end register initially reserved for the scratch buffer in case
820b57cec5SDimitry Andric   /// spilling is needed.
835ffd83dbSDimitry Andric   MCRegister reservedPrivateSegmentBufferReg(const MachineFunction &MF) const;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   BitVector getReservedRegs(const MachineFunction &MF) const override;
8681ad6265SDimitry Andric   bool isAsmClobberable(const MachineFunction &MF,
8781ad6265SDimitry Andric                         MCRegister PhysReg) const override;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
900b57cec5SDimitry Andric   const MCPhysReg *getCalleeSavedRegsViaCopy(const MachineFunction *MF) const;
910b57cec5SDimitry Andric   const uint32_t *getCallPreservedMask(const MachineFunction &MF,
920b57cec5SDimitry Andric                                        CallingConv::ID) const override;
93e8d8bef9SDimitry Andric   const uint32_t *getNoPreservedMask() const override;
940b57cec5SDimitry Andric 
95*5f757f3fSDimitry Andric   // Functions with the amdgpu_cs_chain or amdgpu_cs_chain_preserve calling
96*5f757f3fSDimitry Andric   // conventions are free to use certain VGPRs without saving and restoring any
97*5f757f3fSDimitry Andric   // lanes (not even inactive ones).
98*5f757f3fSDimitry Andric   static bool isChainScratchRegister(Register VGPR);
99*5f757f3fSDimitry Andric 
1000b57cec5SDimitry Andric   // Stack access is very expensive. CSRs are also the high registers, and we
1010b57cec5SDimitry Andric   // want to minimize the number of used registers.
1020b57cec5SDimitry Andric   unsigned getCSRFirstUseCost() const override {
1030b57cec5SDimitry Andric     return 100;
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1064824e7fdSDimitry Andric   const TargetRegisterClass *
1074824e7fdSDimitry Andric   getLargestLegalSuperClass(const TargetRegisterClass *RC,
1084824e7fdSDimitry Andric                             const MachineFunction &MF) const override;
1094824e7fdSDimitry Andric 
1100b57cec5SDimitry Andric   Register getFrameRegister(const MachineFunction &MF) const override;
1110b57cec5SDimitry Andric 
1125ffd83dbSDimitry Andric   bool hasBasePointer(const MachineFunction &MF) const;
1135ffd83dbSDimitry Andric   Register getBaseRegister() const;
1145ffd83dbSDimitry Andric 
115fe6060f1SDimitry Andric   bool shouldRealignStack(const MachineFunction &MF) const override;
1160b57cec5SDimitry Andric   bool requiresRegisterScavenging(const MachineFunction &Fn) const override;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
1190b57cec5SDimitry Andric   bool requiresFrameIndexReplacementScavenging(
1200b57cec5SDimitry Andric     const MachineFunction &MF) const override;
1210b57cec5SDimitry Andric   bool requiresVirtualBaseRegisters(const MachineFunction &Fn) const override;
1220b57cec5SDimitry Andric 
123e8d8bef9SDimitry Andric   int64_t getScratchInstrOffset(const MachineInstr *MI) const;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   int64_t getFrameIndexInstrOffset(const MachineInstr *MI,
1260b57cec5SDimitry Andric                                    int Idx) const override;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override;
1290b57cec5SDimitry Andric 
130e8d8bef9SDimitry Andric   Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx,
1310b57cec5SDimitry Andric                                         int64_t Offset) const override;
1320b57cec5SDimitry Andric 
1335ffd83dbSDimitry Andric   void resolveFrameIndex(MachineInstr &MI, Register BaseReg,
1340b57cec5SDimitry Andric                          int64_t Offset) const override;
1350b57cec5SDimitry Andric 
1365ffd83dbSDimitry Andric   bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg,
1370b57cec5SDimitry Andric                           int64_t Offset) const override;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   const TargetRegisterClass *getPointerRegClass(
1400b57cec5SDimitry Andric     const MachineFunction &MF, unsigned Kind = 0) const override;
1410b57cec5SDimitry Andric 
142349cc55cSDimitry Andric   /// Returns a legal register class to copy a register in the specified class
143349cc55cSDimitry Andric   /// to or from. If it is possible to copy the register directly without using
144349cc55cSDimitry Andric   /// a cross register class copy, return the specified RC. Returns NULL if it
145349cc55cSDimitry Andric   /// is not possible to copy between two registers of the specified class.
146349cc55cSDimitry Andric   const TargetRegisterClass *
147349cc55cSDimitry Andric   getCrossCopyRegClass(const TargetRegisterClass *RC) const override;
148349cc55cSDimitry Andric 
149fe6060f1SDimitry Andric   void buildVGPRSpillLoadStore(SGPRSpillBuilder &SB, int Index, int Offset,
150fe6060f1SDimitry Andric                                bool IsLoad, bool IsKill = true) const;
1515ffd83dbSDimitry Andric 
152*5f757f3fSDimitry Andric   /// If \p OnlyToVGPR is true, this will only succeed if this manages to find a
153*5f757f3fSDimitry Andric   /// free VGPR lane to spill.
154bdd1243dSDimitry Andric   bool spillSGPR(MachineBasicBlock::iterator MI, int FI, RegScavenger *RS,
155bdd1243dSDimitry Andric                  SlotIndexes *Indexes = nullptr, LiveIntervals *LIS = nullptr,
156*5f757f3fSDimitry Andric                  bool OnlyToVGPR = false,
157*5f757f3fSDimitry Andric                  bool SpillToPhysVGPRLane = false) const;
1580b57cec5SDimitry Andric 
159bdd1243dSDimitry Andric   bool restoreSGPR(MachineBasicBlock::iterator MI, int FI, RegScavenger *RS,
160bdd1243dSDimitry Andric                    SlotIndexes *Indexes = nullptr, LiveIntervals *LIS = nullptr,
161*5f757f3fSDimitry Andric                    bool OnlyToVGPR = false,
162*5f757f3fSDimitry Andric                    bool SpillToPhysVGPRLane = false) const;
1630b57cec5SDimitry Andric 
164349cc55cSDimitry Andric   bool spillEmergencySGPR(MachineBasicBlock::iterator MI,
165349cc55cSDimitry Andric                           MachineBasicBlock &RestoreMBB, Register SGPR,
166349cc55cSDimitry Andric                           RegScavenger *RS) const;
167349cc55cSDimitry Andric 
168bdd1243dSDimitry Andric   bool eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
1690b57cec5SDimitry Andric                            unsigned FIOperandNum,
1700b57cec5SDimitry Andric                            RegScavenger *RS) const override;
1710b57cec5SDimitry Andric 
172*5f757f3fSDimitry Andric   bool eliminateSGPRToVGPRSpillFrameIndex(
173*5f757f3fSDimitry Andric       MachineBasicBlock::iterator MI, int FI, RegScavenger *RS,
174*5f757f3fSDimitry Andric       SlotIndexes *Indexes = nullptr, LiveIntervals *LIS = nullptr,
175*5f757f3fSDimitry Andric       bool SpillToPhysVGPRLane = false) const;
1760b57cec5SDimitry Andric 
1775ffd83dbSDimitry Andric   StringRef getRegAsmName(MCRegister Reg) const override;
1780b57cec5SDimitry Andric 
179e8d8bef9SDimitry Andric   // Pseudo regs are not allowed
1805ffd83dbSDimitry Andric   unsigned getHWRegIndex(MCRegister Reg) const {
1810b57cec5SDimitry Andric     return getEncodingValue(Reg) & 0xff;
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric 
184fe6060f1SDimitry Andric   LLVM_READONLY
185fe6060f1SDimitry Andric   const TargetRegisterClass *getVGPRClassForBitWidth(unsigned BitWidth) const;
186fe6060f1SDimitry Andric 
187fe6060f1SDimitry Andric   LLVM_READONLY
188fe6060f1SDimitry Andric   const TargetRegisterClass *getAGPRClassForBitWidth(unsigned BitWidth) const;
189fe6060f1SDimitry Andric 
190fe6060f1SDimitry Andric   LLVM_READONLY
1914824e7fdSDimitry Andric   const TargetRegisterClass *
1924824e7fdSDimitry Andric   getVectorSuperClassForBitWidth(unsigned BitWidth) const;
1934824e7fdSDimitry Andric 
1944824e7fdSDimitry Andric   LLVM_READONLY
1955ffd83dbSDimitry Andric   static const TargetRegisterClass *getSGPRClassForBitWidth(unsigned BitWidth);
1965ffd83dbSDimitry Andric 
1970b57cec5SDimitry Andric   /// \returns true if this class contains only SGPR registers
198349cc55cSDimitry Andric   static bool isSGPRClass(const TargetRegisterClass *RC) {
1994824e7fdSDimitry Andric     return hasSGPRs(RC) && !hasVGPRs(RC) && !hasAGPRs(RC);
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   /// \returns true if this class ID contains only SGPR registers
2030b57cec5SDimitry Andric   bool isSGPRClassID(unsigned RCID) const {
2040b57cec5SDimitry Andric     return isSGPRClass(getRegClass(RCID));
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
207e8d8bef9SDimitry Andric   bool isSGPRReg(const MachineRegisterInfo &MRI, Register Reg) const;
2080b57cec5SDimitry Andric 
209349cc55cSDimitry Andric   /// \returns true if this class contains only VGPR registers
210349cc55cSDimitry Andric   static bool isVGPRClass(const TargetRegisterClass *RC) {
2114824e7fdSDimitry Andric     return hasVGPRs(RC) && !hasAGPRs(RC) && !hasSGPRs(RC);
212349cc55cSDimitry Andric   }
213349cc55cSDimitry Andric 
214480093f4SDimitry Andric   /// \returns true if this class contains only AGPR registers
215349cc55cSDimitry Andric   static bool isAGPRClass(const TargetRegisterClass *RC) {
2164824e7fdSDimitry Andric     return hasAGPRs(RC) && !hasVGPRs(RC) && !hasSGPRs(RC);
2174824e7fdSDimitry Andric   }
2184824e7fdSDimitry Andric 
2194824e7fdSDimitry Andric   /// \returns true only if this class contains both VGPR and AGPR registers
2204824e7fdSDimitry Andric   bool isVectorSuperClass(const TargetRegisterClass *RC) const {
2214824e7fdSDimitry Andric     return hasVGPRs(RC) && hasAGPRs(RC) && !hasSGPRs(RC);
2224824e7fdSDimitry Andric   }
2234824e7fdSDimitry Andric 
2244824e7fdSDimitry Andric   /// \returns true only if this class contains both VGPR and SGPR registers
2254824e7fdSDimitry Andric   bool isVSSuperClass(const TargetRegisterClass *RC) const {
2264824e7fdSDimitry Andric     return hasVGPRs(RC) && hasSGPRs(RC) && !hasAGPRs(RC);
227480093f4SDimitry Andric   }
228480093f4SDimitry Andric 
2290b57cec5SDimitry Andric   /// \returns true if this class contains VGPR registers.
230349cc55cSDimitry Andric   static bool hasVGPRs(const TargetRegisterClass *RC) {
231349cc55cSDimitry Andric     return RC->TSFlags & SIRCFlags::HasVGPR;
232349cc55cSDimitry Andric   }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   /// \returns true if this class contains AGPR registers.
235349cc55cSDimitry Andric   static bool hasAGPRs(const TargetRegisterClass *RC) {
236349cc55cSDimitry Andric     return RC->TSFlags & SIRCFlags::HasAGPR;
237349cc55cSDimitry Andric   }
2380b57cec5SDimitry Andric 
2394824e7fdSDimitry Andric   /// \returns true if this class contains SGPR registers.
2404824e7fdSDimitry Andric   static bool hasSGPRs(const TargetRegisterClass *RC) {
2414824e7fdSDimitry Andric     return RC->TSFlags & SIRCFlags::HasSGPR;
2424824e7fdSDimitry Andric   }
2434824e7fdSDimitry Andric 
2440b57cec5SDimitry Andric   /// \returns true if this class contains any vector registers.
245349cc55cSDimitry Andric   static bool hasVectorRegisters(const TargetRegisterClass *RC) {
2460b57cec5SDimitry Andric     return hasVGPRs(RC) || hasAGPRs(RC);
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   /// \returns A VGPR reg class with the same width as \p SRC
2505ffd83dbSDimitry Andric   const TargetRegisterClass *
2515ffd83dbSDimitry Andric   getEquivalentVGPRClass(const TargetRegisterClass *SRC) const;
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   /// \returns An AGPR reg class with the same width as \p SRC
2545ffd83dbSDimitry Andric   const TargetRegisterClass *
2555ffd83dbSDimitry Andric   getEquivalentAGPRClass(const TargetRegisterClass *SRC) const;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   /// \returns A SGPR reg class with the same width as \p SRC
2585ffd83dbSDimitry Andric   const TargetRegisterClass *
2595ffd83dbSDimitry Andric   getEquivalentSGPRClass(const TargetRegisterClass *VRC) const;
2600b57cec5SDimitry Andric 
261fe6060f1SDimitry Andric   /// Returns a register class which is compatible with \p SuperRC, such that a
262fe6060f1SDimitry Andric   /// subregister exists with class \p SubRC with subregister index \p
263fe6060f1SDimitry Andric   /// SubIdx. If this is impossible (e.g., an unaligned subregister index within
264fe6060f1SDimitry Andric   /// a register tuple), return null.
265fe6060f1SDimitry Andric   const TargetRegisterClass *
266fe6060f1SDimitry Andric   getCompatibleSubRegClass(const TargetRegisterClass *SuperRC,
267fe6060f1SDimitry Andric                            const TargetRegisterClass *SubRC,
268fe6060f1SDimitry Andric                            unsigned SubIdx) const;
269fe6060f1SDimitry Andric 
2700b57cec5SDimitry Andric   bool shouldRewriteCopySrc(const TargetRegisterClass *DefRC,
2710b57cec5SDimitry Andric                             unsigned DefSubReg,
2720b57cec5SDimitry Andric                             const TargetRegisterClass *SrcRC,
2730b57cec5SDimitry Andric                             unsigned SrcSubReg) const override;
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   /// \returns True if operands defined with this operand type can accept
2760b57cec5SDimitry Andric   /// a literal constant (i.e. any 32-bit immediate).
277e8d8bef9SDimitry Andric   bool opCanUseLiteralConstant(unsigned OpType) const;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   /// \returns True if operands defined with this operand type can accept
2800b57cec5SDimitry Andric   /// an inline constant. i.e. An integer value in the range (-16, 64) or
2810b57cec5SDimitry Andric   /// -4.0f, -2.0f, -1.0f, -0.5f, 0.0f, 0.5f, 1.0f, 2.0f, 4.0f.
2828bcb0991SDimitry Andric   bool opCanUseInlineConstant(unsigned OpType) const;
2830b57cec5SDimitry Andric 
2845ffd83dbSDimitry Andric   MCRegister findUnusedRegister(const MachineRegisterInfo &MRI,
2850b57cec5SDimitry Andric                                 const TargetRegisterClass *RC,
2865ffd83dbSDimitry Andric                                 const MachineFunction &MF,
2875ffd83dbSDimitry Andric                                 bool ReserveHighestVGPR = false) const;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   const TargetRegisterClass *getRegClassForReg(const MachineRegisterInfo &MRI,
2905ffd83dbSDimitry Andric                                                Register Reg) const;
291bdd1243dSDimitry Andric   const TargetRegisterClass *
292bdd1243dSDimitry Andric   getRegClassForOperandReg(const MachineRegisterInfo &MRI,
293bdd1243dSDimitry Andric                            const MachineOperand &MO) const;
294bdd1243dSDimitry Andric 
2955ffd83dbSDimitry Andric   bool isVGPR(const MachineRegisterInfo &MRI, Register Reg) const;
2965ffd83dbSDimitry Andric   bool isAGPR(const MachineRegisterInfo &MRI, Register Reg) const;
2975ffd83dbSDimitry Andric   bool isVectorRegister(const MachineRegisterInfo &MRI, Register Reg) const {
2980b57cec5SDimitry Andric     return isVGPR(MRI, Reg) || isAGPR(MRI, Reg);
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
30106c3fb27SDimitry Andric   // FIXME: SGPRs are assumed to be uniform, but this is not true for i1 SGPRs
30206c3fb27SDimitry Andric   // (such as VCC) which hold a wave-wide vector of boolean values. Examining
30306c3fb27SDimitry Andric   // just the register class is not suffcient; it needs to be combined with a
30406c3fb27SDimitry Andric   // value type. The next predicate isUniformReg() does this correctly.
3055ffd83dbSDimitry Andric   bool isDivergentRegClass(const TargetRegisterClass *RC) const override {
3065ffd83dbSDimitry Andric     return !isSGPRClass(RC);
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
30906c3fb27SDimitry Andric   bool isUniformReg(const MachineRegisterInfo &MRI, const RegisterBankInfo &RBI,
31006c3fb27SDimitry Andric                     Register Reg) const override;
31106c3fb27SDimitry Andric 
3120b57cec5SDimitry Andric   ArrayRef<int16_t> getRegSplitParts(const TargetRegisterClass *RC,
3130b57cec5SDimitry Andric                                      unsigned EltSize) const;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   bool shouldCoalesce(MachineInstr *MI,
3160b57cec5SDimitry Andric                       const TargetRegisterClass *SrcRC,
3170b57cec5SDimitry Andric                       unsigned SubReg,
3180b57cec5SDimitry Andric                       const TargetRegisterClass *DstRC,
3190b57cec5SDimitry Andric                       unsigned DstSubReg,
3200b57cec5SDimitry Andric                       const TargetRegisterClass *NewRC,
3210b57cec5SDimitry Andric                       LiveIntervals &LIS) const override;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   unsigned getRegPressureLimit(const TargetRegisterClass *RC,
3240b57cec5SDimitry Andric                                MachineFunction &MF) const override;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   unsigned getRegPressureSetLimit(const MachineFunction &MF,
3270b57cec5SDimitry Andric                                   unsigned Idx) const override;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   const int *getRegUnitPressureSets(unsigned RegUnit) const override;
3300b57cec5SDimitry Andric 
3315ffd83dbSDimitry Andric   MCRegister getReturnAddressReg(const MachineFunction &MF) const;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   const TargetRegisterClass *
33481ad6265SDimitry Andric   getRegClassForSizeOnBank(unsigned Size, const RegisterBank &Bank) const;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   const TargetRegisterClass *
33781ad6265SDimitry Andric   getRegClassForTypeOnBank(LLT Ty, const RegisterBank &Bank) const {
33881ad6265SDimitry Andric     return getRegClassForSizeOnBank(Ty.getSizeInBits(), Bank);
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   const TargetRegisterClass *
3420b57cec5SDimitry Andric   getConstrainedRegClassForOperand(const MachineOperand &MO,
3430b57cec5SDimitry Andric                                  const MachineRegisterInfo &MRI) const override;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   const TargetRegisterClass *getBoolRC() const {
3468bcb0991SDimitry Andric     return isWave32 ? &AMDGPU::SReg_32RegClass
3470b57cec5SDimitry Andric                     : &AMDGPU::SReg_64RegClass;
3480b57cec5SDimitry Andric   }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   const TargetRegisterClass *getWaveMaskRegClass() const {
3510b57cec5SDimitry Andric     return isWave32 ? &AMDGPU::SReg_32_XM0_XEXECRegClass
3520b57cec5SDimitry Andric                     : &AMDGPU::SReg_64_XEXECRegClass;
3530b57cec5SDimitry Andric   }
3540b57cec5SDimitry Andric 
355fe6060f1SDimitry Andric   // Return the appropriate register class to use for 64-bit VGPRs for the
356fe6060f1SDimitry Andric   // subtarget.
357fe6060f1SDimitry Andric   const TargetRegisterClass *getVGPR64Class() const;
358fe6060f1SDimitry Andric 
3595ffd83dbSDimitry Andric   MCRegister getVCC() const;
3600b57cec5SDimitry Andric 
361753f127fSDimitry Andric   MCRegister getExec() const;
362753f127fSDimitry Andric 
3630b57cec5SDimitry Andric   const TargetRegisterClass *getRegClass(unsigned RCID) const;
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   // Find reaching register definition
3665ffd83dbSDimitry Andric   MachineInstr *findReachingDef(Register Reg, unsigned SubReg,
3670b57cec5SDimitry Andric                                 MachineInstr &Use,
3680b57cec5SDimitry Andric                                 MachineRegisterInfo &MRI,
3690b57cec5SDimitry Andric                                 LiveIntervals *LIS) const;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   const uint32_t *getAllVGPRRegMask() const;
372fe6060f1SDimitry Andric   const uint32_t *getAllAGPRRegMask() const;
373fe6060f1SDimitry Andric   const uint32_t *getAllVectorRegMask() const;
3740b57cec5SDimitry Andric   const uint32_t *getAllAllocatableSRegMask() const;
3750b57cec5SDimitry Andric 
3765ffd83dbSDimitry Andric   // \returns number of 32 bit registers covered by a \p LM
3775ffd83dbSDimitry Andric   static unsigned getNumCoveredRegs(LaneBitmask LM) {
3785ffd83dbSDimitry Andric     // The assumption is that every lo16 subreg is an even bit and every hi16
3795ffd83dbSDimitry Andric     // is an adjacent odd bit or vice versa.
3805ffd83dbSDimitry Andric     uint64_t Mask = LM.getAsInteger();
3815ffd83dbSDimitry Andric     uint64_t Even = Mask & 0xAAAAAAAAAAAAAAAAULL;
3825ffd83dbSDimitry Andric     Mask = (Even >> 1) | Mask;
3835ffd83dbSDimitry Andric     uint64_t Odd = Mask & 0x5555555555555555ULL;
384bdd1243dSDimitry Andric     return llvm::popcount(Odd);
3855ffd83dbSDimitry Andric   }
3865ffd83dbSDimitry Andric 
3875ffd83dbSDimitry Andric   // \returns a DWORD offset of a \p SubReg
3885ffd83dbSDimitry Andric   unsigned getChannelFromSubReg(unsigned SubReg) const {
3895ffd83dbSDimitry Andric     return SubReg ? (getSubRegIdxOffset(SubReg) + 31) / 32 : 0;
3905ffd83dbSDimitry Andric   }
3915ffd83dbSDimitry Andric 
3925ffd83dbSDimitry Andric   // \returns a DWORD size of a \p SubReg
3935ffd83dbSDimitry Andric   unsigned getNumChannelsFromSubReg(unsigned SubReg) const {
3945ffd83dbSDimitry Andric     return getNumCoveredRegs(getSubRegIndexLaneMask(SubReg));
3955ffd83dbSDimitry Andric   }
3965ffd83dbSDimitry Andric 
3975ffd83dbSDimitry Andric   // For a given 16 bit \p Reg \returns a 32 bit register holding it.
3985ffd83dbSDimitry Andric   // \returns \p Reg otherwise.
3995ffd83dbSDimitry Andric   MCPhysReg get32BitRegister(MCPhysReg Reg) const;
4005ffd83dbSDimitry Andric 
401fe6060f1SDimitry Andric   // Returns true if a given register class is properly aligned for
402fe6060f1SDimitry Andric   // the subtarget.
403fe6060f1SDimitry Andric   bool isProperlyAlignedRC(const TargetRegisterClass &RC) const;
404fe6060f1SDimitry Andric 
40581ad6265SDimitry Andric   // Given \p RC returns corresponding aligned register class if required
40681ad6265SDimitry Andric   // by the subtarget.
40781ad6265SDimitry Andric   const TargetRegisterClass *
40881ad6265SDimitry Andric   getProperlyAlignedRC(const TargetRegisterClass *RC) const;
40981ad6265SDimitry Andric 
4105ffd83dbSDimitry Andric   /// Return all SGPR128 which satisfy the waves per execution unit requirement
4115ffd83dbSDimitry Andric   /// of the subtarget.
4125ffd83dbSDimitry Andric   ArrayRef<MCPhysReg> getAllSGPR128(const MachineFunction &MF) const;
4135ffd83dbSDimitry Andric 
414e8d8bef9SDimitry Andric   /// Return all SGPR64 which satisfy the waves per execution unit requirement
415e8d8bef9SDimitry Andric   /// of the subtarget.
416e8d8bef9SDimitry Andric   ArrayRef<MCPhysReg> getAllSGPR64(const MachineFunction &MF) const;
417e8d8bef9SDimitry Andric 
4185ffd83dbSDimitry Andric   /// Return all SGPR32 which satisfy the waves per execution unit requirement
4195ffd83dbSDimitry Andric   /// of the subtarget.
4205ffd83dbSDimitry Andric   ArrayRef<MCPhysReg> getAllSGPR32(const MachineFunction &MF) const;
4215ffd83dbSDimitry Andric 
422fe6060f1SDimitry Andric   // Insert spill or restore instructions.
423fe6060f1SDimitry Andric   // When lowering spill pseudos, the RegScavenger should be set.
424fe6060f1SDimitry Andric   // For creating spill instructions during frame lowering, where no scavenger
425*5f757f3fSDimitry Andric   // is available, LiveUnits can be used.
426fe6060f1SDimitry Andric   void buildSpillLoadStore(MachineBasicBlock &MBB,
427349cc55cSDimitry Andric                            MachineBasicBlock::iterator MI, const DebugLoc &DL,
428349cc55cSDimitry Andric                            unsigned LoadStoreOp, int Index, Register ValueReg,
429349cc55cSDimitry Andric                            bool ValueIsKill, MCRegister ScratchOffsetReg,
430349cc55cSDimitry Andric                            int64_t InstrOffset, MachineMemOperand *MMO,
431349cc55cSDimitry Andric                            RegScavenger *RS,
432*5f757f3fSDimitry Andric                            LiveRegUnits *LiveUnits = nullptr) const;
43306c3fb27SDimitry Andric 
43406c3fb27SDimitry Andric   // Return alignment in register file of first register in a register tuple.
43506c3fb27SDimitry Andric   unsigned getRegClassAlignmentNumBits(const TargetRegisterClass *RC) const {
43606c3fb27SDimitry Andric     return (RC->TSFlags & SIRCFlags::RegTupleAlignUnitsMask) * 32;
43706c3fb27SDimitry Andric   }
43806c3fb27SDimitry Andric 
43906c3fb27SDimitry Andric   // Check if register class RC has required alignment.
44006c3fb27SDimitry Andric   bool isRegClassAligned(const TargetRegisterClass *RC,
44106c3fb27SDimitry Andric                          unsigned AlignNumBits) const {
44206c3fb27SDimitry Andric     assert(AlignNumBits != 0);
44306c3fb27SDimitry Andric     unsigned RCAlign = getRegClassAlignmentNumBits(RC);
44406c3fb27SDimitry Andric     return RCAlign == AlignNumBits ||
44506c3fb27SDimitry Andric            (RCAlign > AlignNumBits && (RCAlign % AlignNumBits) == 0);
44606c3fb27SDimitry Andric   }
44706c3fb27SDimitry Andric 
44806c3fb27SDimitry Andric   // Return alignment of a SubReg relative to start of a register in RC class.
44906c3fb27SDimitry Andric   // No check if the subreg is supported by the current RC is made.
45006c3fb27SDimitry Andric   unsigned getSubRegAlignmentNumBits(const TargetRegisterClass *RC,
45106c3fb27SDimitry Andric                                      unsigned SubReg) const;
4520b57cec5SDimitry Andric };
4530b57cec5SDimitry Andric 
454*5f757f3fSDimitry Andric namespace AMDGPU {
455*5f757f3fSDimitry Andric /// Get the size in bits of a register from the register class \p RC.
456*5f757f3fSDimitry Andric unsigned getRegBitWidth(const TargetRegisterClass &RC);
457*5f757f3fSDimitry Andric } // namespace AMDGPU
458*5f757f3fSDimitry Andric 
4590b57cec5SDimitry Andric } // End namespace llvm
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric #endif
462