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