1 //===- SIInstrInfo.h - SI Instruction Info Interface ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Interface definition for SIInstrInfo.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
16 #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
18 #include "AMDGPUInstrInfo.h"
19 #include "SIDefines.h"
20 #include "SIRegisterInfo.h"
21 #include "Utils/AMDGPUBaseInfo.h"
22 #include "llvm/ADT/ArrayRef.h"
23 #include "llvm/ADT/SetVector.h"
24 #include "llvm/CodeGen/MachineBasicBlock.h"
25 #include "llvm/CodeGen/MachineFunction.h"
26 #include "llvm/CodeGen/MachineInstr.h"
27 #include "llvm/CodeGen/MachineInstrBuilder.h"
28 #include "llvm/CodeGen/MachineOperand.h"
29 #include "llvm/MC/MCInstrDesc.h"
30 #include "llvm/Support/Compiler.h"
37 class MachineRegisterInfo;
40 class TargetRegisterClass;
42 class SIInstrInfo final : public AMDGPUInstrInfo {
44 const SIRegisterInfo RI;
45 const SISubtarget &ST;
47 // The the inverse predicate should have the negative value.
48 enum BranchPredicate {
58 using SetVectorType = SmallSetVector<MachineInstr *, 32>;
60 static unsigned getBranchOpcode(BranchPredicate Cond);
61 static BranchPredicate getBranchPredicate(unsigned Opcode);
64 unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
65 MachineRegisterInfo &MRI,
66 MachineOperand &SuperReg,
67 const TargetRegisterClass *SuperRC,
69 const TargetRegisterClass *SubRC) const;
70 MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
71 MachineRegisterInfo &MRI,
72 MachineOperand &SuperReg,
73 const TargetRegisterClass *SuperRC,
75 const TargetRegisterClass *SubRC) const;
77 void swapOperands(MachineInstr &Inst) const;
79 bool moveScalarAddSub(SetVectorType &Worklist,
80 MachineInstr &Inst) const;
82 void lowerScalarAbs(SetVectorType &Worklist,
83 MachineInstr &Inst) const;
85 void lowerScalarXnor(SetVectorType &Worklist,
86 MachineInstr &Inst) const;
88 void splitScalar64BitUnaryOp(SetVectorType &Worklist,
89 MachineInstr &Inst, unsigned Opcode) const;
91 void splitScalar64BitAddSub(SetVectorType &Worklist,
92 MachineInstr &Inst) const;
94 void splitScalar64BitBinaryOp(SetVectorType &Worklist,
95 MachineInstr &Inst, unsigned Opcode) const;
97 void splitScalar64BitBCNT(SetVectorType &Worklist,
98 MachineInstr &Inst) const;
99 void splitScalar64BitBFE(SetVectorType &Worklist,
100 MachineInstr &Inst) const;
101 void movePackToVALU(SetVectorType &Worklist,
102 MachineRegisterInfo &MRI,
103 MachineInstr &Inst) const;
105 void addUsersToMoveToVALUWorklist(unsigned Reg, MachineRegisterInfo &MRI,
106 SetVectorType &Worklist) const;
109 addSCCDefUsersToVALUWorklist(MachineInstr &SCCDefInst,
110 SetVectorType &Worklist) const;
112 const TargetRegisterClass *
113 getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
115 bool checkInstOffsetsDoNotOverlap(MachineInstr &MIa, MachineInstr &MIb) const;
117 unsigned findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
120 bool swapSourceModifiers(MachineInstr &MI,
121 MachineOperand &Src0, unsigned Src0OpName,
122 MachineOperand &Src1, unsigned Src1OpName) const;
124 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
126 unsigned OpIdx1) const override;
129 enum TargetOperandFlags {
133 // MO_GOTPCREL -> symbol@GOTPCREL -> R_AMDGPU_GOTPCREL.
135 // MO_GOTPCREL32_LO -> symbol@gotpcrel32@lo -> R_AMDGPU_GOTPCREL32_LO.
137 MO_GOTPCREL32_LO = 2,
138 // MO_GOTPCREL32_HI -> symbol@gotpcrel32@hi -> R_AMDGPU_GOTPCREL32_HI.
139 MO_GOTPCREL32_HI = 3,
140 // MO_REL32_LO -> symbol@rel32@lo -> R_AMDGPU_REL32_LO.
143 // MO_REL32_HI -> symbol@rel32@hi -> R_AMDGPU_REL32_HI.
147 explicit SIInstrInfo(const SISubtarget &ST);
149 const SIRegisterInfo &getRegisterInfo() const {
153 bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
154 AliasAnalysis *AA) const override;
156 bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
158 int64_t &Offset2) const override;
160 bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
162 const TargetRegisterInfo *TRI) const final;
164 bool shouldClusterMemOps(MachineInstr &FirstLdSt, unsigned BaseReg1,
165 MachineInstr &SecondLdSt, unsigned BaseReg2,
166 unsigned NumLoads) const final;
168 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
169 const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
170 bool KillSrc) const override;
172 unsigned calculateLDSSpillAddress(MachineBasicBlock &MBB, MachineInstr &MI,
173 RegScavenger *RS, unsigned TmpReg,
174 unsigned Offset, unsigned Size) const;
176 void materializeImmediate(MachineBasicBlock &MBB,
177 MachineBasicBlock::iterator MI,
180 int64_t Value) const;
182 const TargetRegisterClass *getPreferredSelectRegClass(
183 unsigned Size) const;
185 unsigned insertNE(MachineBasicBlock *MBB,
186 MachineBasicBlock::iterator I, const DebugLoc &DL,
187 unsigned SrcReg, int Value) const;
189 unsigned insertEQ(MachineBasicBlock *MBB,
190 MachineBasicBlock::iterator I, const DebugLoc &DL,
191 unsigned SrcReg, int Value) const;
193 void storeRegToStackSlot(MachineBasicBlock &MBB,
194 MachineBasicBlock::iterator MI, unsigned SrcReg,
195 bool isKill, int FrameIndex,
196 const TargetRegisterClass *RC,
197 const TargetRegisterInfo *TRI) const override;
199 void loadRegFromStackSlot(MachineBasicBlock &MBB,
200 MachineBasicBlock::iterator MI, unsigned DestReg,
201 int FrameIndex, const TargetRegisterClass *RC,
202 const TargetRegisterInfo *TRI) const override;
204 bool expandPostRAPseudo(MachineInstr &MI) const override;
206 // \brief Returns an opcode that can be used to move a value to a \p DstRC
207 // register. If there is no hardware instruction that can store to \p
208 // DstRC, then AMDGPU::COPY is returned.
209 unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
212 int commuteOpcode(unsigned Opc) const;
215 inline int commuteOpcode(const MachineInstr &MI) const {
216 return commuteOpcode(MI.getOpcode());
219 bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
220 unsigned &SrcOpIdx2) const override;
222 bool isBranchOffsetInRange(unsigned BranchOpc,
223 int64_t BrOffset) const override;
225 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
227 unsigned insertIndirectBranch(MachineBasicBlock &MBB,
228 MachineBasicBlock &NewDestBB,
231 RegScavenger *RS = nullptr) const override;
233 bool analyzeBranchImpl(MachineBasicBlock &MBB,
234 MachineBasicBlock::iterator I,
235 MachineBasicBlock *&TBB,
236 MachineBasicBlock *&FBB,
237 SmallVectorImpl<MachineOperand> &Cond,
238 bool AllowModify) const;
240 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
241 MachineBasicBlock *&FBB,
242 SmallVectorImpl<MachineOperand> &Cond,
243 bool AllowModify = false) const override;
245 unsigned removeBranch(MachineBasicBlock &MBB,
246 int *BytesRemoved = nullptr) const override;
248 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
249 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
251 int *BytesAdded = nullptr) const override;
253 bool reverseBranchCondition(
254 SmallVectorImpl<MachineOperand> &Cond) const override;
256 bool canInsertSelect(const MachineBasicBlock &MBB,
257 ArrayRef<MachineOperand> Cond,
258 unsigned TrueReg, unsigned FalseReg,
260 int &TrueCycles, int &FalseCycles) const override;
262 void insertSelect(MachineBasicBlock &MBB,
263 MachineBasicBlock::iterator I, const DebugLoc &DL,
264 unsigned DstReg, ArrayRef<MachineOperand> Cond,
265 unsigned TrueReg, unsigned FalseReg) const override;
267 void insertVectorSelect(MachineBasicBlock &MBB,
268 MachineBasicBlock::iterator I, const DebugLoc &DL,
269 unsigned DstReg, ArrayRef<MachineOperand> Cond,
270 unsigned TrueReg, unsigned FalseReg) const;
272 unsigned getAddressSpaceForPseudoSourceKind(
273 PseudoSourceValue::PSVKind Kind) const override;
276 areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
277 AliasAnalysis *AA = nullptr) const override;
279 bool isFoldableCopy(const MachineInstr &MI) const;
281 bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg,
282 MachineRegisterInfo *MRI) const final;
284 unsigned getMachineCSELookAheadLimit() const override { return 500; }
286 MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
288 LiveVariables *LV) const override;
290 bool isSchedulingBoundary(const MachineInstr &MI,
291 const MachineBasicBlock *MBB,
292 const MachineFunction &MF) const override;
294 static bool isSALU(const MachineInstr &MI) {
295 return MI.getDesc().TSFlags & SIInstrFlags::SALU;
298 bool isSALU(uint16_t Opcode) const {
299 return get(Opcode).TSFlags & SIInstrFlags::SALU;
302 static bool isVALU(const MachineInstr &MI) {
303 return MI.getDesc().TSFlags & SIInstrFlags::VALU;
306 bool isVALU(uint16_t Opcode) const {
307 return get(Opcode).TSFlags & SIInstrFlags::VALU;
310 static bool isVMEM(const MachineInstr &MI) {
311 return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
314 bool isVMEM(uint16_t Opcode) const {
315 return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
318 static bool isSOP1(const MachineInstr &MI) {
319 return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
322 bool isSOP1(uint16_t Opcode) const {
323 return get(Opcode).TSFlags & SIInstrFlags::SOP1;
326 static bool isSOP2(const MachineInstr &MI) {
327 return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
330 bool isSOP2(uint16_t Opcode) const {
331 return get(Opcode).TSFlags & SIInstrFlags::SOP2;
334 static bool isSOPC(const MachineInstr &MI) {
335 return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
338 bool isSOPC(uint16_t Opcode) const {
339 return get(Opcode).TSFlags & SIInstrFlags::SOPC;
342 static bool isSOPK(const MachineInstr &MI) {
343 return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
346 bool isSOPK(uint16_t Opcode) const {
347 return get(Opcode).TSFlags & SIInstrFlags::SOPK;
350 static bool isSOPP(const MachineInstr &MI) {
351 return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
354 bool isSOPP(uint16_t Opcode) const {
355 return get(Opcode).TSFlags & SIInstrFlags::SOPP;
358 static bool isVOP1(const MachineInstr &MI) {
359 return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
362 bool isVOP1(uint16_t Opcode) const {
363 return get(Opcode).TSFlags & SIInstrFlags::VOP1;
366 static bool isVOP2(const MachineInstr &MI) {
367 return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
370 bool isVOP2(uint16_t Opcode) const {
371 return get(Opcode).TSFlags & SIInstrFlags::VOP2;
374 static bool isVOP3(const MachineInstr &MI) {
375 return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
378 bool isVOP3(uint16_t Opcode) const {
379 return get(Opcode).TSFlags & SIInstrFlags::VOP3;
382 static bool isSDWA(const MachineInstr &MI) {
383 return MI.getDesc().TSFlags & SIInstrFlags::SDWA;
386 bool isSDWA(uint16_t Opcode) const {
387 return get(Opcode).TSFlags & SIInstrFlags::SDWA;
390 static bool isVOPC(const MachineInstr &MI) {
391 return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
394 bool isVOPC(uint16_t Opcode) const {
395 return get(Opcode).TSFlags & SIInstrFlags::VOPC;
398 static bool isMUBUF(const MachineInstr &MI) {
399 return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
402 bool isMUBUF(uint16_t Opcode) const {
403 return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
406 static bool isMTBUF(const MachineInstr &MI) {
407 return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
410 bool isMTBUF(uint16_t Opcode) const {
411 return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
414 static bool isSMRD(const MachineInstr &MI) {
415 return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
418 bool isSMRD(uint16_t Opcode) const {
419 return get(Opcode).TSFlags & SIInstrFlags::SMRD;
422 bool isBufferSMRD(const MachineInstr &MI) const {
426 // Check that it is using a buffer resource.
427 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
428 if (Idx == -1) // e.g. s_memtime
431 const auto RCID = MI.getDesc().OpInfo[Idx].RegClass;
432 return RCID == AMDGPU::SReg_128RegClassID;
435 static bool isDS(const MachineInstr &MI) {
436 return MI.getDesc().TSFlags & SIInstrFlags::DS;
439 bool isDS(uint16_t Opcode) const {
440 return get(Opcode).TSFlags & SIInstrFlags::DS;
443 static bool isMIMG(const MachineInstr &MI) {
444 return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
447 bool isMIMG(uint16_t Opcode) const {
448 return get(Opcode).TSFlags & SIInstrFlags::MIMG;
451 static bool isGather4(const MachineInstr &MI) {
452 return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
455 bool isGather4(uint16_t Opcode) const {
456 return get(Opcode).TSFlags & SIInstrFlags::Gather4;
459 static bool isFLAT(const MachineInstr &MI) {
460 return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
463 // Is a FLAT encoded instruction which accesses a specific segment,
464 // i.e. global_* or scratch_*.
465 static bool isSegmentSpecificFLAT(const MachineInstr &MI) {
466 auto Flags = MI.getDesc().TSFlags;
467 return (Flags & SIInstrFlags::FLAT) && !(Flags & SIInstrFlags::LGKM_CNT);
470 // Any FLAT encoded instruction, including global_* and scratch_*.
471 bool isFLAT(uint16_t Opcode) const {
472 return get(Opcode).TSFlags & SIInstrFlags::FLAT;
475 static bool isEXP(const MachineInstr &MI) {
476 return MI.getDesc().TSFlags & SIInstrFlags::EXP;
479 bool isEXP(uint16_t Opcode) const {
480 return get(Opcode).TSFlags & SIInstrFlags::EXP;
483 static bool isWQM(const MachineInstr &MI) {
484 return MI.getDesc().TSFlags & SIInstrFlags::WQM;
487 bool isWQM(uint16_t Opcode) const {
488 return get(Opcode).TSFlags & SIInstrFlags::WQM;
491 static bool isDisableWQM(const MachineInstr &MI) {
492 return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM;
495 bool isDisableWQM(uint16_t Opcode) const {
496 return get(Opcode).TSFlags & SIInstrFlags::DisableWQM;
499 static bool isVGPRSpill(const MachineInstr &MI) {
500 return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
503 bool isVGPRSpill(uint16_t Opcode) const {
504 return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
507 static bool isSGPRSpill(const MachineInstr &MI) {
508 return MI.getDesc().TSFlags & SIInstrFlags::SGPRSpill;
511 bool isSGPRSpill(uint16_t Opcode) const {
512 return get(Opcode).TSFlags & SIInstrFlags::SGPRSpill;
515 static bool isDPP(const MachineInstr &MI) {
516 return MI.getDesc().TSFlags & SIInstrFlags::DPP;
519 bool isDPP(uint16_t Opcode) const {
520 return get(Opcode).TSFlags & SIInstrFlags::DPP;
523 static bool isVOP3P(const MachineInstr &MI) {
524 return MI.getDesc().TSFlags & SIInstrFlags::VOP3P;
527 bool isVOP3P(uint16_t Opcode) const {
528 return get(Opcode).TSFlags & SIInstrFlags::VOP3P;
531 static bool isVINTRP(const MachineInstr &MI) {
532 return MI.getDesc().TSFlags & SIInstrFlags::VINTRP;
535 bool isVINTRP(uint16_t Opcode) const {
536 return get(Opcode).TSFlags & SIInstrFlags::VINTRP;
539 static bool isScalarUnit(const MachineInstr &MI) {
540 return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
543 static bool usesVM_CNT(const MachineInstr &MI) {
544 return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
547 static bool usesLGKM_CNT(const MachineInstr &MI) {
548 return MI.getDesc().TSFlags & SIInstrFlags::LGKM_CNT;
551 static bool sopkIsZext(const MachineInstr &MI) {
552 return MI.getDesc().TSFlags & SIInstrFlags::SOPK_ZEXT;
555 bool sopkIsZext(uint16_t Opcode) const {
556 return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT;
559 /// \returns true if this is an s_store_dword* instruction. This is more
560 /// specific than than isSMEM && mayStore.
561 static bool isScalarStore(const MachineInstr &MI) {
562 return MI.getDesc().TSFlags & SIInstrFlags::SCALAR_STORE;
565 bool isScalarStore(uint16_t Opcode) const {
566 return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE;
569 static bool isFixedSize(const MachineInstr &MI) {
570 return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE;
573 bool isFixedSize(uint16_t Opcode) const {
574 return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE;
577 static bool hasFPClamp(const MachineInstr &MI) {
578 return MI.getDesc().TSFlags & SIInstrFlags::FPClamp;
581 bool hasFPClamp(uint16_t Opcode) const {
582 return get(Opcode).TSFlags & SIInstrFlags::FPClamp;
585 static bool hasIntClamp(const MachineInstr &MI) {
586 return MI.getDesc().TSFlags & SIInstrFlags::IntClamp;
589 uint64_t getClampMask(const MachineInstr &MI) const {
590 const uint64_t ClampFlags = SIInstrFlags::FPClamp |
591 SIInstrFlags::IntClamp |
592 SIInstrFlags::ClampLo |
593 SIInstrFlags::ClampHi;
594 return MI.getDesc().TSFlags & ClampFlags;
597 bool isVGPRCopy(const MachineInstr &MI) const {
599 unsigned Dest = MI.getOperand(0).getReg();
600 const MachineFunction &MF = *MI.getParent()->getParent();
601 const MachineRegisterInfo &MRI = MF.getRegInfo();
602 return !RI.isSGPRReg(MRI, Dest);
605 bool isInlineConstant(const APInt &Imm) const;
607 bool isInlineConstant(const MachineOperand &MO, uint8_t OperandType) const;
609 bool isInlineConstant(const MachineOperand &MO,
610 const MCOperandInfo &OpInfo) const {
611 return isInlineConstant(MO, OpInfo.OperandType);
614 /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would
615 /// be an inline immediate.
616 bool isInlineConstant(const MachineInstr &MI,
617 const MachineOperand &UseMO,
618 const MachineOperand &DefMO) const {
619 assert(UseMO.getParent() == &MI);
620 int OpIdx = MI.getOperandNo(&UseMO);
621 if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) {
625 return isInlineConstant(DefMO, MI.getDesc().OpInfo[OpIdx]);
628 /// \p returns true if the operand \p OpIdx in \p MI is a valid inline
630 bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx) const {
631 const MachineOperand &MO = MI.getOperand(OpIdx);
632 return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
635 bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx,
636 const MachineOperand &MO) const {
637 if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands)
641 unsigned Size = getOpSize(MI, OpIdx);
642 assert(Size == 8 || Size == 4);
644 uint8_t OpType = (Size == 8) ?
645 AMDGPU::OPERAND_REG_IMM_INT64 : AMDGPU::OPERAND_REG_IMM_INT32;
646 return isInlineConstant(MO, OpType);
649 return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType);
652 bool isInlineConstant(const MachineOperand &MO) const {
653 const MachineInstr *Parent = MO.getParent();
654 return isInlineConstant(*Parent, Parent->getOperandNo(&MO));
657 bool isLiteralConstant(const MachineOperand &MO,
658 const MCOperandInfo &OpInfo) const {
659 return MO.isImm() && !isInlineConstant(MO, OpInfo.OperandType);
662 bool isLiteralConstant(const MachineInstr &MI, int OpIdx) const {
663 const MachineOperand &MO = MI.getOperand(OpIdx);
664 return MO.isImm() && !isInlineConstant(MI, OpIdx);
667 // Returns true if this operand could potentially require a 32-bit literal
668 // operand, but not necessarily. A FrameIndex for example could resolve to an
669 // inline immediate value that will not require an additional 4-bytes; this
670 // assumes that it will.
671 bool isLiteralConstantLike(const MachineOperand &MO,
672 const MCOperandInfo &OpInfo) const;
674 bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
675 const MachineOperand &MO) const;
677 /// \brief Return true if this 64-bit VALU instruction has a 32-bit encoding.
678 /// This function will return false if you pass it a 32-bit instruction.
679 bool hasVALU32BitEncoding(unsigned Opcode) const;
681 /// \brief Returns true if this operand uses the constant bus.
682 bool usesConstantBus(const MachineRegisterInfo &MRI,
683 const MachineOperand &MO,
684 const MCOperandInfo &OpInfo) const;
686 /// \brief Return true if this instruction has any modifiers.
687 /// e.g. src[012]_mod, omod, clamp.
688 bool hasModifiers(unsigned Opcode) const;
690 bool hasModifiersSet(const MachineInstr &MI,
691 unsigned OpName) const;
692 bool hasAnyModifiersSet(const MachineInstr &MI) const;
694 bool verifyInstruction(const MachineInstr &MI,
695 StringRef &ErrInfo) const override;
697 unsigned getVALUOp(const MachineInstr &MI) const;
699 /// \brief Return the correct register class for \p OpNo. For target-specific
700 /// instructions, this will return the register class that has been defined
701 /// in tablegen. For generic instructions, like REG_SEQUENCE it will return
702 /// the register class of its machine operand.
703 /// to infer the correct register class base on the other operands.
704 const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
705 unsigned OpNo) const;
707 /// \brief Return the size in bytes of the operand OpNo on the given
708 // instruction opcode.
709 unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
710 const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
712 if (OpInfo.RegClass == -1) {
713 // If this is an immediate operand, this must be a 32-bit literal.
714 assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
718 return RI.getRegSizeInBits(*RI.getRegClass(OpInfo.RegClass)) / 8;
721 /// \brief This form should usually be preferred since it handles operands
722 /// with unknown register classes.
723 unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
724 return RI.getRegSizeInBits(*getOpRegClass(MI, OpNo)) / 8;
727 /// \returns true if it is legal for the operand at index \p OpNo
729 bool canReadVGPR(const MachineInstr &MI, unsigned OpNo) const;
731 /// \brief Legalize the \p OpIndex operand of this instruction by inserting
732 /// a MOV. For example:
733 /// ADD_I32_e32 VGPR0, 15
736 /// ADD_I32_e32 VGPR0, VGPR1
738 /// If the operand being legalized is a register, then a COPY will be used
740 void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
742 /// \brief Check if \p MO is a legal operand if it was the \p OpIdx Operand
744 bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
745 const MachineOperand *MO = nullptr) const;
747 /// \brief Check if \p MO would be a valid operand for the given operand
748 /// definition \p OpInfo. Note this does not attempt to validate constant bus
749 /// restrictions (e.g. literal constant usage).
750 bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
751 const MCOperandInfo &OpInfo,
752 const MachineOperand &MO) const;
754 /// \brief Check if \p MO (a register operand) is a legal register for the
755 /// given operand description.
756 bool isLegalRegOperand(const MachineRegisterInfo &MRI,
757 const MCOperandInfo &OpInfo,
758 const MachineOperand &MO) const;
760 /// \brief Legalize operands in \p MI by either commuting it or inserting a
762 void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
764 /// \brief Fix operands in \p MI to satisfy constant bus requirements.
765 void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
767 /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
768 /// be used when it is know that the value in SrcReg is same across all
769 /// threads in the wave.
770 /// \returns The SGPR register that \p SrcReg was copied to.
771 unsigned readlaneVGPRToSGPR(unsigned SrcReg, MachineInstr &UseMI,
772 MachineRegisterInfo &MRI) const;
774 void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
776 void legalizeGenericOperand(MachineBasicBlock &InsertMBB,
777 MachineBasicBlock::iterator I,
778 const TargetRegisterClass *DstRC,
779 MachineOperand &Op, MachineRegisterInfo &MRI,
780 const DebugLoc &DL) const;
782 /// \brief Legalize all operands in this instruction. This function may
783 /// create new instruction and insert them before \p MI.
784 void legalizeOperands(MachineInstr &MI) const;
786 /// \brief Replace this instruction's opcode with the equivalent VALU
787 /// opcode. This function will also move the users of \p MI to the
788 /// VALU if necessary.
789 void moveToVALU(MachineInstr &MI) const;
791 void insertWaitStates(MachineBasicBlock &MBB,MachineBasicBlock::iterator MI,
794 void insertNoop(MachineBasicBlock &MBB,
795 MachineBasicBlock::iterator MI) const override;
797 void insertReturn(MachineBasicBlock &MBB) const;
798 /// \brief Return the number of wait states that result from executing this
800 unsigned getNumWaitStates(const MachineInstr &MI) const;
802 /// \brief Returns the operand named \p Op. If \p MI does not have an
803 /// operand named \c Op, this function returns nullptr.
805 MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
808 const MachineOperand *getNamedOperand(const MachineInstr &MI,
809 unsigned OpName) const {
810 return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
813 /// Get required immediate operand
814 int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
815 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
816 return MI.getOperand(Idx).getImm();
819 uint64_t getDefaultRsrcDataFormat() const;
820 uint64_t getScratchRsrcWords23() const;
822 bool isLowLatencyInstruction(const MachineInstr &MI) const;
823 bool isHighLatencyInstruction(const MachineInstr &MI) const;
825 /// \brief Return the descriptor of the target-specific machine instruction
826 /// that corresponds to the specified pseudo or native opcode.
827 const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
828 return get(pseudoToMCOpcode(Opcode));
831 unsigned isStackAccess(const MachineInstr &MI, int &FrameIndex) const;
832 unsigned isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex) const;
834 unsigned isLoadFromStackSlot(const MachineInstr &MI,
835 int &FrameIndex) const override;
836 unsigned isStoreToStackSlot(const MachineInstr &MI,
837 int &FrameIndex) const override;
839 unsigned getInstBundleSize(const MachineInstr &MI) const;
840 unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
842 bool mayAccessFlatAddressSpace(const MachineInstr &MI) const;
844 bool isNonUniformBranchInstr(MachineInstr &Instr) const;
846 void convertNonUniformIfRegion(MachineBasicBlock *IfEntry,
847 MachineBasicBlock *IfEnd) const;
849 void convertNonUniformLoopRegion(MachineBasicBlock *LoopEntry,
850 MachineBasicBlock *LoopEnd) const;
852 std::pair<unsigned, unsigned>
853 decomposeMachineOperandsTargetFlags(unsigned TF) const override;
855 ArrayRef<std::pair<int, const char *>>
856 getSerializableTargetIndices() const override;
858 ArrayRef<std::pair<unsigned, const char *>>
859 getSerializableDirectMachineOperandTargetFlags() const override;
861 ScheduleHazardRecognizer *
862 CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
863 const ScheduleDAG *DAG) const override;
865 ScheduleHazardRecognizer *
866 CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
868 bool isBasicBlockPrologue(const MachineInstr &MI) const override;
870 /// \brief Return a partially built integer add instruction without carry.
871 /// Caller must add source operands.
872 /// For pre-GFX9 it will generate unused carry destination operand.
873 /// TODO: After GFX9 it should return a no-carry operation.
874 MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB,
875 MachineBasicBlock::iterator I,
877 unsigned DestReg) const;
879 static bool isKillTerminator(unsigned Opcode);
880 const MCInstrDesc &getKillTerminatorFromPseudo(unsigned Opcode) const;
882 static bool isLegalMUBUFImmOffset(unsigned Imm) {
883 return isUInt<12>(Imm);
890 int getVOPe64(uint16_t Opcode);
893 int getVOPe32(uint16_t Opcode);
896 int getSDWAOp(uint16_t Opcode);
899 int getBasicFromSDWAOp(uint16_t Opcode);
902 int getCommuteRev(uint16_t Opcode);
905 int getCommuteOrig(uint16_t Opcode);
908 int getAddr64Inst(uint16_t Opcode);
911 int getAtomicRetOp(uint16_t Opcode);
914 int getAtomicNoRetOp(uint16_t Opcode);
917 int getSOPKOp(uint16_t Opcode);
919 const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
920 const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
921 const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
922 const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
924 // For MachineOperands.
926 TF_LONG_BRANCH_FORWARD = 1 << 0,
927 TF_LONG_BRANCH_BACKWARD = 1 << 1
930 } // end namespace AMDGPU
933 namespace KernelInputOffsets {
935 /// Offsets in bytes from the start of the input buffer
948 } // end namespace KernelInputOffsets
949 } // end namespace SI
951 } // end namespace llvm
953 #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H