1 //===- SIInstrInfo.h - SI Instruction Info Interface ------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// Interface definition for SIInstrInfo.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
15 #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
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"
24 #define GET_INSTRINFO_HEADER
25 #include "AMDGPUGenInstrInfo.inc"
32 class MachineDominatorTree;
33 class MachineRegisterInfo;
35 class TargetRegisterClass;
36 class ScheduleHazardRecognizer;
38 class SIInstrInfo final : public AMDGPUGenInstrInfo {
40 const SIRegisterInfo RI;
41 const GCNSubtarget &ST;
42 TargetSchedModel SchedModel;
43 mutable std::unique_ptr<AMDGPUMIRFormatter> Formatter;
45 // The inverse predicate should have the negative value.
46 enum BranchPredicate {
56 using SetVectorType = SmallSetVector<MachineInstr *, 32>;
58 static unsigned getBranchOpcode(BranchPredicate Cond);
59 static BranchPredicate getBranchPredicate(unsigned Opcode);
62 unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
63 MachineRegisterInfo &MRI,
64 MachineOperand &SuperReg,
65 const TargetRegisterClass *SuperRC,
67 const TargetRegisterClass *SubRC) const;
68 MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
69 MachineRegisterInfo &MRI,
70 MachineOperand &SuperReg,
71 const TargetRegisterClass *SuperRC,
73 const TargetRegisterClass *SubRC) const;
75 void swapOperands(MachineInstr &Inst) const;
77 std::pair<bool, MachineBasicBlock *>
78 moveScalarAddSub(SetVectorType &Worklist, MachineInstr &Inst,
79 MachineDominatorTree *MDT = nullptr) const;
81 void lowerSelect(SetVectorType &Worklist, MachineInstr &Inst,
82 MachineDominatorTree *MDT = nullptr) const;
84 void lowerScalarAbs(SetVectorType &Worklist,
85 MachineInstr &Inst) const;
87 void lowerScalarXnor(SetVectorType &Worklist,
88 MachineInstr &Inst) const;
90 void splitScalarNotBinop(SetVectorType &Worklist,
92 unsigned Opcode) const;
94 void splitScalarBinOpN2(SetVectorType &Worklist,
96 unsigned Opcode) const;
98 void splitScalar64BitUnaryOp(SetVectorType &Worklist,
99 MachineInstr &Inst, unsigned Opcode) const;
101 void splitScalar64BitAddSub(SetVectorType &Worklist, MachineInstr &Inst,
102 MachineDominatorTree *MDT = nullptr) const;
104 void splitScalar64BitBinaryOp(SetVectorType &Worklist, MachineInstr &Inst,
106 MachineDominatorTree *MDT = nullptr) const;
108 void splitScalar64BitXnor(SetVectorType &Worklist, MachineInstr &Inst,
109 MachineDominatorTree *MDT = nullptr) const;
111 void splitScalar64BitBCNT(SetVectorType &Worklist,
112 MachineInstr &Inst) const;
113 void splitScalar64BitBFE(SetVectorType &Worklist,
114 MachineInstr &Inst) const;
115 void movePackToVALU(SetVectorType &Worklist,
116 MachineRegisterInfo &MRI,
117 MachineInstr &Inst) const;
119 void addUsersToMoveToVALUWorklist(Register Reg, MachineRegisterInfo &MRI,
120 SetVectorType &Worklist) const;
122 void addSCCDefUsersToVALUWorklist(MachineOperand &Op,
123 MachineInstr &SCCDefInst,
124 SetVectorType &Worklist) const;
126 const TargetRegisterClass *
127 getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
129 bool checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
130 const MachineInstr &MIb) const;
132 Register findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
135 bool swapSourceModifiers(MachineInstr &MI,
136 MachineOperand &Src0, unsigned Src0OpName,
137 MachineOperand &Src1, unsigned Src1OpName) const;
139 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
141 unsigned OpIdx1) const override;
144 enum TargetOperandFlags {
148 // MO_GOTPCREL -> symbol@GOTPCREL -> R_AMDGPU_GOTPCREL.
150 // MO_GOTPCREL32_LO -> symbol@gotpcrel32@lo -> R_AMDGPU_GOTPCREL32_LO.
152 MO_GOTPCREL32_LO = 2,
153 // MO_GOTPCREL32_HI -> symbol@gotpcrel32@hi -> R_AMDGPU_GOTPCREL32_HI.
154 MO_GOTPCREL32_HI = 3,
155 // MO_REL32_LO -> symbol@rel32@lo -> R_AMDGPU_REL32_LO.
158 // MO_REL32_HI -> symbol@rel32@hi -> R_AMDGPU_REL32_HI.
161 MO_LONG_BRANCH_FORWARD = 6,
162 MO_LONG_BRANCH_BACKWARD = 7,
168 explicit SIInstrInfo(const GCNSubtarget &ST);
170 const SIRegisterInfo &getRegisterInfo() const {
174 bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
175 AAResults *AA) const override;
177 bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
179 int64_t &Offset2) const override;
181 bool getMemOperandsWithOffsetWidth(
182 const MachineInstr &LdSt,
183 SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset,
184 bool &OffsetIsScalable, unsigned &Width,
185 const TargetRegisterInfo *TRI) const final;
187 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
188 ArrayRef<const MachineOperand *> BaseOps2,
189 unsigned NumLoads, unsigned NumBytes) const override;
191 bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0,
192 int64_t Offset1, unsigned NumLoads) const override;
194 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
195 const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
196 bool KillSrc) const override;
198 void materializeImmediate(MachineBasicBlock &MBB,
199 MachineBasicBlock::iterator MI,
202 int64_t Value) const;
204 const TargetRegisterClass *getPreferredSelectRegClass(
205 unsigned Size) const;
207 Register insertNE(MachineBasicBlock *MBB,
208 MachineBasicBlock::iterator I, const DebugLoc &DL,
209 Register SrcReg, int Value) const;
211 Register insertEQ(MachineBasicBlock *MBB,
212 MachineBasicBlock::iterator I, const DebugLoc &DL,
213 Register SrcReg, int Value) const;
215 void storeRegToStackSlot(MachineBasicBlock &MBB,
216 MachineBasicBlock::iterator MI, Register SrcReg,
217 bool isKill, int FrameIndex,
218 const TargetRegisterClass *RC,
219 const TargetRegisterInfo *TRI) const override;
221 void loadRegFromStackSlot(MachineBasicBlock &MBB,
222 MachineBasicBlock::iterator MI, Register DestReg,
223 int FrameIndex, const TargetRegisterClass *RC,
224 const TargetRegisterInfo *TRI) const override;
226 bool expandPostRAPseudo(MachineInstr &MI) const override;
228 // Splits a V_MOV_B64_DPP_PSEUDO opcode into a pair of v_mov_b32_dpp
229 // instructions. Returns a pair of generated instructions.
230 // Can split either post-RA with physical registers or pre-RA with
231 // virtual registers. In latter case IR needs to be in SSA form and
232 // and a REG_SEQUENCE is produced to define original register.
233 std::pair<MachineInstr*, MachineInstr*>
234 expandMovDPP64(MachineInstr &MI) const;
236 // Returns an opcode that can be used to move a value to a \p DstRC
237 // register. If there is no hardware instruction that can store to \p
238 // DstRC, then AMDGPU::COPY is returned.
239 unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
241 const MCInstrDesc &getIndirectRegWriteMovRelPseudo(unsigned VecSize,
245 const MCInstrDesc &getIndirectGPRIDXPseudo(unsigned VecSize,
246 bool IsIndirectSrc) const;
248 int commuteOpcode(unsigned Opc) const;
251 inline int commuteOpcode(const MachineInstr &MI) const {
252 return commuteOpcode(MI.getOpcode());
255 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
256 unsigned &SrcOpIdx2) const override;
258 bool findCommutedOpIndices(MCInstrDesc Desc, unsigned & SrcOpIdx0,
259 unsigned & SrcOpIdx1) const;
261 bool isBranchOffsetInRange(unsigned BranchOpc,
262 int64_t BrOffset) const override;
264 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
266 unsigned insertIndirectBranch(MachineBasicBlock &MBB,
267 MachineBasicBlock &NewDestBB,
270 RegScavenger *RS = nullptr) const override;
272 bool analyzeBranchImpl(MachineBasicBlock &MBB,
273 MachineBasicBlock::iterator I,
274 MachineBasicBlock *&TBB,
275 MachineBasicBlock *&FBB,
276 SmallVectorImpl<MachineOperand> &Cond,
277 bool AllowModify) const;
279 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
280 MachineBasicBlock *&FBB,
281 SmallVectorImpl<MachineOperand> &Cond,
282 bool AllowModify = false) const override;
284 unsigned removeBranch(MachineBasicBlock &MBB,
285 int *BytesRemoved = nullptr) const override;
287 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
288 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
290 int *BytesAdded = nullptr) const override;
292 bool reverseBranchCondition(
293 SmallVectorImpl<MachineOperand> &Cond) const override;
295 bool canInsertSelect(const MachineBasicBlock &MBB,
296 ArrayRef<MachineOperand> Cond, Register DstReg,
297 Register TrueReg, Register FalseReg, int &CondCycles,
298 int &TrueCycles, int &FalseCycles) const override;
300 void insertSelect(MachineBasicBlock &MBB,
301 MachineBasicBlock::iterator I, const DebugLoc &DL,
302 Register DstReg, ArrayRef<MachineOperand> Cond,
303 Register TrueReg, Register FalseReg) const override;
305 void insertVectorSelect(MachineBasicBlock &MBB,
306 MachineBasicBlock::iterator I, const DebugLoc &DL,
307 Register DstReg, ArrayRef<MachineOperand> Cond,
308 Register TrueReg, Register FalseReg) const;
310 unsigned getAddressSpaceForPseudoSourceKind(
311 unsigned Kind) const override;
314 areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
315 const MachineInstr &MIb) const override;
317 bool isFoldableCopy(const MachineInstr &MI) const;
319 bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg,
320 MachineRegisterInfo *MRI) const final;
322 unsigned getMachineCSELookAheadLimit() const override { return 500; }
324 MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
326 LiveVariables *LV) const override;
328 bool isSchedulingBoundary(const MachineInstr &MI,
329 const MachineBasicBlock *MBB,
330 const MachineFunction &MF) const override;
332 static bool isSALU(const MachineInstr &MI) {
333 return MI.getDesc().TSFlags & SIInstrFlags::SALU;
336 bool isSALU(uint16_t Opcode) const {
337 return get(Opcode).TSFlags & SIInstrFlags::SALU;
340 static bool isVALU(const MachineInstr &MI) {
341 return MI.getDesc().TSFlags & SIInstrFlags::VALU;
344 bool isVALU(uint16_t Opcode) const {
345 return get(Opcode).TSFlags & SIInstrFlags::VALU;
348 static bool isVMEM(const MachineInstr &MI) {
349 return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
352 bool isVMEM(uint16_t Opcode) const {
353 return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
356 static bool isSOP1(const MachineInstr &MI) {
357 return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
360 bool isSOP1(uint16_t Opcode) const {
361 return get(Opcode).TSFlags & SIInstrFlags::SOP1;
364 static bool isSOP2(const MachineInstr &MI) {
365 return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
368 bool isSOP2(uint16_t Opcode) const {
369 return get(Opcode).TSFlags & SIInstrFlags::SOP2;
372 static bool isSOPC(const MachineInstr &MI) {
373 return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
376 bool isSOPC(uint16_t Opcode) const {
377 return get(Opcode).TSFlags & SIInstrFlags::SOPC;
380 static bool isSOPK(const MachineInstr &MI) {
381 return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
384 bool isSOPK(uint16_t Opcode) const {
385 return get(Opcode).TSFlags & SIInstrFlags::SOPK;
388 static bool isSOPP(const MachineInstr &MI) {
389 return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
392 bool isSOPP(uint16_t Opcode) const {
393 return get(Opcode).TSFlags & SIInstrFlags::SOPP;
396 static bool isPacked(const MachineInstr &MI) {
397 return MI.getDesc().TSFlags & SIInstrFlags::IsPacked;
400 bool isPacked(uint16_t Opcode) const {
401 return get(Opcode).TSFlags & SIInstrFlags::IsPacked;
404 static bool isVOP1(const MachineInstr &MI) {
405 return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
408 bool isVOP1(uint16_t Opcode) const {
409 return get(Opcode).TSFlags & SIInstrFlags::VOP1;
412 static bool isVOP2(const MachineInstr &MI) {
413 return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
416 bool isVOP2(uint16_t Opcode) const {
417 return get(Opcode).TSFlags & SIInstrFlags::VOP2;
420 static bool isVOP3(const MachineInstr &MI) {
421 return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
424 bool isVOP3(uint16_t Opcode) const {
425 return get(Opcode).TSFlags & SIInstrFlags::VOP3;
428 static bool isSDWA(const MachineInstr &MI) {
429 return MI.getDesc().TSFlags & SIInstrFlags::SDWA;
432 bool isSDWA(uint16_t Opcode) const {
433 return get(Opcode).TSFlags & SIInstrFlags::SDWA;
436 static bool isVOPC(const MachineInstr &MI) {
437 return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
440 bool isVOPC(uint16_t Opcode) const {
441 return get(Opcode).TSFlags & SIInstrFlags::VOPC;
444 static bool isMUBUF(const MachineInstr &MI) {
445 return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
448 bool isMUBUF(uint16_t Opcode) const {
449 return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
452 static bool isMTBUF(const MachineInstr &MI) {
453 return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
456 bool isMTBUF(uint16_t Opcode) const {
457 return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
460 static bool isSMRD(const MachineInstr &MI) {
461 return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
464 bool isSMRD(uint16_t Opcode) const {
465 return get(Opcode).TSFlags & SIInstrFlags::SMRD;
468 bool isBufferSMRD(const MachineInstr &MI) const;
470 static bool isDS(const MachineInstr &MI) {
471 return MI.getDesc().TSFlags & SIInstrFlags::DS;
474 bool isDS(uint16_t Opcode) const {
475 return get(Opcode).TSFlags & SIInstrFlags::DS;
478 bool isAlwaysGDS(uint16_t Opcode) const;
480 static bool isMIMG(const MachineInstr &MI) {
481 return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
484 bool isMIMG(uint16_t Opcode) const {
485 return get(Opcode).TSFlags & SIInstrFlags::MIMG;
488 static bool isGather4(const MachineInstr &MI) {
489 return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
492 bool isGather4(uint16_t Opcode) const {
493 return get(Opcode).TSFlags & SIInstrFlags::Gather4;
496 static bool isFLAT(const MachineInstr &MI) {
497 return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
500 // Is a FLAT encoded instruction which accesses a specific segment,
501 // i.e. global_* or scratch_*.
502 static bool isSegmentSpecificFLAT(const MachineInstr &MI) {
503 auto Flags = MI.getDesc().TSFlags;
504 return Flags & (SIInstrFlags::IsFlatGlobal | SIInstrFlags::IsFlatScratch);
507 bool isSegmentSpecificFLAT(uint16_t Opcode) const {
508 auto Flags = get(Opcode).TSFlags;
509 return Flags & (SIInstrFlags::IsFlatGlobal | SIInstrFlags::IsFlatScratch);
512 static bool isFLATGlobal(const MachineInstr &MI) {
513 return MI.getDesc().TSFlags & SIInstrFlags::IsFlatGlobal;
516 bool isFLATGlobal(uint16_t Opcode) const {
517 return get(Opcode).TSFlags & SIInstrFlags::IsFlatGlobal;
520 static bool isFLATScratch(const MachineInstr &MI) {
521 return MI.getDesc().TSFlags & SIInstrFlags::IsFlatScratch;
524 bool isFLATScratch(uint16_t Opcode) const {
525 return get(Opcode).TSFlags & SIInstrFlags::IsFlatScratch;
528 // Any FLAT encoded instruction, including global_* and scratch_*.
529 bool isFLAT(uint16_t Opcode) const {
530 return get(Opcode).TSFlags & SIInstrFlags::FLAT;
533 static bool isEXP(const MachineInstr &MI) {
534 return MI.getDesc().TSFlags & SIInstrFlags::EXP;
537 bool isEXP(uint16_t Opcode) const {
538 return get(Opcode).TSFlags & SIInstrFlags::EXP;
541 static bool isWQM(const MachineInstr &MI) {
542 return MI.getDesc().TSFlags & SIInstrFlags::WQM;
545 bool isWQM(uint16_t Opcode) const {
546 return get(Opcode).TSFlags & SIInstrFlags::WQM;
549 static bool isDisableWQM(const MachineInstr &MI) {
550 return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM;
553 bool isDisableWQM(uint16_t Opcode) const {
554 return get(Opcode).TSFlags & SIInstrFlags::DisableWQM;
557 static bool isVGPRSpill(const MachineInstr &MI) {
558 return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
561 bool isVGPRSpill(uint16_t Opcode) const {
562 return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
565 static bool isSGPRSpill(const MachineInstr &MI) {
566 return MI.getDesc().TSFlags & SIInstrFlags::SGPRSpill;
569 bool isSGPRSpill(uint16_t Opcode) const {
570 return get(Opcode).TSFlags & SIInstrFlags::SGPRSpill;
573 static bool isDPP(const MachineInstr &MI) {
574 return MI.getDesc().TSFlags & SIInstrFlags::DPP;
577 bool isDPP(uint16_t Opcode) const {
578 return get(Opcode).TSFlags & SIInstrFlags::DPP;
581 static bool isTRANS(const MachineInstr &MI) {
582 return MI.getDesc().TSFlags & SIInstrFlags::TRANS;
585 bool isTRANS(uint16_t Opcode) const {
586 return get(Opcode).TSFlags & SIInstrFlags::TRANS;
589 static bool isVOP3P(const MachineInstr &MI) {
590 return MI.getDesc().TSFlags & SIInstrFlags::VOP3P;
593 bool isVOP3P(uint16_t Opcode) const {
594 return get(Opcode).TSFlags & SIInstrFlags::VOP3P;
597 static bool isVINTRP(const MachineInstr &MI) {
598 return MI.getDesc().TSFlags & SIInstrFlags::VINTRP;
601 bool isVINTRP(uint16_t Opcode) const {
602 return get(Opcode).TSFlags & SIInstrFlags::VINTRP;
605 static bool isMAI(const MachineInstr &MI) {
606 return MI.getDesc().TSFlags & SIInstrFlags::IsMAI;
609 bool isMAI(uint16_t Opcode) const {
610 return get(Opcode).TSFlags & SIInstrFlags::IsMAI;
613 static bool isDOT(const MachineInstr &MI) {
614 return MI.getDesc().TSFlags & SIInstrFlags::IsDOT;
617 bool isDOT(uint16_t Opcode) const {
618 return get(Opcode).TSFlags & SIInstrFlags::IsDOT;
621 static bool isScalarUnit(const MachineInstr &MI) {
622 return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
625 static bool usesVM_CNT(const MachineInstr &MI) {
626 return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
629 static bool usesLGKM_CNT(const MachineInstr &MI) {
630 return MI.getDesc().TSFlags & SIInstrFlags::LGKM_CNT;
633 static bool sopkIsZext(const MachineInstr &MI) {
634 return MI.getDesc().TSFlags & SIInstrFlags::SOPK_ZEXT;
637 bool sopkIsZext(uint16_t Opcode) const {
638 return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT;
641 /// \returns true if this is an s_store_dword* instruction. This is more
642 /// specific than than isSMEM && mayStore.
643 static bool isScalarStore(const MachineInstr &MI) {
644 return MI.getDesc().TSFlags & SIInstrFlags::SCALAR_STORE;
647 bool isScalarStore(uint16_t Opcode) const {
648 return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE;
651 static bool isFixedSize(const MachineInstr &MI) {
652 return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE;
655 bool isFixedSize(uint16_t Opcode) const {
656 return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE;
659 static bool hasFPClamp(const MachineInstr &MI) {
660 return MI.getDesc().TSFlags & SIInstrFlags::FPClamp;
663 bool hasFPClamp(uint16_t Opcode) const {
664 return get(Opcode).TSFlags & SIInstrFlags::FPClamp;
667 static bool hasIntClamp(const MachineInstr &MI) {
668 return MI.getDesc().TSFlags & SIInstrFlags::IntClamp;
671 uint64_t getClampMask(const MachineInstr &MI) const {
672 const uint64_t ClampFlags = SIInstrFlags::FPClamp |
673 SIInstrFlags::IntClamp |
674 SIInstrFlags::ClampLo |
675 SIInstrFlags::ClampHi;
676 return MI.getDesc().TSFlags & ClampFlags;
679 static bool usesFPDPRounding(const MachineInstr &MI) {
680 return MI.getDesc().TSFlags & SIInstrFlags::FPDPRounding;
683 bool usesFPDPRounding(uint16_t Opcode) const {
684 return get(Opcode).TSFlags & SIInstrFlags::FPDPRounding;
687 static bool isFPAtomic(const MachineInstr &MI) {
688 return MI.getDesc().TSFlags & SIInstrFlags::FPAtomic;
691 bool isFPAtomic(uint16_t Opcode) const {
692 return get(Opcode).TSFlags & SIInstrFlags::FPAtomic;
695 bool isVGPRCopy(const MachineInstr &MI) const {
697 Register Dest = MI.getOperand(0).getReg();
698 const MachineFunction &MF = *MI.getParent()->getParent();
699 const MachineRegisterInfo &MRI = MF.getRegInfo();
700 return !RI.isSGPRReg(MRI, Dest);
703 bool hasVGPRUses(const MachineInstr &MI) const {
704 const MachineFunction &MF = *MI.getParent()->getParent();
705 const MachineRegisterInfo &MRI = MF.getRegInfo();
706 return llvm::any_of(MI.explicit_uses(),
707 [&MRI, this](const MachineOperand &MO) {
708 return MO.isReg() && RI.isVGPR(MRI, MO.getReg());});
711 /// Return true if the instruction modifies the mode register.q
712 static bool modifiesModeRegister(const MachineInstr &MI);
714 /// Whether we must prevent this instruction from executing with EXEC = 0.
715 bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const;
717 /// Returns true if the instruction could potentially depend on the value of
718 /// exec. If false, exec dependencies may safely be ignored.
719 bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const;
721 bool isInlineConstant(const APInt &Imm) const;
723 bool isInlineConstant(const APFloat &Imm) const {
724 return isInlineConstant(Imm.bitcastToAPInt());
727 bool isInlineConstant(const MachineOperand &MO, uint8_t OperandType) const;
729 bool isInlineConstant(const MachineOperand &MO,
730 const MCOperandInfo &OpInfo) const {
731 return isInlineConstant(MO, OpInfo.OperandType);
734 /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would
735 /// be an inline immediate.
736 bool isInlineConstant(const MachineInstr &MI,
737 const MachineOperand &UseMO,
738 const MachineOperand &DefMO) const {
739 assert(UseMO.getParent() == &MI);
740 int OpIdx = MI.getOperandNo(&UseMO);
741 if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) {
745 return isInlineConstant(DefMO, MI.getDesc().OpInfo[OpIdx]);
748 /// \p returns true if the operand \p OpIdx in \p MI is a valid inline
750 bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx) const {
751 const MachineOperand &MO = MI.getOperand(OpIdx);
752 return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
755 bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx,
756 const MachineOperand &MO) const {
757 if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands)
761 unsigned Size = getOpSize(MI, OpIdx);
762 assert(Size == 8 || Size == 4);
764 uint8_t OpType = (Size == 8) ?
765 AMDGPU::OPERAND_REG_IMM_INT64 : AMDGPU::OPERAND_REG_IMM_INT32;
766 return isInlineConstant(MO, OpType);
769 return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
772 bool isInlineConstant(const MachineOperand &MO) const {
773 const MachineInstr *Parent = MO.getParent();
774 return isInlineConstant(*Parent, Parent->getOperandNo(&MO));
777 bool isLiteralConstant(const MachineOperand &MO,
778 const MCOperandInfo &OpInfo) const {
779 return MO.isImm() && !isInlineConstant(MO, OpInfo.OperandType);
782 bool isLiteralConstant(const MachineInstr &MI, int OpIdx) const {
783 const MachineOperand &MO = MI.getOperand(OpIdx);
784 return MO.isImm() && !isInlineConstant(MI, OpIdx);
787 // Returns true if this operand could potentially require a 32-bit literal
788 // operand, but not necessarily. A FrameIndex for example could resolve to an
789 // inline immediate value that will not require an additional 4-bytes; this
790 // assumes that it will.
791 bool isLiteralConstantLike(const MachineOperand &MO,
792 const MCOperandInfo &OpInfo) const;
794 bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
795 const MachineOperand &MO) const;
797 /// Return true if this 64-bit VALU instruction has a 32-bit encoding.
798 /// This function will return false if you pass it a 32-bit instruction.
799 bool hasVALU32BitEncoding(unsigned Opcode) const;
801 /// Returns true if this operand uses the constant bus.
802 bool usesConstantBus(const MachineRegisterInfo &MRI,
803 const MachineOperand &MO,
804 const MCOperandInfo &OpInfo) const;
806 /// Return true if this instruction has any modifiers.
807 /// e.g. src[012]_mod, omod, clamp.
808 bool hasModifiers(unsigned Opcode) const;
810 bool hasModifiersSet(const MachineInstr &MI,
811 unsigned OpName) const;
812 bool hasAnyModifiersSet(const MachineInstr &MI) const;
814 bool canShrink(const MachineInstr &MI,
815 const MachineRegisterInfo &MRI) const;
817 MachineInstr *buildShrunkInst(MachineInstr &MI,
818 unsigned NewOpcode) const;
820 bool verifyInstruction(const MachineInstr &MI,
821 StringRef &ErrInfo) const override;
823 unsigned getVALUOp(const MachineInstr &MI) const;
825 /// Return the correct register class for \p OpNo. For target-specific
826 /// instructions, this will return the register class that has been defined
827 /// in tablegen. For generic instructions, like REG_SEQUENCE it will return
828 /// the register class of its machine operand.
829 /// to infer the correct register class base on the other operands.
830 const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
831 unsigned OpNo) const;
833 /// Return the size in bytes of the operand OpNo on the given
834 // instruction opcode.
835 unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
836 const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
838 if (OpInfo.RegClass == -1) {
839 // If this is an immediate operand, this must be a 32-bit literal.
840 assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
844 return RI.getRegSizeInBits(*RI.getRegClass(OpInfo.RegClass)) / 8;
847 /// This form should usually be preferred since it handles operands
848 /// with unknown register classes.
849 unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
850 const MachineOperand &MO = MI.getOperand(OpNo);
852 if (unsigned SubReg = MO.getSubReg()) {
853 return RI.getSubRegIdxSize(SubReg) / 8;
856 return RI.getRegSizeInBits(*getOpRegClass(MI, OpNo)) / 8;
859 /// Legalize the \p OpIndex operand of this instruction by inserting
860 /// a MOV. For example:
861 /// ADD_I32_e32 VGPR0, 15
864 /// ADD_I32_e32 VGPR0, VGPR1
866 /// If the operand being legalized is a register, then a COPY will be used
868 void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
870 /// Check if \p MO is a legal operand if it was the \p OpIdx Operand
872 bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
873 const MachineOperand *MO = nullptr) const;
875 /// Check if \p MO would be a valid operand for the given operand
876 /// definition \p OpInfo. Note this does not attempt to validate constant bus
877 /// restrictions (e.g. literal constant usage).
878 bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
879 const MCOperandInfo &OpInfo,
880 const MachineOperand &MO) const;
882 /// Check if \p MO (a register operand) is a legal register for the
883 /// given operand description.
884 bool isLegalRegOperand(const MachineRegisterInfo &MRI,
885 const MCOperandInfo &OpInfo,
886 const MachineOperand &MO) const;
888 /// Legalize operands in \p MI by either commuting it or inserting a
890 void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
892 /// Fix operands in \p MI to satisfy constant bus requirements.
893 void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
895 /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
896 /// be used when it is know that the value in SrcReg is same across all
897 /// threads in the wave.
898 /// \returns The SGPR register that \p SrcReg was copied to.
899 Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI,
900 MachineRegisterInfo &MRI) const;
902 void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
903 void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const;
905 void legalizeGenericOperand(MachineBasicBlock &InsertMBB,
906 MachineBasicBlock::iterator I,
907 const TargetRegisterClass *DstRC,
908 MachineOperand &Op, MachineRegisterInfo &MRI,
909 const DebugLoc &DL) const;
911 /// Legalize all operands in this instruction. This function may create new
912 /// instructions and control-flow around \p MI. If present, \p MDT is
914 /// \returns A new basic block that contains \p MI if new blocks were created.
916 legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT = nullptr) const;
918 /// Replace this instruction's opcode with the equivalent VALU
919 /// opcode. This function will also move the users of \p MI to the
920 /// VALU if necessary. If present, \p MDT is updated.
921 MachineBasicBlock *moveToVALU(MachineInstr &MI,
922 MachineDominatorTree *MDT = nullptr) const;
924 void insertNoop(MachineBasicBlock &MBB,
925 MachineBasicBlock::iterator MI) const override;
927 void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
928 unsigned Quantity) const override;
930 void insertReturn(MachineBasicBlock &MBB) const;
931 /// Return the number of wait states that result from executing this
933 static unsigned getNumWaitStates(const MachineInstr &MI);
935 /// Returns the operand named \p Op. If \p MI does not have an
936 /// operand named \c Op, this function returns nullptr.
938 MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
941 const MachineOperand *getNamedOperand(const MachineInstr &MI,
942 unsigned OpName) const {
943 return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
946 /// Get required immediate operand
947 int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
948 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
949 return MI.getOperand(Idx).getImm();
952 uint64_t getDefaultRsrcDataFormat() const;
953 uint64_t getScratchRsrcWords23() const;
955 bool isLowLatencyInstruction(const MachineInstr &MI) const;
956 bool isHighLatencyDef(int Opc) const override;
958 /// Return the descriptor of the target-specific machine instruction
959 /// that corresponds to the specified pseudo or native opcode.
960 const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
961 return get(pseudoToMCOpcode(Opcode));
964 unsigned isStackAccess(const MachineInstr &MI, int &FrameIndex) const;
965 unsigned isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex) const;
967 unsigned isLoadFromStackSlot(const MachineInstr &MI,
968 int &FrameIndex) const override;
969 unsigned isStoreToStackSlot(const MachineInstr &MI,
970 int &FrameIndex) const override;
972 unsigned getInstBundleSize(const MachineInstr &MI) const;
973 unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
975 bool mayAccessFlatAddressSpace(const MachineInstr &MI) const;
977 bool isNonUniformBranchInstr(MachineInstr &Instr) const;
979 void convertNonUniformIfRegion(MachineBasicBlock *IfEntry,
980 MachineBasicBlock *IfEnd) const;
982 void convertNonUniformLoopRegion(MachineBasicBlock *LoopEntry,
983 MachineBasicBlock *LoopEnd) const;
985 std::pair<unsigned, unsigned>
986 decomposeMachineOperandsTargetFlags(unsigned TF) const override;
988 ArrayRef<std::pair<int, const char *>>
989 getSerializableTargetIndices() const override;
991 ArrayRef<std::pair<unsigned, const char *>>
992 getSerializableDirectMachineOperandTargetFlags() const override;
994 ScheduleHazardRecognizer *
995 CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
996 const ScheduleDAG *DAG) const override;
998 ScheduleHazardRecognizer *
999 CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
1001 bool isBasicBlockPrologue(const MachineInstr &MI) const override;
1003 MachineInstr *createPHIDestinationCopy(MachineBasicBlock &MBB,
1004 MachineBasicBlock::iterator InsPt,
1005 const DebugLoc &DL, Register Src,
1006 Register Dst) const override;
1008 MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB,
1009 MachineBasicBlock::iterator InsPt,
1010 const DebugLoc &DL, Register Src,
1012 Register Dst) const override;
1014 bool isWave32() const;
1016 /// Return a partially built integer add instruction without carry.
1017 /// Caller must add source operands.
1018 /// For pre-GFX9 it will generate unused carry destination operand.
1019 /// TODO: After GFX9 it should return a no-carry operation.
1020 MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
1021 MachineBasicBlock::iterator I,
1023 Register DestReg) const;
1025 MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
1026 MachineBasicBlock::iterator I,
1029 RegScavenger &RS) const;
1031 static bool isKillTerminator(unsigned Opcode);
1032 const MCInstrDesc &getKillTerminatorFromPseudo(unsigned Opcode) const;
1034 static bool isLegalMUBUFImmOffset(unsigned Imm) {
1035 return isUInt<12>(Imm);
1038 /// Returns if \p Offset is legal for the subtarget as the offset to a FLAT
1039 /// encoded instruction. If \p Signed, this is for an instruction that
1040 /// interprets the offset as signed.
1041 bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
1044 /// Split \p COffsetVal into {immediate offset field, remainder offset}
1046 std::pair<int64_t, int64_t> splitFlatOffset(int64_t COffsetVal,
1048 bool IsSigned) const;
1050 /// \brief Return a target-specific opcode if Opcode is a pseudo instruction.
1051 /// Return -1 if the target-specific opcode for the pseudo instruction does
1052 /// not exist. If Opcode is not a pseudo instruction, this is identity.
1053 int pseudoToMCOpcode(int Opcode) const;
1055 /// \brief Check if this instruction should only be used by assembler.
1056 /// Return true if this opcode should not be used by codegen.
1057 bool isAsmOnlyOpcode(int MCOp) const;
1059 const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum,
1060 const TargetRegisterInfo *TRI,
1061 const MachineFunction &MF)
1063 if (OpNum >= TID.getNumOperands())
1065 return RI.getRegClass(TID.OpInfo[OpNum].RegClass);
1068 void fixImplicitOperands(MachineInstr &MI) const;
1070 MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
1071 ArrayRef<unsigned> Ops,
1072 MachineBasicBlock::iterator InsertPt,
1074 LiveIntervals *LIS = nullptr,
1075 VirtRegMap *VRM = nullptr) const override;
1077 unsigned getInstrLatency(const InstrItineraryData *ItinData,
1078 const MachineInstr &MI,
1079 unsigned *PredCost = nullptr) const override;
1081 const MIRFormatter *getMIRFormatter() const override {
1082 if (!Formatter.get())
1083 Formatter = std::make_unique<AMDGPUMIRFormatter>();
1084 return Formatter.get();
1087 static unsigned getDSShaderTypeValue(const MachineFunction &MF);
1090 /// \brief Returns true if a reg:subreg pair P has a TRC class
1091 inline bool isOfRegClass(const TargetInstrInfo::RegSubRegPair &P,
1092 const TargetRegisterClass &TRC,
1093 MachineRegisterInfo &MRI) {
1094 auto *RC = MRI.getRegClass(P.Reg);
1097 auto *TRI = MRI.getTargetRegisterInfo();
1098 return RC == TRI->getMatchingSuperRegClass(RC, &TRC, P.SubReg);
1101 /// \brief Create RegSubRegPair from a register MachineOperand
1103 TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O) {
1105 return TargetInstrInfo::RegSubRegPair(O.getReg(), O.getSubReg());
1108 /// \brief Return the SubReg component from REG_SEQUENCE
1109 TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI,
1112 /// \brief Return the defining instruction for a given reg:subreg pair
1113 /// skipping copy like instructions and subreg-manipulation pseudos.
1114 /// Following another subreg of a reg:subreg isn't supported.
1115 MachineInstr *getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P,
1116 MachineRegisterInfo &MRI);
1118 /// \brief Return false if EXEC is not changed between the def of \p VReg at \p
1119 /// DefMI and the use at \p UseMI. Should be run on SSA. Currently does not
1120 /// attempt to track between blocks.
1121 bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI,
1123 const MachineInstr &DefMI,
1124 const MachineInstr &UseMI);
1126 /// \brief Return false if EXEC is not changed between the def of \p VReg at \p
1127 /// DefMI and all its uses. Should be run on SSA. Currently does not attempt to
1128 /// track between blocks.
1129 bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI,
1131 const MachineInstr &DefMI);
1136 int getVOPe64(uint16_t Opcode);
1139 int getVOPe32(uint16_t Opcode);
1142 int getSDWAOp(uint16_t Opcode);
1145 int getDPPOp32(uint16_t Opcode);
1148 int getBasicFromSDWAOp(uint16_t Opcode);
1151 int getCommuteRev(uint16_t Opcode);
1154 int getCommuteOrig(uint16_t Opcode);
1157 int getAddr64Inst(uint16_t Opcode);
1159 /// Check if \p Opcode is an Addr64 opcode.
1161 /// \returns \p Opcode if it is an Addr64 opcode, otherwise -1.
1163 int getIfAddr64Inst(uint16_t Opcode);
1166 int getMUBUFNoLdsInst(uint16_t Opcode);
1169 int getAtomicRetOp(uint16_t Opcode);
1172 int getAtomicNoRetOp(uint16_t Opcode);
1175 int getSOPKOp(uint16_t Opcode);
1178 int getGlobalSaddrOp(uint16_t Opcode);
1181 int getVCMPXNoSDstOp(uint16_t Opcode);
1184 int getFlatScratchInstSTfromSS(uint16_t Opcode);
1187 int getFlatScratchInstSSfromSV(uint16_t Opcode);
1189 const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
1190 const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
1191 const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
1192 const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
1194 } // end namespace AMDGPU
1197 namespace KernelInputOffsets {
1199 /// Offsets in bytes from the start of the input buffer
1212 } // end namespace KernelInputOffsets
1213 } // end namespace SI
1215 } // end namespace llvm
1217 #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H