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 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
17 #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H
19 #include "AMDGPUInstrInfo.h"
20 #include "SIDefines.h"
21 #include "SIRegisterInfo.h"
25 class SIInstrInfo final : public AMDGPUInstrInfo {
27 const SIRegisterInfo RI;
28 const SISubtarget &ST;
30 // The the inverse predicate should have the negative value.
31 enum BranchPredicate {
41 static unsigned getBranchOpcode(BranchPredicate Cond);
42 static BranchPredicate getBranchPredicate(unsigned Opcode);
44 unsigned buildExtractSubReg(MachineBasicBlock::iterator MI,
45 MachineRegisterInfo &MRI,
46 MachineOperand &SuperReg,
47 const TargetRegisterClass *SuperRC,
49 const TargetRegisterClass *SubRC) const;
50 MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI,
51 MachineRegisterInfo &MRI,
52 MachineOperand &SuperReg,
53 const TargetRegisterClass *SuperRC,
55 const TargetRegisterClass *SubRC) const;
57 void swapOperands(MachineInstr &Inst) const;
59 void lowerScalarAbs(SmallVectorImpl<MachineInstr *> &Worklist,
60 MachineInstr &Inst) const;
62 void splitScalar64BitUnaryOp(SmallVectorImpl<MachineInstr *> &Worklist,
63 MachineInstr &Inst, unsigned Opcode) const;
65 void splitScalar64BitBinaryOp(SmallVectorImpl<MachineInstr *> &Worklist,
66 MachineInstr &Inst, unsigned Opcode) const;
68 void splitScalar64BitBCNT(SmallVectorImpl<MachineInstr *> &Worklist,
69 MachineInstr &Inst) const;
70 void splitScalar64BitBFE(SmallVectorImpl<MachineInstr *> &Worklist,
71 MachineInstr &Inst) const;
73 void addUsersToMoveToVALUWorklist(
74 unsigned Reg, MachineRegisterInfo &MRI,
75 SmallVectorImpl<MachineInstr *> &Worklist) const;
78 addSCCDefUsersToVALUWorklist(MachineInstr &SCCDefInst,
79 SmallVectorImpl<MachineInstr *> &Worklist) const;
81 const TargetRegisterClass *
82 getDestEquivalentVGPRClass(const MachineInstr &Inst) const;
84 bool checkInstOffsetsDoNotOverlap(MachineInstr &MIa, MachineInstr &MIb) const;
86 unsigned findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const;
89 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
91 unsigned OpIdx1) const override;
95 enum TargetOperandFlags {
100 explicit SIInstrInfo(const SISubtarget &);
102 const SIRegisterInfo &getRegisterInfo() const {
106 bool isReallyTriviallyReMaterializable(const MachineInstr &MI,
107 AliasAnalysis *AA) const override;
109 bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
111 int64_t &Offset2) const override;
113 bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg,
115 const TargetRegisterInfo *TRI) const final;
117 bool shouldClusterMemOps(MachineInstr &FirstLdSt, MachineInstr &SecondLdSt,
118 unsigned NumLoads) const final;
120 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
121 const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
122 bool KillSrc) const override;
124 unsigned calculateLDSSpillAddress(MachineBasicBlock &MBB, MachineInstr &MI,
125 RegScavenger *RS, unsigned TmpReg,
126 unsigned Offset, unsigned Size) const;
128 void storeRegToStackSlot(MachineBasicBlock &MBB,
129 MachineBasicBlock::iterator MI, unsigned SrcReg,
130 bool isKill, int FrameIndex,
131 const TargetRegisterClass *RC,
132 const TargetRegisterInfo *TRI) const override;
134 void loadRegFromStackSlot(MachineBasicBlock &MBB,
135 MachineBasicBlock::iterator MI, unsigned DestReg,
136 int FrameIndex, const TargetRegisterClass *RC,
137 const TargetRegisterInfo *TRI) const override;
139 bool expandPostRAPseudo(MachineInstr &MI) const override;
141 // \brief Returns an opcode that can be used to move a value to a \p DstRC
142 // register. If there is no hardware instruction that can store to \p
143 // DstRC, then AMDGPU::COPY is returned.
144 unsigned getMovOpcode(const TargetRegisterClass *DstRC) const;
147 int commuteOpcode(const MachineInstr &MI) const;
149 bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1,
150 unsigned &SrcOpIdx2) const override;
152 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
153 MachineBasicBlock *&FBB,
154 SmallVectorImpl<MachineOperand> &Cond,
155 bool AllowModify) const override;
157 unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
159 unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
160 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
161 const DebugLoc &DL) const override;
163 bool ReverseBranchCondition(
164 SmallVectorImpl<MachineOperand> &Cond) const override;
167 areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
168 AliasAnalysis *AA = nullptr) const override;
170 bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, unsigned Reg,
171 MachineRegisterInfo *MRI) const final;
173 unsigned getMachineCSELookAheadLimit() const override { return 500; }
175 MachineInstr *convertToThreeAddress(MachineFunction::iterator &MBB,
177 LiveVariables *LV) const override;
179 bool isSchedulingBoundary(const MachineInstr &MI,
180 const MachineBasicBlock *MBB,
181 const MachineFunction &MF) const override;
183 static bool isSALU(const MachineInstr &MI) {
184 return MI.getDesc().TSFlags & SIInstrFlags::SALU;
187 bool isSALU(uint16_t Opcode) const {
188 return get(Opcode).TSFlags & SIInstrFlags::SALU;
191 static bool isVALU(const MachineInstr &MI) {
192 return MI.getDesc().TSFlags & SIInstrFlags::VALU;
195 bool isVALU(uint16_t Opcode) const {
196 return get(Opcode).TSFlags & SIInstrFlags::VALU;
199 static bool isVMEM(const MachineInstr &MI) {
200 return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI);
203 bool isVMEM(uint16_t Opcode) const {
204 return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode);
207 static bool isSOP1(const MachineInstr &MI) {
208 return MI.getDesc().TSFlags & SIInstrFlags::SOP1;
211 bool isSOP1(uint16_t Opcode) const {
212 return get(Opcode).TSFlags & SIInstrFlags::SOP1;
215 static bool isSOP2(const MachineInstr &MI) {
216 return MI.getDesc().TSFlags & SIInstrFlags::SOP2;
219 bool isSOP2(uint16_t Opcode) const {
220 return get(Opcode).TSFlags & SIInstrFlags::SOP2;
223 static bool isSOPC(const MachineInstr &MI) {
224 return MI.getDesc().TSFlags & SIInstrFlags::SOPC;
227 bool isSOPC(uint16_t Opcode) const {
228 return get(Opcode).TSFlags & SIInstrFlags::SOPC;
231 static bool isSOPK(const MachineInstr &MI) {
232 return MI.getDesc().TSFlags & SIInstrFlags::SOPK;
235 bool isSOPK(uint16_t Opcode) const {
236 return get(Opcode).TSFlags & SIInstrFlags::SOPK;
239 static bool isSOPP(const MachineInstr &MI) {
240 return MI.getDesc().TSFlags & SIInstrFlags::SOPP;
243 bool isSOPP(uint16_t Opcode) const {
244 return get(Opcode).TSFlags & SIInstrFlags::SOPP;
247 static bool isVOP1(const MachineInstr &MI) {
248 return MI.getDesc().TSFlags & SIInstrFlags::VOP1;
251 bool isVOP1(uint16_t Opcode) const {
252 return get(Opcode).TSFlags & SIInstrFlags::VOP1;
255 static bool isVOP2(const MachineInstr &MI) {
256 return MI.getDesc().TSFlags & SIInstrFlags::VOP2;
259 bool isVOP2(uint16_t Opcode) const {
260 return get(Opcode).TSFlags & SIInstrFlags::VOP2;
263 static bool isVOP3(const MachineInstr &MI) {
264 return MI.getDesc().TSFlags & SIInstrFlags::VOP3;
267 bool isVOP3(uint16_t Opcode) const {
268 return get(Opcode).TSFlags & SIInstrFlags::VOP3;
271 static bool isVOPC(const MachineInstr &MI) {
272 return MI.getDesc().TSFlags & SIInstrFlags::VOPC;
275 bool isVOPC(uint16_t Opcode) const {
276 return get(Opcode).TSFlags & SIInstrFlags::VOPC;
279 static bool isMUBUF(const MachineInstr &MI) {
280 return MI.getDesc().TSFlags & SIInstrFlags::MUBUF;
283 bool isMUBUF(uint16_t Opcode) const {
284 return get(Opcode).TSFlags & SIInstrFlags::MUBUF;
287 static bool isMTBUF(const MachineInstr &MI) {
288 return MI.getDesc().TSFlags & SIInstrFlags::MTBUF;
291 bool isMTBUF(uint16_t Opcode) const {
292 return get(Opcode).TSFlags & SIInstrFlags::MTBUF;
295 static bool isSMRD(const MachineInstr &MI) {
296 return MI.getDesc().TSFlags & SIInstrFlags::SMRD;
299 bool isSMRD(uint16_t Opcode) const {
300 return get(Opcode).TSFlags & SIInstrFlags::SMRD;
303 static bool isDS(const MachineInstr &MI) {
304 return MI.getDesc().TSFlags & SIInstrFlags::DS;
307 bool isDS(uint16_t Opcode) const {
308 return get(Opcode).TSFlags & SIInstrFlags::DS;
311 static bool isMIMG(const MachineInstr &MI) {
312 return MI.getDesc().TSFlags & SIInstrFlags::MIMG;
315 bool isMIMG(uint16_t Opcode) const {
316 return get(Opcode).TSFlags & SIInstrFlags::MIMG;
319 static bool isGather4(const MachineInstr &MI) {
320 return MI.getDesc().TSFlags & SIInstrFlags::Gather4;
323 bool isGather4(uint16_t Opcode) const {
324 return get(Opcode).TSFlags & SIInstrFlags::Gather4;
327 static bool isFLAT(const MachineInstr &MI) {
328 return MI.getDesc().TSFlags & SIInstrFlags::FLAT;
331 bool isFLAT(uint16_t Opcode) const {
332 return get(Opcode).TSFlags & SIInstrFlags::FLAT;
335 static bool isWQM(const MachineInstr &MI) {
336 return MI.getDesc().TSFlags & SIInstrFlags::WQM;
339 bool isWQM(uint16_t Opcode) const {
340 return get(Opcode).TSFlags & SIInstrFlags::WQM;
343 static bool isDisableWQM(const MachineInstr &MI) {
344 return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM;
347 bool isDisableWQM(uint16_t Opcode) const {
348 return get(Opcode).TSFlags & SIInstrFlags::DisableWQM;
351 static bool isVGPRSpill(const MachineInstr &MI) {
352 return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill;
355 bool isVGPRSpill(uint16_t Opcode) const {
356 return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill;
359 static bool isDPP(const MachineInstr &MI) {
360 return MI.getDesc().TSFlags & SIInstrFlags::DPP;
363 bool isDPP(uint16_t Opcode) const {
364 return get(Opcode).TSFlags & SIInstrFlags::DPP;
367 static bool isScalarUnit(const MachineInstr &MI) {
368 return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD);
371 static bool usesVM_CNT(const MachineInstr &MI) {
372 return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT;
375 bool isVGPRCopy(const MachineInstr &MI) const {
377 unsigned Dest = MI.getOperand(0).getReg();
378 const MachineFunction &MF = *MI.getParent()->getParent();
379 const MachineRegisterInfo &MRI = MF.getRegInfo();
380 return !RI.isSGPRReg(MRI, Dest);
383 bool isInlineConstant(const APInt &Imm) const;
384 bool isInlineConstant(const MachineOperand &MO, unsigned OpSize) const;
385 bool isLiteralConstant(const MachineOperand &MO, unsigned OpSize) const;
387 bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo,
388 const MachineOperand &MO) const;
390 /// \brief Return true if this 64-bit VALU instruction has a 32-bit encoding.
391 /// This function will return false if you pass it a 32-bit instruction.
392 bool hasVALU32BitEncoding(unsigned Opcode) const;
394 /// \brief Returns true if this operand uses the constant bus.
395 bool usesConstantBus(const MachineRegisterInfo &MRI,
396 const MachineOperand &MO,
397 unsigned OpSize) const;
399 /// \brief Return true if this instruction has any modifiers.
400 /// e.g. src[012]_mod, omod, clamp.
401 bool hasModifiers(unsigned Opcode) const;
403 bool hasModifiersSet(const MachineInstr &MI,
404 unsigned OpName) const;
406 bool verifyInstruction(const MachineInstr &MI,
407 StringRef &ErrInfo) const override;
409 static unsigned getVALUOp(const MachineInstr &MI);
411 bool isSALUOpSupportedOnVALU(const MachineInstr &MI) const;
413 /// \brief Return the correct register class for \p OpNo. For target-specific
414 /// instructions, this will return the register class that has been defined
415 /// in tablegen. For generic instructions, like REG_SEQUENCE it will return
416 /// the register class of its machine operand.
417 /// to infer the correct register class base on the other operands.
418 const TargetRegisterClass *getOpRegClass(const MachineInstr &MI,
419 unsigned OpNo) const;
421 /// \brief Return the size in bytes of the operand OpNo on the given
422 // instruction opcode.
423 unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const {
424 const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo];
426 if (OpInfo.RegClass == -1) {
427 // If this is an immediate operand, this must be a 32-bit literal.
428 assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE);
432 return RI.getRegClass(OpInfo.RegClass)->getSize();
435 /// \brief This form should usually be preferred since it handles operands
436 /// with unknown register classes.
437 unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const {
438 return getOpRegClass(MI, OpNo)->getSize();
441 /// \returns true if it is legal for the operand at index \p OpNo
443 bool canReadVGPR(const MachineInstr &MI, unsigned OpNo) const;
445 /// \brief Legalize the \p OpIndex operand of this instruction by inserting
446 /// a MOV. For example:
447 /// ADD_I32_e32 VGPR0, 15
450 /// ADD_I32_e32 VGPR0, VGPR1
452 /// If the operand being legalized is a register, then a COPY will be used
454 void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const;
456 /// \brief Check if \p MO is a legal operand if it was the \p OpIdx Operand
458 bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
459 const MachineOperand *MO = nullptr) const;
461 /// \brief Check if \p MO would be a valid operand for the given operand
462 /// definition \p OpInfo. Note this does not attempt to validate constant bus
463 /// restrictions (e.g. literal constant usage).
464 bool isLegalVSrcOperand(const MachineRegisterInfo &MRI,
465 const MCOperandInfo &OpInfo,
466 const MachineOperand &MO) const;
468 /// \brief Check if \p MO (a register operand) is a legal register for the
469 /// given operand description.
470 bool isLegalRegOperand(const MachineRegisterInfo &MRI,
471 const MCOperandInfo &OpInfo,
472 const MachineOperand &MO) const;
474 /// \brief Legalize operands in \p MI by either commuting it or inserting a
476 void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const;
478 /// \brief Fix operands in \p MI to satisfy constant bus requirements.
479 void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const;
481 /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
482 /// be used when it is know that the value in SrcReg is same across all
483 /// threads in the wave.
484 /// \returns The SGPR register that \p SrcReg was copied to.
485 unsigned readlaneVGPRToSGPR(unsigned SrcReg, MachineInstr &UseMI,
486 MachineRegisterInfo &MRI) const;
488 void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const;
490 /// \brief Legalize all operands in this instruction. This function may
491 /// create new instruction and insert them before \p MI.
492 void legalizeOperands(MachineInstr &MI) const;
494 /// \brief Replace this instruction's opcode with the equivalent VALU
495 /// opcode. This function will also move the users of \p MI to the
496 /// VALU if necessary.
497 void moveToVALU(MachineInstr &MI) const;
499 void insertWaitStates(MachineBasicBlock &MBB,MachineBasicBlock::iterator MI,
502 void insertNoop(MachineBasicBlock &MBB,
503 MachineBasicBlock::iterator MI) const override;
505 /// \brief Return the number of wait states that result from executing this
507 unsigned getNumWaitStates(const MachineInstr &MI) const;
509 /// \brief Returns the operand named \p Op. If \p MI does not have an
510 /// operand named \c Op, this function returns nullptr.
512 MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const;
515 const MachineOperand *getNamedOperand(const MachineInstr &MI,
516 unsigned OpName) const {
517 return getNamedOperand(const_cast<MachineInstr &>(MI), OpName);
520 /// Get required immediate operand
521 int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const {
522 int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
523 return MI.getOperand(Idx).getImm();
526 uint64_t getDefaultRsrcDataFormat() const;
527 uint64_t getScratchRsrcWords23() const;
529 bool isLowLatencyInstruction(const MachineInstr &MI) const;
530 bool isHighLatencyInstruction(const MachineInstr &MI) const;
532 /// \brief Return the descriptor of the target-specific machine instruction
533 /// that corresponds to the specified pseudo or native opcode.
534 const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const {
535 return get(pseudoToMCOpcode(Opcode));
538 unsigned getInstSizeInBytes(const MachineInstr &MI) const;
540 ArrayRef<std::pair<int, const char *>>
541 getSerializableTargetIndices() const override;
543 ScheduleHazardRecognizer *
544 CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
545 const ScheduleDAG *DAG) const override;
547 ScheduleHazardRecognizer *
548 CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override;
553 int getVOPe64(uint16_t Opcode);
556 int getVOPe32(uint16_t Opcode);
559 int getCommuteRev(uint16_t Opcode);
562 int getCommuteOrig(uint16_t Opcode);
565 int getAddr64Inst(uint16_t Opcode);
568 int getAtomicRetOp(uint16_t Opcode);
571 int getAtomicNoRetOp(uint16_t Opcode);
573 const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL;
574 const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19);
575 const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21);
576 const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23);
577 } // End namespace AMDGPU
580 namespace KernelInputOffsets {
582 /// Offsets in bytes from the start of the input buffer
595 } // End namespace KernelInputOffsets
596 } // End namespace SI
598 } // End namespace llvm