1 //===- SIInstrInfo.h - SI Instruction Info Interface ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 /// \file
10 /// Interface definition for SIInstrInfo.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
15 #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
16 
17 #include "AMDGPUMIRFormatter.h"
18 #include "SIRegisterInfo.h"
19 #include "Utils/AMDGPUBaseInfo.h"
20 #include "llvm/ADT/SetVector.h"
21 #include "llvm/CodeGen/TargetInstrInfo.h"
22 #include "llvm/CodeGen/TargetSchedule.h"
23 
24 #define GET_INSTRINFO_HEADER
25 #include "AMDGPUGenInstrInfo.inc"
26 
27 namespace llvm {
28 
29 class APInt;
30 class GCNSubtarget;
31 class LiveVariables;
32 class MachineDominatorTree;
33 class MachineRegisterInfo;
34 class RegScavenger;
35 class TargetRegisterClass;
36 class ScheduleHazardRecognizer;
37 
38 class SIInstrInfo final : public AMDGPUGenInstrInfo {
39 private:
40   const SIRegisterInfo RI;
41   const GCNSubtarget &ST;
42   TargetSchedModel SchedModel;
43   mutable std::unique_ptr<AMDGPUMIRFormatter> Formatter;
44 
45   // The inverse predicate should have the negative value.
46   enum BranchPredicate {
47     INVALID_BR = 0,
48     SCC_TRUE = 1,
49     SCC_FALSE = -1,
50     VCCNZ = 2,
51     VCCZ = -2,
52     EXECNZ = -3,
53     EXECZ = 3
54   };
55 
56   using SetVectorType = SmallSetVector<MachineInstr *, 32>;
57 
58   static unsigned getBranchOpcode(BranchPredicate Cond);
59   static BranchPredicate getBranchPredicate(unsigned Opcode);
60 
61 public:
62   unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
63                               MachineRegisterInfo &MRI,
64                               MachineOperand &SuperReg,
65                               const TargetRegisterClass *SuperRC,
66                               unsigned SubIdx,
67                               const TargetRegisterClass *SubRC) const;
68   MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
69                                          MachineRegisterInfo &MRI,
70                                          MachineOperand &SuperReg,
71                                          const TargetRegisterClass *SuperRC,
72                                          unsigned SubIdx,
73                                          const TargetRegisterClass *SubRC) const;
74 private:
75   void swapOperands(MachineInstr &Inst) const;
76 
77   std::pair<bool, MachineBasicBlock *>
78   moveScalarAddSub(SetVectorType &Worklist, MachineInstr &Inst,
79                    MachineDominatorTree *MDT = nullptr) const;
80 
81   void lowerSelect(SetVectorType &Worklist, MachineInstr &Inst,
82                    MachineDominatorTree *MDT = nullptr) const;
83 
84   void lowerScalarAbs(SetVectorType &Worklist,
85                       MachineInstr &Inst) const;
86 
87   void lowerScalarXnor(SetVectorType &Worklist,
88                        MachineInstr &Inst) const;
89 
90   void splitScalarNotBinop(SetVectorType &Worklist,
91                            MachineInstr &Inst,
92                            unsigned Opcode) const;
93 
94   void splitScalarBinOpN2(SetVectorType &Worklist,
95                           MachineInstr &Inst,
96                           unsigned Opcode) const;
97 
98   void splitScalar64BitUnaryOp(SetVectorType &Worklist,
99                                MachineInstr &Inst, unsigned Opcode,
100                                bool Swap = false) const;
101 
102   void splitScalar64BitAddSub(SetVectorType &Worklist, MachineInstr &Inst,
103                               MachineDominatorTree *MDT = nullptr) const;
104 
105   void splitScalar64BitBinaryOp(SetVectorType &Worklist, MachineInstr &Inst,
106                                 unsigned Opcode,
107                                 MachineDominatorTree *MDT = nullptr) const;
108 
109   void splitScalar64BitXnor(SetVectorType &Worklist, MachineInstr &Inst,
110                                 MachineDominatorTree *MDT = nullptr) const;
111 
112   void splitScalar64BitBCNT(SetVectorType &Worklist,
113                             MachineInstr &Inst) const;
114   void splitScalar64BitBFE(SetVectorType &Worklist,
115                            MachineInstr &Inst) const;
116   void movePackToVALU(SetVectorType &Worklist,
117                       MachineRegisterInfo &MRI,
118                       MachineInstr &Inst) const;
119 
120   void addUsersToMoveToVALUWorklist(Register Reg, MachineRegisterInfo &MRI,
121                                     SetVectorType &Worklist) const;
122 
123   void addSCCDefUsersToVALUWorklist(MachineOperand &Op,
124                                     MachineInstr &SCCDefInst,
125                                     SetVectorType &Worklist) const;
126   void addSCCDefsToVALUWorklist(MachineOperand &Op,
127                                 SetVectorType &Worklist) const;
128 
129   const TargetRegisterClass *
130   getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
131 
132   bool checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
133                                     const MachineInstr &MIb) const;
134 
135   Register findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
136 
137 protected:
138   bool swapSourceModifiers(MachineInstr &MI,
139                            MachineOperand &Src0, unsigned Src0OpName,
140                            MachineOperand &Src1, unsigned Src1OpName) const;
141 
142   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
143                                        unsigned OpIdx0,
144                                        unsigned OpIdx1) const override;
145 
146 public:
147   enum TargetOperandFlags {
148     MO_MASK = 0xf,
149 
150     MO_NONE = 0,
151     // MO_GOTPCREL -> symbol@GOTPCREL -> R_AMDGPU_GOTPCREL.
152     MO_GOTPCREL = 1,
153     // MO_GOTPCREL32_LO -> symbol@gotpcrel32@lo -> R_AMDGPU_GOTPCREL32_LO.
154     MO_GOTPCREL32 = 2,
155     MO_GOTPCREL32_LO = 2,
156     // MO_GOTPCREL32_HI -> symbol@gotpcrel32@hi -> R_AMDGPU_GOTPCREL32_HI.
157     MO_GOTPCREL32_HI = 3,
158     // MO_REL32_LO -> symbol@rel32@lo -> R_AMDGPU_REL32_LO.
159     MO_REL32 = 4,
160     MO_REL32_LO = 4,
161     // MO_REL32_HI -> symbol@rel32@hi -> R_AMDGPU_REL32_HI.
162     MO_REL32_HI = 5,
163 
164     MO_LONG_BRANCH_FORWARD = 6,
165     MO_LONG_BRANCH_BACKWARD = 7,
166 
167     MO_ABS32_LO = 8,
168     MO_ABS32_HI = 9,
169   };
170 
171   explicit SIInstrInfo(const GCNSubtarget &ST);
172 
getRegisterInfo()173   const SIRegisterInfo &getRegisterInfo() const {
174     return RI;
175   }
176 
getSubtarget()177   const GCNSubtarget &getSubtarget() const {
178     return ST;
179   }
180 
181   bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
182                                          AAResults *AA) const override;
183 
184   bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
185                                int64_t &Offset1,
186                                int64_t &Offset2) const override;
187 
188   bool getMemOperandsWithOffsetWidth(
189       const MachineInstr &LdSt,
190       SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset,
191       bool &OffsetIsScalable, unsigned &Width,
192       const TargetRegisterInfo *TRI) const final;
193 
194   bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
195                            ArrayRef<const MachineOperand *> BaseOps2,
196                            unsigned NumLoads, unsigned NumBytes) const override;
197 
198   bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0,
199                                int64_t Offset1, unsigned NumLoads) const override;
200 
201   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
202                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
203                    bool KillSrc) const override;
204 
205   void materializeImmediate(MachineBasicBlock &MBB,
206                             MachineBasicBlock::iterator MI,
207                             const DebugLoc &DL,
208                             unsigned DestReg,
209                             int64_t Value) const;
210 
211   const TargetRegisterClass *getPreferredSelectRegClass(
212                                unsigned Size) const;
213 
214   Register insertNE(MachineBasicBlock *MBB,
215                     MachineBasicBlock::iterator I, const DebugLoc &DL,
216                     Register SrcReg, int Value) const;
217 
218   Register insertEQ(MachineBasicBlock *MBB,
219                     MachineBasicBlock::iterator I, const DebugLoc &DL,
220                     Register SrcReg, int Value)  const;
221 
222   void storeRegToStackSlot(MachineBasicBlock &MBB,
223                            MachineBasicBlock::iterator MI, Register SrcReg,
224                            bool isKill, int FrameIndex,
225                            const TargetRegisterClass *RC,
226                            const TargetRegisterInfo *TRI) const override;
227 
228   void loadRegFromStackSlot(MachineBasicBlock &MBB,
229                             MachineBasicBlock::iterator MI, Register DestReg,
230                             int FrameIndex, const TargetRegisterClass *RC,
231                             const TargetRegisterInfo *TRI) const override;
232 
233   bool expandPostRAPseudo(MachineInstr &MI) const override;
234 
235   // Splits a V_MOV_B64_DPP_PSEUDO opcode into a pair of v_mov_b32_dpp
236   // instructions. Returns a pair of generated instructions.
237   // Can split either post-RA with physical registers or pre-RA with
238   // virtual registers. In latter case IR needs to be in SSA form and
239   // and a REG_SEQUENCE is produced to define original register.
240   std::pair<MachineInstr*, MachineInstr*>
241   expandMovDPP64(MachineInstr &MI) const;
242 
243   // Returns an opcode that can be used to move a value to a \p DstRC
244   // register.  If there is no hardware instruction that can store to \p
245   // DstRC, then AMDGPU::COPY is returned.
246   unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
247 
248   const MCInstrDesc &getIndirectRegWriteMovRelPseudo(unsigned VecSize,
249                                                      unsigned EltSize,
250                                                      bool IsSGPR) const;
251 
252   const MCInstrDesc &getIndirectGPRIDXPseudo(unsigned VecSize,
253                                              bool IsIndirectSrc) const;
254   LLVM_READONLY
255   int commuteOpcode(unsigned Opc) const;
256 
257   LLVM_READONLY
commuteOpcode(const MachineInstr & MI)258   inline int commuteOpcode(const MachineInstr &MI) const {
259     return commuteOpcode(MI.getOpcode());
260   }
261 
262   bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
263                              unsigned &SrcOpIdx2) const override;
264 
265   bool findCommutedOpIndices(MCInstrDesc Desc, unsigned & SrcOpIdx0,
266    unsigned & SrcOpIdx1) const;
267 
268   bool isBranchOffsetInRange(unsigned BranchOpc,
269                              int64_t BrOffset) const override;
270 
271   MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
272 
273   unsigned insertIndirectBranch(MachineBasicBlock &MBB,
274                                 MachineBasicBlock &NewDestBB,
275                                 const DebugLoc &DL,
276                                 int64_t BrOffset,
277                                 RegScavenger *RS = nullptr) const override;
278 
279   bool analyzeBranchImpl(MachineBasicBlock &MBB,
280                          MachineBasicBlock::iterator I,
281                          MachineBasicBlock *&TBB,
282                          MachineBasicBlock *&FBB,
283                          SmallVectorImpl<MachineOperand> &Cond,
284                          bool AllowModify) const;
285 
286   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
287                      MachineBasicBlock *&FBB,
288                      SmallVectorImpl<MachineOperand> &Cond,
289                      bool AllowModify = false) const override;
290 
291   unsigned removeBranch(MachineBasicBlock &MBB,
292                         int *BytesRemoved = nullptr) const override;
293 
294   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
295                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
296                         const DebugLoc &DL,
297                         int *BytesAdded = nullptr) const override;
298 
299   bool reverseBranchCondition(
300     SmallVectorImpl<MachineOperand> &Cond) const override;
301 
302   bool canInsertSelect(const MachineBasicBlock &MBB,
303                        ArrayRef<MachineOperand> Cond, Register DstReg,
304                        Register TrueReg, Register FalseReg, int &CondCycles,
305                        int &TrueCycles, int &FalseCycles) const override;
306 
307   void insertSelect(MachineBasicBlock &MBB,
308                     MachineBasicBlock::iterator I, const DebugLoc &DL,
309                     Register DstReg, ArrayRef<MachineOperand> Cond,
310                     Register TrueReg, Register FalseReg) const override;
311 
312   void insertVectorSelect(MachineBasicBlock &MBB,
313                           MachineBasicBlock::iterator I, const DebugLoc &DL,
314                           Register DstReg, ArrayRef<MachineOperand> Cond,
315                           Register TrueReg, Register FalseReg) const;
316 
317   unsigned getAddressSpaceForPseudoSourceKind(
318              unsigned Kind) const override;
319 
320   bool
321   areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
322                                   const MachineInstr &MIb) const override;
323 
324   bool isFoldableCopy(const MachineInstr &MI) const;
325 
326   bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,
327                      MachineRegisterInfo *MRI) const final;
328 
getMachineCSELookAheadLimit()329   unsigned getMachineCSELookAheadLimit() const override { return 500; }
330 
331   MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
332                                       MachineInstr &MI,
333                                       LiveVariables *LV) const override;
334 
335   bool isSchedulingBoundary(const MachineInstr &MI,
336                             const MachineBasicBlock *MBB,
337                             const MachineFunction &MF) const override;
338 
isSALU(const MachineInstr & MI)339   static bool isSALU(const MachineInstr &MI) {
340     return MI.getDesc().TSFlags & SIInstrFlags::SALU;
341   }
342 
isSALU(uint16_t Opcode)343   bool isSALU(uint16_t Opcode) const {
344     return get(Opcode).TSFlags & SIInstrFlags::SALU;
345   }
346 
isVALU(const MachineInstr & MI)347   static bool isVALU(const MachineInstr &MI) {
348     return MI.getDesc().TSFlags & SIInstrFlags::VALU;
349   }
350 
isVALU(uint16_t Opcode)351   bool isVALU(uint16_t Opcode) const {
352     return get(Opcode).TSFlags & SIInstrFlags::VALU;
353   }
354 
isVMEM(const MachineInstr & MI)355   static bool isVMEM(const MachineInstr &MI) {
356     return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
357   }
358 
isVMEM(uint16_t Opcode)359   bool isVMEM(uint16_t Opcode) const {
360     return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
361   }
362 
isSOP1(const MachineInstr & MI)363   static bool isSOP1(const MachineInstr &MI) {
364     return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
365   }
366 
isSOP1(uint16_t Opcode)367   bool isSOP1(uint16_t Opcode) const {
368     return get(Opcode).TSFlags & SIInstrFlags::SOP1;
369   }
370 
isSOP2(const MachineInstr & MI)371   static bool isSOP2(const MachineInstr &MI) {
372     return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
373   }
374 
isSOP2(uint16_t Opcode)375   bool isSOP2(uint16_t Opcode) const {
376     return get(Opcode).TSFlags & SIInstrFlags::SOP2;
377   }
378 
isSOPC(const MachineInstr & MI)379   static bool isSOPC(const MachineInstr &MI) {
380     return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
381   }
382 
isSOPC(uint16_t Opcode)383   bool isSOPC(uint16_t Opcode) const {
384     return get(Opcode).TSFlags & SIInstrFlags::SOPC;
385   }
386 
isSOPK(const MachineInstr & MI)387   static bool isSOPK(const MachineInstr &MI) {
388     return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
389   }
390 
isSOPK(uint16_t Opcode)391   bool isSOPK(uint16_t Opcode) const {
392     return get(Opcode).TSFlags & SIInstrFlags::SOPK;
393   }
394 
isSOPP(const MachineInstr & MI)395   static bool isSOPP(const MachineInstr &MI) {
396     return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
397   }
398 
isSOPP(uint16_t Opcode)399   bool isSOPP(uint16_t Opcode) const {
400     return get(Opcode).TSFlags & SIInstrFlags::SOPP;
401   }
402 
isPacked(const MachineInstr & MI)403   static bool isPacked(const MachineInstr &MI) {
404     return MI.getDesc().TSFlags & SIInstrFlags::IsPacked;
405   }
406 
isPacked(uint16_t Opcode)407   bool isPacked(uint16_t Opcode) const {
408     return get(Opcode).TSFlags & SIInstrFlags::IsPacked;
409   }
410 
isVOP1(const MachineInstr & MI)411   static bool isVOP1(const MachineInstr &MI) {
412     return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
413   }
414 
isVOP1(uint16_t Opcode)415   bool isVOP1(uint16_t Opcode) const {
416     return get(Opcode).TSFlags & SIInstrFlags::VOP1;
417   }
418 
isVOP2(const MachineInstr & MI)419   static bool isVOP2(const MachineInstr &MI) {
420     return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
421   }
422 
isVOP2(uint16_t Opcode)423   bool isVOP2(uint16_t Opcode) const {
424     return get(Opcode).TSFlags & SIInstrFlags::VOP2;
425   }
426 
isVOP3(const MachineInstr & MI)427   static bool isVOP3(const MachineInstr &MI) {
428     return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
429   }
430 
isVOP3(uint16_t Opcode)431   bool isVOP3(uint16_t Opcode) const {
432     return get(Opcode).TSFlags & SIInstrFlags::VOP3;
433   }
434 
isSDWA(const MachineInstr & MI)435   static bool isSDWA(const MachineInstr &MI) {
436     return MI.getDesc().TSFlags & SIInstrFlags::SDWA;
437   }
438 
isSDWA(uint16_t Opcode)439   bool isSDWA(uint16_t Opcode) const {
440     return get(Opcode).TSFlags & SIInstrFlags::SDWA;
441   }
442 
isVOPC(const MachineInstr & MI)443   static bool isVOPC(const MachineInstr &MI) {
444     return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
445   }
446 
isVOPC(uint16_t Opcode)447   bool isVOPC(uint16_t Opcode) const {
448     return get(Opcode).TSFlags & SIInstrFlags::VOPC;
449   }
450 
isMUBUF(const MachineInstr & MI)451   static bool isMUBUF(const MachineInstr &MI) {
452     return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
453   }
454 
isMUBUF(uint16_t Opcode)455   bool isMUBUF(uint16_t Opcode) const {
456     return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
457   }
458 
isMTBUF(const MachineInstr & MI)459   static bool isMTBUF(const MachineInstr &MI) {
460     return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
461   }
462 
isMTBUF(uint16_t Opcode)463   bool isMTBUF(uint16_t Opcode) const {
464     return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
465   }
466 
isSMRD(const MachineInstr & MI)467   static bool isSMRD(const MachineInstr &MI) {
468     return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
469   }
470 
isSMRD(uint16_t Opcode)471   bool isSMRD(uint16_t Opcode) const {
472     return get(Opcode).TSFlags & SIInstrFlags::SMRD;
473   }
474 
475   bool isBufferSMRD(const MachineInstr &MI) const;
476 
isDS(const MachineInstr & MI)477   static bool isDS(const MachineInstr &MI) {
478     return MI.getDesc().TSFlags & SIInstrFlags::DS;
479   }
480 
isDS(uint16_t Opcode)481   bool isDS(uint16_t Opcode) const {
482     return get(Opcode).TSFlags & SIInstrFlags::DS;
483   }
484 
485   bool isAlwaysGDS(uint16_t Opcode) const;
486 
isMIMG(const MachineInstr & MI)487   static bool isMIMG(const MachineInstr &MI) {
488     return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
489   }
490 
isMIMG(uint16_t Opcode)491   bool isMIMG(uint16_t Opcode) const {
492     return get(Opcode).TSFlags & SIInstrFlags::MIMG;
493   }
494 
isGather4(const MachineInstr & MI)495   static bool isGather4(const MachineInstr &MI) {
496     return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
497   }
498 
isGather4(uint16_t Opcode)499   bool isGather4(uint16_t Opcode) const {
500     return get(Opcode).TSFlags & SIInstrFlags::Gather4;
501   }
502 
isFLAT(const MachineInstr & MI)503   static bool isFLAT(const MachineInstr &MI) {
504     return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
505   }
506 
507   // Is a FLAT encoded instruction which accesses a specific segment,
508   // i.e. global_* or scratch_*.
isSegmentSpecificFLAT(const MachineInstr & MI)509   static bool isSegmentSpecificFLAT(const MachineInstr &MI) {
510     auto Flags = MI.getDesc().TSFlags;
511     return Flags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch);
512   }
513 
isSegmentSpecificFLAT(uint16_t Opcode)514   bool isSegmentSpecificFLAT(uint16_t Opcode) const {
515     auto Flags = get(Opcode).TSFlags;
516     return Flags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch);
517   }
518 
isFLATGlobal(const MachineInstr & MI)519   static bool isFLATGlobal(const MachineInstr &MI) {
520     return MI.getDesc().TSFlags & SIInstrFlags::FlatGlobal;
521   }
522 
isFLATGlobal(uint16_t Opcode)523   bool isFLATGlobal(uint16_t Opcode) const {
524     return get(Opcode).TSFlags & SIInstrFlags::FlatGlobal;
525   }
526 
isFLATScratch(const MachineInstr & MI)527   static bool isFLATScratch(const MachineInstr &MI) {
528     return MI.getDesc().TSFlags & SIInstrFlags::FlatScratch;
529   }
530 
isFLATScratch(uint16_t Opcode)531   bool isFLATScratch(uint16_t Opcode) const {
532     return get(Opcode).TSFlags & SIInstrFlags::FlatScratch;
533   }
534 
535   // Any FLAT encoded instruction, including global_* and scratch_*.
isFLAT(uint16_t Opcode)536   bool isFLAT(uint16_t Opcode) const {
537     return get(Opcode).TSFlags & SIInstrFlags::FLAT;
538   }
539 
isEXP(const MachineInstr & MI)540   static bool isEXP(const MachineInstr &MI) {
541     return MI.getDesc().TSFlags & SIInstrFlags::EXP;
542   }
543 
isEXP(uint16_t Opcode)544   bool isEXP(uint16_t Opcode) const {
545     return get(Opcode).TSFlags & SIInstrFlags::EXP;
546   }
547 
isAtomicNoRet(const MachineInstr & MI)548   static bool isAtomicNoRet(const MachineInstr &MI) {
549     return MI.getDesc().TSFlags & SIInstrFlags::IsAtomicNoRet;
550   }
551 
isAtomicNoRet(uint16_t Opcode)552   bool isAtomicNoRet(uint16_t Opcode) const {
553     return get(Opcode).TSFlags & SIInstrFlags::IsAtomicNoRet;
554   }
555 
isAtomicRet(const MachineInstr & MI)556   static bool isAtomicRet(const MachineInstr &MI) {
557     return MI.getDesc().TSFlags & SIInstrFlags::IsAtomicRet;
558   }
559 
isAtomicRet(uint16_t Opcode)560   bool isAtomicRet(uint16_t Opcode) const {
561     return get(Opcode).TSFlags & SIInstrFlags::IsAtomicRet;
562   }
563 
isAtomic(const MachineInstr & MI)564   static bool isAtomic(const MachineInstr &MI) {
565     return MI.getDesc().TSFlags & (SIInstrFlags::IsAtomicRet |
566                                    SIInstrFlags::IsAtomicNoRet);
567   }
568 
isAtomic(uint16_t Opcode)569   bool isAtomic(uint16_t Opcode) const {
570     return get(Opcode).TSFlags & (SIInstrFlags::IsAtomicRet |
571                                   SIInstrFlags::IsAtomicNoRet);
572   }
573 
isWQM(const MachineInstr & MI)574   static bool isWQM(const MachineInstr &MI) {
575     return MI.getDesc().TSFlags & SIInstrFlags::WQM;
576   }
577 
isWQM(uint16_t Opcode)578   bool isWQM(uint16_t Opcode) const {
579     return get(Opcode).TSFlags & SIInstrFlags::WQM;
580   }
581 
isDisableWQM(const MachineInstr & MI)582   static bool isDisableWQM(const MachineInstr &MI) {
583     return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM;
584   }
585 
isDisableWQM(uint16_t Opcode)586   bool isDisableWQM(uint16_t Opcode) const {
587     return get(Opcode).TSFlags & SIInstrFlags::DisableWQM;
588   }
589 
isVGPRSpill(const MachineInstr & MI)590   static bool isVGPRSpill(const MachineInstr &MI) {
591     return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
592   }
593 
isVGPRSpill(uint16_t Opcode)594   bool isVGPRSpill(uint16_t Opcode) const {
595     return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
596   }
597 
isSGPRSpill(const MachineInstr & MI)598   static bool isSGPRSpill(const MachineInstr &MI) {
599     return MI.getDesc().TSFlags & SIInstrFlags::SGPRSpill;
600   }
601 
isSGPRSpill(uint16_t Opcode)602   bool isSGPRSpill(uint16_t Opcode) const {
603     return get(Opcode).TSFlags & SIInstrFlags::SGPRSpill;
604   }
605 
isDPP(const MachineInstr & MI)606   static bool isDPP(const MachineInstr &MI) {
607     return MI.getDesc().TSFlags & SIInstrFlags::DPP;
608   }
609 
isDPP(uint16_t Opcode)610   bool isDPP(uint16_t Opcode) const {
611     return get(Opcode).TSFlags & SIInstrFlags::DPP;
612   }
613 
isTRANS(const MachineInstr & MI)614   static bool isTRANS(const MachineInstr &MI) {
615     return MI.getDesc().TSFlags & SIInstrFlags::TRANS;
616   }
617 
isTRANS(uint16_t Opcode)618   bool isTRANS(uint16_t Opcode) const {
619     return get(Opcode).TSFlags & SIInstrFlags::TRANS;
620   }
621 
isVOP3P(const MachineInstr & MI)622   static bool isVOP3P(const MachineInstr &MI) {
623     return MI.getDesc().TSFlags & SIInstrFlags::VOP3P;
624   }
625 
isVOP3P(uint16_t Opcode)626   bool isVOP3P(uint16_t Opcode) const {
627     return get(Opcode).TSFlags & SIInstrFlags::VOP3P;
628   }
629 
isVINTRP(const MachineInstr & MI)630   static bool isVINTRP(const MachineInstr &MI) {
631     return MI.getDesc().TSFlags & SIInstrFlags::VINTRP;
632   }
633 
isVINTRP(uint16_t Opcode)634   bool isVINTRP(uint16_t Opcode) const {
635     return get(Opcode).TSFlags & SIInstrFlags::VINTRP;
636   }
637 
isMAI(const MachineInstr & MI)638   static bool isMAI(const MachineInstr &MI) {
639     return MI.getDesc().TSFlags & SIInstrFlags::IsMAI;
640   }
641 
isMAI(uint16_t Opcode)642   bool isMAI(uint16_t Opcode) const {
643     return get(Opcode).TSFlags & SIInstrFlags::IsMAI;
644   }
645 
isDOT(const MachineInstr & MI)646   static bool isDOT(const MachineInstr &MI) {
647     return MI.getDesc().TSFlags & SIInstrFlags::IsDOT;
648   }
649 
isDOT(uint16_t Opcode)650   bool isDOT(uint16_t Opcode) const {
651     return get(Opcode).TSFlags & SIInstrFlags::IsDOT;
652   }
653 
isScalarUnit(const MachineInstr & MI)654   static bool isScalarUnit(const MachineInstr &MI) {
655     return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
656   }
657 
usesVM_CNT(const MachineInstr & MI)658   static bool usesVM_CNT(const MachineInstr &MI) {
659     return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
660   }
661 
usesLGKM_CNT(const MachineInstr & MI)662   static bool usesLGKM_CNT(const MachineInstr &MI) {
663     return MI.getDesc().TSFlags & SIInstrFlags::LGKM_CNT;
664   }
665 
sopkIsZext(const MachineInstr & MI)666   static bool sopkIsZext(const MachineInstr &MI) {
667     return MI.getDesc().TSFlags & SIInstrFlags::SOPK_ZEXT;
668   }
669 
sopkIsZext(uint16_t Opcode)670   bool sopkIsZext(uint16_t Opcode) const {
671     return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT;
672   }
673 
674   /// \returns true if this is an s_store_dword* instruction. This is more
675   /// specific than than isSMEM && mayStore.
isScalarStore(const MachineInstr & MI)676   static bool isScalarStore(const MachineInstr &MI) {
677     return MI.getDesc().TSFlags & SIInstrFlags::SCALAR_STORE;
678   }
679 
isScalarStore(uint16_t Opcode)680   bool isScalarStore(uint16_t Opcode) const {
681     return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE;
682   }
683 
isFixedSize(const MachineInstr & MI)684   static bool isFixedSize(const MachineInstr &MI) {
685     return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE;
686   }
687 
isFixedSize(uint16_t Opcode)688   bool isFixedSize(uint16_t Opcode) const {
689     return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE;
690   }
691 
hasFPClamp(const MachineInstr & MI)692   static bool hasFPClamp(const MachineInstr &MI) {
693     return MI.getDesc().TSFlags & SIInstrFlags::FPClamp;
694   }
695 
hasFPClamp(uint16_t Opcode)696   bool hasFPClamp(uint16_t Opcode) const {
697     return get(Opcode).TSFlags & SIInstrFlags::FPClamp;
698   }
699 
hasIntClamp(const MachineInstr & MI)700   static bool hasIntClamp(const MachineInstr &MI) {
701     return MI.getDesc().TSFlags & SIInstrFlags::IntClamp;
702   }
703 
getClampMask(const MachineInstr & MI)704   uint64_t getClampMask(const MachineInstr &MI) const {
705     const uint64_t ClampFlags = SIInstrFlags::FPClamp |
706                                 SIInstrFlags::IntClamp |
707                                 SIInstrFlags::ClampLo |
708                                 SIInstrFlags::ClampHi;
709       return MI.getDesc().TSFlags & ClampFlags;
710   }
711 
usesFPDPRounding(const MachineInstr & MI)712   static bool usesFPDPRounding(const MachineInstr &MI) {
713     return MI.getDesc().TSFlags & SIInstrFlags::FPDPRounding;
714   }
715 
usesFPDPRounding(uint16_t Opcode)716   bool usesFPDPRounding(uint16_t Opcode) const {
717     return get(Opcode).TSFlags & SIInstrFlags::FPDPRounding;
718   }
719 
isFPAtomic(const MachineInstr & MI)720   static bool isFPAtomic(const MachineInstr &MI) {
721     return MI.getDesc().TSFlags & SIInstrFlags::FPAtomic;
722   }
723 
isFPAtomic(uint16_t Opcode)724   bool isFPAtomic(uint16_t Opcode) const {
725     return get(Opcode).TSFlags & SIInstrFlags::FPAtomic;
726   }
727 
isVGPRCopy(const MachineInstr & MI)728   bool isVGPRCopy(const MachineInstr &MI) const {
729     assert(MI.isCopy());
730     Register Dest = MI.getOperand(0).getReg();
731     const MachineFunction &MF = *MI.getParent()->getParent();
732     const MachineRegisterInfo &MRI = MF.getRegInfo();
733     return !RI.isSGPRReg(MRI, Dest);
734   }
735 
hasVGPRUses(const MachineInstr & MI)736   bool hasVGPRUses(const MachineInstr &MI) const {
737     const MachineFunction &MF = *MI.getParent()->getParent();
738     const MachineRegisterInfo &MRI = MF.getRegInfo();
739     return llvm::any_of(MI.explicit_uses(),
740                         [&MRI, this](const MachineOperand &MO) {
741       return MO.isReg() && RI.isVGPR(MRI, MO.getReg());});
742   }
743 
744   /// Return true if the instruction modifies the mode register.q
745   static bool modifiesModeRegister(const MachineInstr &MI);
746 
747   /// Whether we must prevent this instruction from executing with EXEC = 0.
748   bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const;
749 
750   /// Returns true if the instruction could potentially depend on the value of
751   /// exec. If false, exec dependencies may safely be ignored.
752   bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const;
753 
754   bool isInlineConstant(const APInt &Imm) const;
755 
isInlineConstant(const APFloat & Imm)756   bool isInlineConstant(const APFloat &Imm) const {
757     return isInlineConstant(Imm.bitcastToAPInt());
758   }
759 
760   bool isInlineConstant(const MachineOperand &MO, uint8_t OperandType) const;
761 
isInlineConstant(const MachineOperand & MO,const MCOperandInfo & OpInfo)762   bool isInlineConstant(const MachineOperand &MO,
763                         const MCOperandInfo &OpInfo) const {
764     return isInlineConstant(MO, OpInfo.OperandType);
765   }
766 
767   /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would
768   /// be an inline immediate.
isInlineConstant(const MachineInstr & MI,const MachineOperand & UseMO,const MachineOperand & DefMO)769   bool isInlineConstant(const MachineInstr &MI,
770                         const MachineOperand &UseMO,
771                         const MachineOperand &DefMO) const {
772     assert(UseMO.getParent() == &MI);
773     int OpIdx = MI.getOperandNo(&UseMO);
774     if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) {
775       return false;
776     }
777 
778     return isInlineConstant(DefMO, MI.getDesc().OpInfo[OpIdx]);
779   }
780 
781   /// \p returns true if the operand \p OpIdx in \p MI is a valid inline
782   /// immediate.
isInlineConstant(const MachineInstr & MI,unsigned OpIdx)783   bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx) const {
784     const MachineOperand &MO = MI.getOperand(OpIdx);
785     return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
786   }
787 
isInlineConstant(const MachineInstr & MI,unsigned OpIdx,const MachineOperand & MO)788   bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx,
789                         const MachineOperand &MO) const {
790     if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands)
791       return false;
792 
793     if (MI.isCopy()) {
794       unsigned Size = getOpSize(MI, OpIdx);
795       assert(Size == 8 || Size == 4);
796 
797       uint8_t OpType = (Size == 8) ?
798         AMDGPU::OPERAND_REG_IMM_INT64 : AMDGPU::OPERAND_REG_IMM_INT32;
799       return isInlineConstant(MO, OpType);
800     }
801 
802     return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
803   }
804 
isInlineConstant(const MachineOperand & MO)805   bool isInlineConstant(const MachineOperand &MO) const {
806     const MachineInstr *Parent = MO.getParent();
807     return isInlineConstant(*Parent, Parent->getOperandNo(&MO));
808   }
809 
isLiteralConstant(const MachineOperand & MO,const MCOperandInfo & OpInfo)810   bool isLiteralConstant(const MachineOperand &MO,
811                          const MCOperandInfo &OpInfo) const {
812     return MO.isImm() && !isInlineConstant(MO, OpInfo.OperandType);
813   }
814 
isLiteralConstant(const MachineInstr & MI,int OpIdx)815   bool isLiteralConstant(const MachineInstr &MI, int OpIdx) const {
816     const MachineOperand &MO = MI.getOperand(OpIdx);
817     return MO.isImm() && !isInlineConstant(MI, OpIdx);
818   }
819 
820   // Returns true if this operand could potentially require a 32-bit literal
821   // operand, but not necessarily. A FrameIndex for example could resolve to an
822   // inline immediate value that will not require an additional 4-bytes; this
823   // assumes that it will.
824   bool isLiteralConstantLike(const MachineOperand &MO,
825                              const MCOperandInfo &OpInfo) const;
826 
827   bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
828                          const MachineOperand &MO) const;
829 
830   /// Return true if this 64-bit VALU instruction has a 32-bit encoding.
831   /// This function will return false if you pass it a 32-bit instruction.
832   bool hasVALU32BitEncoding(unsigned Opcode) const;
833 
834   /// Returns true if this operand uses the constant bus.
835   bool usesConstantBus(const MachineRegisterInfo &MRI,
836                        const MachineOperand &MO,
837                        const MCOperandInfo &OpInfo) const;
838 
839   /// Return true if this instruction has any modifiers.
840   ///  e.g. src[012]_mod, omod, clamp.
841   bool hasModifiers(unsigned Opcode) const;
842 
843   bool hasModifiersSet(const MachineInstr &MI,
844                        unsigned OpName) const;
845   bool hasAnyModifiersSet(const MachineInstr &MI) const;
846 
847   bool canShrink(const MachineInstr &MI,
848                  const MachineRegisterInfo &MRI) const;
849 
850   MachineInstr *buildShrunkInst(MachineInstr &MI,
851                                 unsigned NewOpcode) const;
852 
853   bool verifyInstruction(const MachineInstr &MI,
854                          StringRef &ErrInfo) const override;
855 
856   unsigned getVALUOp(const MachineInstr &MI) const;
857 
858   /// Return the correct register class for \p OpNo.  For target-specific
859   /// instructions, this will return the register class that has been defined
860   /// in tablegen.  For generic instructions, like REG_SEQUENCE it will return
861   /// the register class of its machine operand.
862   /// to infer the correct register class base on the other operands.
863   const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
864                                            unsigned OpNo) const;
865 
866   /// Return the size in bytes of the operand OpNo on the given
867   // instruction opcode.
getOpSize(uint16_t Opcode,unsigned OpNo)868   unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
869     const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
870 
871     if (OpInfo.RegClass == -1) {
872       // If this is an immediate operand, this must be a 32-bit literal.
873       assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
874       return 4;
875     }
876 
877     return RI.getRegSizeInBits(*RI.getRegClass(OpInfo.RegClass)) / 8;
878   }
879 
880   /// This form should usually be preferred since it handles operands
881   /// with unknown register classes.
getOpSize(const MachineInstr & MI,unsigned OpNo)882   unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
883     const MachineOperand &MO = MI.getOperand(OpNo);
884     if (MO.isReg()) {
885       if (unsigned SubReg = MO.getSubReg()) {
886         return RI.getSubRegIdxSize(SubReg) / 8;
887       }
888     }
889     return RI.getRegSizeInBits(*getOpRegClass(MI, OpNo)) / 8;
890   }
891 
892   /// Legalize the \p OpIndex operand of this instruction by inserting
893   /// a MOV.  For example:
894   /// ADD_I32_e32 VGPR0, 15
895   /// to
896   /// MOV VGPR1, 15
897   /// ADD_I32_e32 VGPR0, VGPR1
898   ///
899   /// If the operand being legalized is a register, then a COPY will be used
900   /// instead of MOV.
901   void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
902 
903   /// Check if \p MO is a legal operand if it was the \p OpIdx Operand
904   /// for \p MI.
905   bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
906                       const MachineOperand *MO = nullptr) const;
907 
908   /// Check if \p MO would be a valid operand for the given operand
909   /// definition \p OpInfo. Note this does not attempt to validate constant bus
910   /// restrictions (e.g. literal constant usage).
911   bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
912                           const MCOperandInfo &OpInfo,
913                           const MachineOperand &MO) const;
914 
915   /// Check if \p MO (a register operand) is a legal register for the
916   /// given operand description.
917   bool isLegalRegOperand(const MachineRegisterInfo &MRI,
918                          const MCOperandInfo &OpInfo,
919                          const MachineOperand &MO) const;
920 
921   /// Legalize operands in \p MI by either commuting it or inserting a
922   /// copy of src1.
923   void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
924 
925   /// Fix operands in \p MI to satisfy constant bus requirements.
926   void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
927 
928   /// Copy a value from a VGPR (\p SrcReg) to SGPR.  This function can only
929   /// be used when it is know that the value in SrcReg is same across all
930   /// threads in the wave.
931   /// \returns The SGPR register that \p SrcReg was copied to.
932   Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI,
933                               MachineRegisterInfo &MRI) const;
934 
935   void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
936   void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const;
937 
938   void legalizeGenericOperand(MachineBasicBlock &InsertMBB,
939                               MachineBasicBlock::iterator I,
940                               const TargetRegisterClass *DstRC,
941                               MachineOperand &Op, MachineRegisterInfo &MRI,
942                               const DebugLoc &DL) const;
943 
944   /// Legalize all operands in this instruction.  This function may create new
945   /// instructions and control-flow around \p MI.  If present, \p MDT is
946   /// updated.
947   /// \returns A new basic block that contains \p MI if new blocks were created.
948   MachineBasicBlock *
949   legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT = nullptr) const;
950 
951   /// Change SADDR form of a FLAT \p Inst to its VADDR form if saddr operand
952   /// was moved to VGPR. \returns true if succeeded.
953   bool moveFlatAddrToVGPR(MachineInstr &Inst) const;
954 
955   /// Replace this instruction's opcode with the equivalent VALU
956   /// opcode.  This function will also move the users of \p MI to the
957   /// VALU if necessary. If present, \p MDT is updated.
958   MachineBasicBlock *moveToVALU(MachineInstr &MI,
959                                 MachineDominatorTree *MDT = nullptr) const;
960 
961   void insertNoop(MachineBasicBlock &MBB,
962                   MachineBasicBlock::iterator MI) const override;
963 
964   void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
965                    unsigned Quantity) const override;
966 
967   void insertReturn(MachineBasicBlock &MBB) const;
968   /// Return the number of wait states that result from executing this
969   /// instruction.
970   static unsigned getNumWaitStates(const MachineInstr &MI);
971 
972   /// Returns the operand named \p Op.  If \p MI does not have an
973   /// operand named \c Op, this function returns nullptr.
974   LLVM_READONLY
975   MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
976 
977   LLVM_READONLY
getNamedOperand(const MachineInstr & MI,unsigned OpName)978   const MachineOperand *getNamedOperand(const MachineInstr &MI,
979                                         unsigned OpName) const {
980     return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
981   }
982 
983   /// Get required immediate operand
getNamedImmOperand(const MachineInstr & MI,unsigned OpName)984   int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
985     int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
986     return MI.getOperand(Idx).getImm();
987   }
988 
989   uint64_t getDefaultRsrcDataFormat() const;
990   uint64_t getScratchRsrcWords23() const;
991 
992   bool isLowLatencyInstruction(const MachineInstr &MI) const;
993   bool isHighLatencyDef(int Opc) const override;
994 
995   /// Return the descriptor of the target-specific machine instruction
996   /// that corresponds to the specified pseudo or native opcode.
getMCOpcodeFromPseudo(unsigned Opcode)997   const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
998     return get(pseudoToMCOpcode(Opcode));
999   }
1000 
1001   unsigned isStackAccess(const MachineInstr &MI, int &FrameIndex) const;
1002   unsigned isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex) const;
1003 
1004   unsigned isLoadFromStackSlot(const MachineInstr &MI,
1005                                int &FrameIndex) const override;
1006   unsigned isStoreToStackSlot(const MachineInstr &MI,
1007                               int &FrameIndex) const override;
1008 
1009   unsigned getInstBundleSize(const MachineInstr &MI) const;
1010   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
1011 
1012   bool mayAccessFlatAddressSpace(const MachineInstr &MI) const;
1013 
1014   bool isNonUniformBranchInstr(MachineInstr &Instr) const;
1015 
1016   void convertNonUniformIfRegion(MachineBasicBlock *IfEntry,
1017                                  MachineBasicBlock *IfEnd) const;
1018 
1019   void convertNonUniformLoopRegion(MachineBasicBlock *LoopEntry,
1020                                    MachineBasicBlock *LoopEnd) const;
1021 
1022   std::pair<unsigned, unsigned>
1023   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
1024 
1025   ArrayRef<std::pair<int, const char *>>
1026   getSerializableTargetIndices() const override;
1027 
1028   ArrayRef<std::pair<unsigned, const char *>>
1029   getSerializableDirectMachineOperandTargetFlags() const override;
1030 
1031   ScheduleHazardRecognizer *
1032   CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
1033                                  const ScheduleDAG *DAG) const override;
1034 
1035   ScheduleHazardRecognizer *
1036   CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
1037 
1038   bool isBasicBlockPrologue(const MachineInstr &MI) const override;
1039 
1040   MachineInstr *createPHIDestinationCopy(MachineBasicBlock &MBB,
1041                                          MachineBasicBlock::iterator InsPt,
1042                                          const DebugLoc &DL, Register Src,
1043                                          Register Dst) const override;
1044 
1045   MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB,
1046                                     MachineBasicBlock::iterator InsPt,
1047                                     const DebugLoc &DL, Register Src,
1048                                     unsigned SrcSubReg,
1049                                     Register Dst) const override;
1050 
1051   bool isWave32() const;
1052 
1053   /// Return a partially built integer add instruction without carry.
1054   /// Caller must add source operands.
1055   /// For pre-GFX9 it will generate unused carry destination operand.
1056   /// TODO: After GFX9 it should return a no-carry operation.
1057   MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
1058                                     MachineBasicBlock::iterator I,
1059                                     const DebugLoc &DL,
1060                                     Register DestReg) const;
1061 
1062   MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
1063                                     MachineBasicBlock::iterator I,
1064                                     const DebugLoc &DL,
1065                                     Register DestReg,
1066                                     RegScavenger &RS) const;
1067 
1068   static bool isKillTerminator(unsigned Opcode);
1069   const MCInstrDesc &getKillTerminatorFromPseudo(unsigned Opcode) const;
1070 
isLegalMUBUFImmOffset(unsigned Imm)1071   static bool isLegalMUBUFImmOffset(unsigned Imm) {
1072     return isUInt<12>(Imm);
1073   }
1074 
1075   /// Returns if \p Offset is legal for the subtarget as the offset to a FLAT
1076   /// encoded instruction. If \p Signed, this is for an instruction that
1077   /// interprets the offset as signed.
1078   bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
1079                          uint64_t FlatVariant) const;
1080 
1081   /// Split \p COffsetVal into {immediate offset field, remainder offset}
1082   /// values.
1083   std::pair<int64_t, int64_t> splitFlatOffset(int64_t COffsetVal,
1084                                               unsigned AddrSpace,
1085                                               uint64_t FlatVariant) const;
1086 
1087   /// \brief Return a target-specific opcode if Opcode is a pseudo instruction.
1088   /// Return -1 if the target-specific opcode for the pseudo instruction does
1089   /// not exist. If Opcode is not a pseudo instruction, this is identity.
1090   int pseudoToMCOpcode(int Opcode) const;
1091 
1092   /// \brief Check if this instruction should only be used by assembler.
1093   /// Return true if this opcode should not be used by codegen.
1094   bool isAsmOnlyOpcode(int MCOp) const;
1095 
1096   const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum,
1097                                          const TargetRegisterInfo *TRI,
1098                                          const MachineFunction &MF)
1099     const override;
1100 
1101   void fixImplicitOperands(MachineInstr &MI) const;
1102 
1103   MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
1104                                       ArrayRef<unsigned> Ops,
1105                                       MachineBasicBlock::iterator InsertPt,
1106                                       int FrameIndex,
1107                                       LiveIntervals *LIS = nullptr,
1108                                       VirtRegMap *VRM = nullptr) const override;
1109 
1110   unsigned getInstrLatency(const InstrItineraryData *ItinData,
1111                            const MachineInstr &MI,
1112                            unsigned *PredCost = nullptr) const override;
1113 
getMIRFormatter()1114   const MIRFormatter *getMIRFormatter() const override {
1115     if (!Formatter.get())
1116       Formatter = std::make_unique<AMDGPUMIRFormatter>();
1117     return Formatter.get();
1118   }
1119 
1120   static unsigned getDSShaderTypeValue(const MachineFunction &MF);
1121 };
1122 
1123 /// \brief Returns true if a reg:subreg pair P has a TRC class
isOfRegClass(const TargetInstrInfo::RegSubRegPair & P,const TargetRegisterClass & TRC,MachineRegisterInfo & MRI)1124 inline bool isOfRegClass(const TargetInstrInfo::RegSubRegPair &P,
1125                          const TargetRegisterClass &TRC,
1126                          MachineRegisterInfo &MRI) {
1127   auto *RC = MRI.getRegClass(P.Reg);
1128   if (!P.SubReg)
1129     return RC == &TRC;
1130   auto *TRI = MRI.getTargetRegisterInfo();
1131   return RC == TRI->getMatchingSuperRegClass(RC, &TRC, P.SubReg);
1132 }
1133 
1134 /// \brief Create RegSubRegPair from a register MachineOperand
1135 inline
getRegSubRegPair(const MachineOperand & O)1136 TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O) {
1137   assert(O.isReg());
1138   return TargetInstrInfo::RegSubRegPair(O.getReg(), O.getSubReg());
1139 }
1140 
1141 /// \brief Return the SubReg component from REG_SEQUENCE
1142 TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI,
1143                                                     unsigned SubReg);
1144 
1145 /// \brief Return the defining instruction for a given reg:subreg pair
1146 /// skipping copy like instructions and subreg-manipulation pseudos.
1147 /// Following another subreg of a reg:subreg isn't supported.
1148 MachineInstr *getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P,
1149                                MachineRegisterInfo &MRI);
1150 
1151 /// \brief Return false if EXEC is not changed between the def of \p VReg at \p
1152 /// DefMI and the use at \p UseMI. Should be run on SSA. Currently does not
1153 /// attempt to track between blocks.
1154 bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI,
1155                                 Register VReg,
1156                                 const MachineInstr &DefMI,
1157                                 const MachineInstr &UseMI);
1158 
1159 /// \brief Return false if EXEC is not changed between the def of \p VReg at \p
1160 /// DefMI and all its uses. Should be run on SSA. Currently does not attempt to
1161 /// track between blocks.
1162 bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI,
1163                                    Register VReg,
1164                                    const MachineInstr &DefMI);
1165 
1166 namespace AMDGPU {
1167 
1168   LLVM_READONLY
1169   int getVOPe64(uint16_t Opcode);
1170 
1171   LLVM_READONLY
1172   int getVOPe32(uint16_t Opcode);
1173 
1174   LLVM_READONLY
1175   int getSDWAOp(uint16_t Opcode);
1176 
1177   LLVM_READONLY
1178   int getDPPOp32(uint16_t Opcode);
1179 
1180   LLVM_READONLY
1181   int getBasicFromSDWAOp(uint16_t Opcode);
1182 
1183   LLVM_READONLY
1184   int getCommuteRev(uint16_t Opcode);
1185 
1186   LLVM_READONLY
1187   int getCommuteOrig(uint16_t Opcode);
1188 
1189   LLVM_READONLY
1190   int getAddr64Inst(uint16_t Opcode);
1191 
1192   /// Check if \p Opcode is an Addr64 opcode.
1193   ///
1194   /// \returns \p Opcode if it is an Addr64 opcode, otherwise -1.
1195   LLVM_READONLY
1196   int getIfAddr64Inst(uint16_t Opcode);
1197 
1198   LLVM_READONLY
1199   int getMUBUFNoLdsInst(uint16_t Opcode);
1200 
1201   LLVM_READONLY
1202   int getAtomicNoRetOp(uint16_t Opcode);
1203 
1204   LLVM_READONLY
1205   int getSOPKOp(uint16_t Opcode);
1206 
1207   /// \returns SADDR form of a FLAT Global instruction given an \p Opcode
1208   /// of a VADDR form.
1209   LLVM_READONLY
1210   int getGlobalSaddrOp(uint16_t Opcode);
1211 
1212   /// \returns VADDR form of a FLAT Global instruction given an \p Opcode
1213   /// of a SADDR form.
1214   LLVM_READONLY
1215   int getGlobalVaddrOp(uint16_t Opcode);
1216 
1217   LLVM_READONLY
1218   int getVCMPXNoSDstOp(uint16_t Opcode);
1219 
1220   /// \returns ST form with only immediate offset of a FLAT Scratch instruction
1221   /// given an \p Opcode of an SS (SADDR) form.
1222   LLVM_READONLY
1223   int getFlatScratchInstSTfromSS(uint16_t Opcode);
1224 
1225   /// \returns SS (SADDR) form of a FLAT Scratch instruction given an \p Opcode
1226   /// of an SV (VADDR) form.
1227   LLVM_READONLY
1228   int getFlatScratchInstSSfromSV(uint16_t Opcode);
1229 
1230   /// \returns SV (VADDR) form of a FLAT Scratch instruction given an \p Opcode
1231   /// of an SS (SADDR) form.
1232   LLVM_READONLY
1233   int getFlatScratchInstSVfromSS(uint16_t Opcode);
1234 
1235   const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
1236   const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
1237   const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
1238   const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
1239 
1240 } // end namespace AMDGPU
1241 
1242 namespace SI {
1243 namespace KernelInputOffsets {
1244 
1245 /// Offsets in bytes from the start of the input buffer
1246 enum Offsets {
1247   NGROUPS_X = 0,
1248   NGROUPS_Y = 4,
1249   NGROUPS_Z = 8,
1250   GLOBAL_SIZE_X = 12,
1251   GLOBAL_SIZE_Y = 16,
1252   GLOBAL_SIZE_Z = 20,
1253   LOCAL_SIZE_X = 24,
1254   LOCAL_SIZE_Y = 28,
1255   LOCAL_SIZE_Z = 32
1256 };
1257 
1258 } // end namespace KernelInputOffsets
1259 } // end namespace SI
1260 
1261 } // end namespace llvm
1262 
1263 #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
1264