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