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 "AMDGPUInstrInfo.h"
18 #include "SIDefines.h"
19 #include "SIRegisterInfo.h"
20 #include "Utils/AMDGPUBaseInfo.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/ADT/SetVector.h"
23 #include "llvm/CodeGen/MachineBasicBlock.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/MachineOperand.h"
28 #include "llvm/MC/MCInstrDesc.h"
29 #include "llvm/Support/Compiler.h"
33 #define GET_INSTRINFO_HEADER
34 #include "AMDGPUGenInstrInfo.inc"
39 class MachineDominatorTree
;
40 class MachineRegisterInfo
;
43 class TargetRegisterClass
;
45 class SIInstrInfo final
: public AMDGPUGenInstrInfo
{
47 const SIRegisterInfo RI
;
48 const GCNSubtarget
&ST
;
50 // The inverse predicate should have the negative value.
51 enum BranchPredicate
{
61 using SetVectorType
= SmallSetVector
<MachineInstr
*, 32>;
63 static unsigned getBranchOpcode(BranchPredicate Cond
);
64 static BranchPredicate
getBranchPredicate(unsigned Opcode
);
67 unsigned buildExtractSubReg(MachineBasicBlock::iterator MI
,
68 MachineRegisterInfo
&MRI
,
69 MachineOperand
&SuperReg
,
70 const TargetRegisterClass
*SuperRC
,
72 const TargetRegisterClass
*SubRC
) const;
73 MachineOperand
buildExtractSubRegOrImm(MachineBasicBlock::iterator MI
,
74 MachineRegisterInfo
&MRI
,
75 MachineOperand
&SuperReg
,
76 const TargetRegisterClass
*SuperRC
,
78 const TargetRegisterClass
*SubRC
) const;
80 void swapOperands(MachineInstr
&Inst
) const;
82 bool moveScalarAddSub(SetVectorType
&Worklist
, MachineInstr
&Inst
,
83 MachineDominatorTree
*MDT
= nullptr) const;
85 void lowerScalarAbs(SetVectorType
&Worklist
,
86 MachineInstr
&Inst
) const;
88 void lowerScalarXnor(SetVectorType
&Worklist
,
89 MachineInstr
&Inst
) const;
91 void splitScalarNotBinop(SetVectorType
&Worklist
,
93 unsigned Opcode
) const;
95 void splitScalarBinOpN2(SetVectorType
&Worklist
,
97 unsigned Opcode
) const;
99 void splitScalar64BitUnaryOp(SetVectorType
&Worklist
,
100 MachineInstr
&Inst
, unsigned Opcode
) const;
102 void splitScalar64BitAddSub(SetVectorType
&Worklist
, MachineInstr
&Inst
,
103 MachineDominatorTree
*MDT
= nullptr) const;
105 void splitScalar64BitBinaryOp(SetVectorType
&Worklist
, MachineInstr
&Inst
,
107 MachineDominatorTree
*MDT
= nullptr) const;
109 void splitScalar64BitXnor(SetVectorType
&Worklist
, MachineInstr
&Inst
,
110 MachineDominatorTree
*MDT
= nullptr) const;
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;
120 void addUsersToMoveToVALUWorklist(unsigned Reg
, MachineRegisterInfo
&MRI
,
121 SetVectorType
&Worklist
) const;
124 addSCCDefUsersToVALUWorklist(MachineInstr
&SCCDefInst
,
125 SetVectorType
&Worklist
) const;
127 const TargetRegisterClass
*
128 getDestEquivalentVGPRClass(const MachineInstr
&Inst
) const;
130 bool checkInstOffsetsDoNotOverlap(MachineInstr
&MIa
, MachineInstr
&MIb
) const;
132 unsigned 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.
162 explicit SIInstrInfo(const GCNSubtarget
&ST
);
164 const SIRegisterInfo
&getRegisterInfo() const {
168 bool isReallyTriviallyReMaterializable(const MachineInstr
&MI
,
169 AliasAnalysis
*AA
) const override
;
171 bool areLoadsFromSameBasePtr(SDNode
*Load1
, SDNode
*Load2
,
173 int64_t &Offset2
) const override
;
175 bool getMemOperandWithOffset(MachineInstr
&LdSt
, MachineOperand
*&BaseOp
,
177 const TargetRegisterInfo
*TRI
) const final
;
179 bool shouldClusterMemOps(MachineOperand
&BaseOp1
, MachineOperand
&BaseOp2
,
180 unsigned NumLoads
) const override
;
182 bool shouldScheduleLoadsNear(SDNode
*Load0
, SDNode
*Load1
, int64_t Offset0
,
183 int64_t Offset1
, unsigned NumLoads
) const override
;
185 void copyPhysReg(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MI
,
186 const DebugLoc
&DL
, unsigned DestReg
, unsigned SrcReg
,
187 bool KillSrc
) const override
;
189 unsigned calculateLDSSpillAddress(MachineBasicBlock
&MBB
, MachineInstr
&MI
,
190 RegScavenger
*RS
, unsigned TmpReg
,
191 unsigned Offset
, unsigned Size
) const;
193 void materializeImmediate(MachineBasicBlock
&MBB
,
194 MachineBasicBlock::iterator MI
,
197 int64_t Value
) const;
199 const TargetRegisterClass
*getPreferredSelectRegClass(
200 unsigned Size
) const;
202 unsigned insertNE(MachineBasicBlock
*MBB
,
203 MachineBasicBlock::iterator I
, const DebugLoc
&DL
,
204 unsigned SrcReg
, int Value
) const;
206 unsigned insertEQ(MachineBasicBlock
*MBB
,
207 MachineBasicBlock::iterator I
, const DebugLoc
&DL
,
208 unsigned SrcReg
, int Value
) const;
210 void storeRegToStackSlot(MachineBasicBlock
&MBB
,
211 MachineBasicBlock::iterator MI
, unsigned SrcReg
,
212 bool isKill
, int FrameIndex
,
213 const TargetRegisterClass
*RC
,
214 const TargetRegisterInfo
*TRI
) const override
;
216 void loadRegFromStackSlot(MachineBasicBlock
&MBB
,
217 MachineBasicBlock::iterator MI
, unsigned DestReg
,
218 int FrameIndex
, const TargetRegisterClass
*RC
,
219 const TargetRegisterInfo
*TRI
) const override
;
221 bool expandPostRAPseudo(MachineInstr
&MI
) const override
;
223 // Returns an opcode that can be used to move a value to a \p DstRC
224 // register. If there is no hardware instruction that can store to \p
225 // DstRC, then AMDGPU::COPY is returned.
226 unsigned getMovOpcode(const TargetRegisterClass
*DstRC
) const;
229 int commuteOpcode(unsigned Opc
) const;
232 inline int commuteOpcode(const MachineInstr
&MI
) const {
233 return commuteOpcode(MI
.getOpcode());
236 bool findCommutedOpIndices(MachineInstr
&MI
, unsigned &SrcOpIdx1
,
237 unsigned &SrcOpIdx2
) const override
;
239 bool findCommutedOpIndices(MCInstrDesc Desc
, unsigned & SrcOpIdx0
,
240 unsigned & SrcOpIdx1
) const;
242 bool isBranchOffsetInRange(unsigned BranchOpc
,
243 int64_t BrOffset
) const override
;
245 MachineBasicBlock
*getBranchDestBlock(const MachineInstr
&MI
) const override
;
247 unsigned insertIndirectBranch(MachineBasicBlock
&MBB
,
248 MachineBasicBlock
&NewDestBB
,
251 RegScavenger
*RS
= nullptr) const override
;
253 bool analyzeBranchImpl(MachineBasicBlock
&MBB
,
254 MachineBasicBlock::iterator I
,
255 MachineBasicBlock
*&TBB
,
256 MachineBasicBlock
*&FBB
,
257 SmallVectorImpl
<MachineOperand
> &Cond
,
258 bool AllowModify
) const;
260 bool analyzeBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*&TBB
,
261 MachineBasicBlock
*&FBB
,
262 SmallVectorImpl
<MachineOperand
> &Cond
,
263 bool AllowModify
= false) const override
;
265 unsigned removeBranch(MachineBasicBlock
&MBB
,
266 int *BytesRemoved
= nullptr) const override
;
268 unsigned insertBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
,
269 MachineBasicBlock
*FBB
, ArrayRef
<MachineOperand
> Cond
,
271 int *BytesAdded
= nullptr) const override
;
273 bool reverseBranchCondition(
274 SmallVectorImpl
<MachineOperand
> &Cond
) const override
;
276 bool canInsertSelect(const MachineBasicBlock
&MBB
,
277 ArrayRef
<MachineOperand
> Cond
,
278 unsigned TrueReg
, unsigned FalseReg
,
280 int &TrueCycles
, int &FalseCycles
) const override
;
282 void insertSelect(MachineBasicBlock
&MBB
,
283 MachineBasicBlock::iterator I
, const DebugLoc
&DL
,
284 unsigned DstReg
, ArrayRef
<MachineOperand
> Cond
,
285 unsigned TrueReg
, unsigned FalseReg
) const override
;
287 void insertVectorSelect(MachineBasicBlock
&MBB
,
288 MachineBasicBlock::iterator I
, const DebugLoc
&DL
,
289 unsigned DstReg
, ArrayRef
<MachineOperand
> Cond
,
290 unsigned TrueReg
, unsigned FalseReg
) const;
292 unsigned getAddressSpaceForPseudoSourceKind(
293 unsigned Kind
) const override
;
296 areMemAccessesTriviallyDisjoint(MachineInstr
&MIa
, MachineInstr
&MIb
,
297 AliasAnalysis
*AA
= nullptr) const override
;
299 bool isFoldableCopy(const MachineInstr
&MI
) const;
301 bool FoldImmediate(MachineInstr
&UseMI
, MachineInstr
&DefMI
, unsigned Reg
,
302 MachineRegisterInfo
*MRI
) const final
;
304 unsigned getMachineCSELookAheadLimit() const override
{ return 500; }
306 MachineInstr
*convertToThreeAddress(MachineFunction::iterator
&MBB
,
308 LiveVariables
*LV
) const override
;
310 bool isSchedulingBoundary(const MachineInstr
&MI
,
311 const MachineBasicBlock
*MBB
,
312 const MachineFunction
&MF
) const override
;
314 static bool isSALU(const MachineInstr
&MI
) {
315 return MI
.getDesc().TSFlags
& SIInstrFlags::SALU
;
318 bool isSALU(uint16_t Opcode
) const {
319 return get(Opcode
).TSFlags
& SIInstrFlags::SALU
;
322 static bool isVALU(const MachineInstr
&MI
) {
323 return MI
.getDesc().TSFlags
& SIInstrFlags::VALU
;
326 bool isVALU(uint16_t Opcode
) const {
327 return get(Opcode
).TSFlags
& SIInstrFlags::VALU
;
330 static bool isVMEM(const MachineInstr
&MI
) {
331 return isMUBUF(MI
) || isMTBUF(MI
) || isMIMG(MI
);
334 bool isVMEM(uint16_t Opcode
) const {
335 return isMUBUF(Opcode
) || isMTBUF(Opcode
) || isMIMG(Opcode
);
338 static bool isSOP1(const MachineInstr
&MI
) {
339 return MI
.getDesc().TSFlags
& SIInstrFlags::SOP1
;
342 bool isSOP1(uint16_t Opcode
) const {
343 return get(Opcode
).TSFlags
& SIInstrFlags::SOP1
;
346 static bool isSOP2(const MachineInstr
&MI
) {
347 return MI
.getDesc().TSFlags
& SIInstrFlags::SOP2
;
350 bool isSOP2(uint16_t Opcode
) const {
351 return get(Opcode
).TSFlags
& SIInstrFlags::SOP2
;
354 static bool isSOPC(const MachineInstr
&MI
) {
355 return MI
.getDesc().TSFlags
& SIInstrFlags::SOPC
;
358 bool isSOPC(uint16_t Opcode
) const {
359 return get(Opcode
).TSFlags
& SIInstrFlags::SOPC
;
362 static bool isSOPK(const MachineInstr
&MI
) {
363 return MI
.getDesc().TSFlags
& SIInstrFlags::SOPK
;
366 bool isSOPK(uint16_t Opcode
) const {
367 return get(Opcode
).TSFlags
& SIInstrFlags::SOPK
;
370 static bool isSOPP(const MachineInstr
&MI
) {
371 return MI
.getDesc().TSFlags
& SIInstrFlags::SOPP
;
374 bool isSOPP(uint16_t Opcode
) const {
375 return get(Opcode
).TSFlags
& SIInstrFlags::SOPP
;
378 static bool isVOP1(const MachineInstr
&MI
) {
379 return MI
.getDesc().TSFlags
& SIInstrFlags::VOP1
;
382 bool isVOP1(uint16_t Opcode
) const {
383 return get(Opcode
).TSFlags
& SIInstrFlags::VOP1
;
386 static bool isVOP2(const MachineInstr
&MI
) {
387 return MI
.getDesc().TSFlags
& SIInstrFlags::VOP2
;
390 bool isVOP2(uint16_t Opcode
) const {
391 return get(Opcode
).TSFlags
& SIInstrFlags::VOP2
;
394 static bool isVOP3(const MachineInstr
&MI
) {
395 return MI
.getDesc().TSFlags
& SIInstrFlags::VOP3
;
398 bool isVOP3(uint16_t Opcode
) const {
399 return get(Opcode
).TSFlags
& SIInstrFlags::VOP3
;
402 static bool isSDWA(const MachineInstr
&MI
) {
403 return MI
.getDesc().TSFlags
& SIInstrFlags::SDWA
;
406 bool isSDWA(uint16_t Opcode
) const {
407 return get(Opcode
).TSFlags
& SIInstrFlags::SDWA
;
410 static bool isVOPC(const MachineInstr
&MI
) {
411 return MI
.getDesc().TSFlags
& SIInstrFlags::VOPC
;
414 bool isVOPC(uint16_t Opcode
) const {
415 return get(Opcode
).TSFlags
& SIInstrFlags::VOPC
;
418 static bool isMUBUF(const MachineInstr
&MI
) {
419 return MI
.getDesc().TSFlags
& SIInstrFlags::MUBUF
;
422 bool isMUBUF(uint16_t Opcode
) const {
423 return get(Opcode
).TSFlags
& SIInstrFlags::MUBUF
;
426 static bool isMTBUF(const MachineInstr
&MI
) {
427 return MI
.getDesc().TSFlags
& SIInstrFlags::MTBUF
;
430 bool isMTBUF(uint16_t Opcode
) const {
431 return get(Opcode
).TSFlags
& SIInstrFlags::MTBUF
;
434 static bool isSMRD(const MachineInstr
&MI
) {
435 return MI
.getDesc().TSFlags
& SIInstrFlags::SMRD
;
438 bool isSMRD(uint16_t Opcode
) const {
439 return get(Opcode
).TSFlags
& SIInstrFlags::SMRD
;
442 bool isBufferSMRD(const MachineInstr
&MI
) const;
444 static bool isDS(const MachineInstr
&MI
) {
445 return MI
.getDesc().TSFlags
& SIInstrFlags::DS
;
448 bool isDS(uint16_t Opcode
) const {
449 return get(Opcode
).TSFlags
& SIInstrFlags::DS
;
452 bool isAlwaysGDS(uint16_t Opcode
) const;
454 static bool isMIMG(const MachineInstr
&MI
) {
455 return MI
.getDesc().TSFlags
& SIInstrFlags::MIMG
;
458 bool isMIMG(uint16_t Opcode
) const {
459 return get(Opcode
).TSFlags
& SIInstrFlags::MIMG
;
462 static bool isGather4(const MachineInstr
&MI
) {
463 return MI
.getDesc().TSFlags
& SIInstrFlags::Gather4
;
466 bool isGather4(uint16_t Opcode
) const {
467 return get(Opcode
).TSFlags
& SIInstrFlags::Gather4
;
470 static bool isFLAT(const MachineInstr
&MI
) {
471 return MI
.getDesc().TSFlags
& SIInstrFlags::FLAT
;
474 // Is a FLAT encoded instruction which accesses a specific segment,
475 // i.e. global_* or scratch_*.
476 static bool isSegmentSpecificFLAT(const MachineInstr
&MI
) {
477 auto Flags
= MI
.getDesc().TSFlags
;
478 return (Flags
& SIInstrFlags::FLAT
) && !(Flags
& SIInstrFlags::LGKM_CNT
);
481 // Any FLAT encoded instruction, including global_* and scratch_*.
482 bool isFLAT(uint16_t Opcode
) const {
483 return get(Opcode
).TSFlags
& SIInstrFlags::FLAT
;
486 static bool isEXP(const MachineInstr
&MI
) {
487 return MI
.getDesc().TSFlags
& SIInstrFlags::EXP
;
490 bool isEXP(uint16_t Opcode
) const {
491 return get(Opcode
).TSFlags
& SIInstrFlags::EXP
;
494 static bool isWQM(const MachineInstr
&MI
) {
495 return MI
.getDesc().TSFlags
& SIInstrFlags::WQM
;
498 bool isWQM(uint16_t Opcode
) const {
499 return get(Opcode
).TSFlags
& SIInstrFlags::WQM
;
502 static bool isDisableWQM(const MachineInstr
&MI
) {
503 return MI
.getDesc().TSFlags
& SIInstrFlags::DisableWQM
;
506 bool isDisableWQM(uint16_t Opcode
) const {
507 return get(Opcode
).TSFlags
& SIInstrFlags::DisableWQM
;
510 static bool isVGPRSpill(const MachineInstr
&MI
) {
511 return MI
.getDesc().TSFlags
& SIInstrFlags::VGPRSpill
;
514 bool isVGPRSpill(uint16_t Opcode
) const {
515 return get(Opcode
).TSFlags
& SIInstrFlags::VGPRSpill
;
518 static bool isSGPRSpill(const MachineInstr
&MI
) {
519 return MI
.getDesc().TSFlags
& SIInstrFlags::SGPRSpill
;
522 bool isSGPRSpill(uint16_t Opcode
) const {
523 return get(Opcode
).TSFlags
& SIInstrFlags::SGPRSpill
;
526 static bool isDPP(const MachineInstr
&MI
) {
527 return MI
.getDesc().TSFlags
& SIInstrFlags::DPP
;
530 bool isDPP(uint16_t Opcode
) const {
531 return get(Opcode
).TSFlags
& SIInstrFlags::DPP
;
534 static bool isVOP3P(const MachineInstr
&MI
) {
535 return MI
.getDesc().TSFlags
& SIInstrFlags::VOP3P
;
538 bool isVOP3P(uint16_t Opcode
) const {
539 return get(Opcode
).TSFlags
& SIInstrFlags::VOP3P
;
542 static bool isVINTRP(const MachineInstr
&MI
) {
543 return MI
.getDesc().TSFlags
& SIInstrFlags::VINTRP
;
546 bool isVINTRP(uint16_t Opcode
) const {
547 return get(Opcode
).TSFlags
& SIInstrFlags::VINTRP
;
550 static bool isScalarUnit(const MachineInstr
&MI
) {
551 return MI
.getDesc().TSFlags
& (SIInstrFlags::SALU
| SIInstrFlags::SMRD
);
554 static bool usesVM_CNT(const MachineInstr
&MI
) {
555 return MI
.getDesc().TSFlags
& SIInstrFlags::VM_CNT
;
558 static bool usesLGKM_CNT(const MachineInstr
&MI
) {
559 return MI
.getDesc().TSFlags
& SIInstrFlags::LGKM_CNT
;
562 static bool sopkIsZext(const MachineInstr
&MI
) {
563 return MI
.getDesc().TSFlags
& SIInstrFlags::SOPK_ZEXT
;
566 bool sopkIsZext(uint16_t Opcode
) const {
567 return get(Opcode
).TSFlags
& SIInstrFlags::SOPK_ZEXT
;
570 /// \returns true if this is an s_store_dword* instruction. This is more
571 /// specific than than isSMEM && mayStore.
572 static bool isScalarStore(const MachineInstr
&MI
) {
573 return MI
.getDesc().TSFlags
& SIInstrFlags::SCALAR_STORE
;
576 bool isScalarStore(uint16_t Opcode
) const {
577 return get(Opcode
).TSFlags
& SIInstrFlags::SCALAR_STORE
;
580 static bool isFixedSize(const MachineInstr
&MI
) {
581 return MI
.getDesc().TSFlags
& SIInstrFlags::FIXED_SIZE
;
584 bool isFixedSize(uint16_t Opcode
) const {
585 return get(Opcode
).TSFlags
& SIInstrFlags::FIXED_SIZE
;
588 static bool hasFPClamp(const MachineInstr
&MI
) {
589 return MI
.getDesc().TSFlags
& SIInstrFlags::FPClamp
;
592 bool hasFPClamp(uint16_t Opcode
) const {
593 return get(Opcode
).TSFlags
& SIInstrFlags::FPClamp
;
596 static bool hasIntClamp(const MachineInstr
&MI
) {
597 return MI
.getDesc().TSFlags
& SIInstrFlags::IntClamp
;
600 uint64_t getClampMask(const MachineInstr
&MI
) const {
601 const uint64_t ClampFlags
= SIInstrFlags::FPClamp
|
602 SIInstrFlags::IntClamp
|
603 SIInstrFlags::ClampLo
|
604 SIInstrFlags::ClampHi
;
605 return MI
.getDesc().TSFlags
& ClampFlags
;
608 static bool usesFPDPRounding(const MachineInstr
&MI
) {
609 return MI
.getDesc().TSFlags
& SIInstrFlags::FPDPRounding
;
612 bool usesFPDPRounding(uint16_t Opcode
) const {
613 return get(Opcode
).TSFlags
& SIInstrFlags::FPDPRounding
;
616 bool isVGPRCopy(const MachineInstr
&MI
) const {
618 unsigned Dest
= MI
.getOperand(0).getReg();
619 const MachineFunction
&MF
= *MI
.getParent()->getParent();
620 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
621 return !RI
.isSGPRReg(MRI
, Dest
);
624 /// Whether we must prevent this instruction from executing with EXEC = 0.
625 bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr
&MI
) const;
627 bool isInlineConstant(const APInt
&Imm
) const;
629 bool isInlineConstant(const MachineOperand
&MO
, uint8_t OperandType
) const;
631 bool isInlineConstant(const MachineOperand
&MO
,
632 const MCOperandInfo
&OpInfo
) const {
633 return isInlineConstant(MO
, OpInfo
.OperandType
);
636 /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would
637 /// be an inline immediate.
638 bool isInlineConstant(const MachineInstr
&MI
,
639 const MachineOperand
&UseMO
,
640 const MachineOperand
&DefMO
) const {
641 assert(UseMO
.getParent() == &MI
);
642 int OpIdx
= MI
.getOperandNo(&UseMO
);
643 if (!MI
.getDesc().OpInfo
|| OpIdx
>= MI
.getDesc().NumOperands
) {
647 return isInlineConstant(DefMO
, MI
.getDesc().OpInfo
[OpIdx
]);
650 /// \p returns true if the operand \p OpIdx in \p MI is a valid inline
652 bool isInlineConstant(const MachineInstr
&MI
, unsigned OpIdx
) const {
653 const MachineOperand
&MO
= MI
.getOperand(OpIdx
);
654 return isInlineConstant(MO
, MI
.getDesc().OpInfo
[OpIdx
].OperandType
);
657 bool isInlineConstant(const MachineInstr
&MI
, unsigned OpIdx
,
658 const MachineOperand
&MO
) const {
659 if (!MI
.getDesc().OpInfo
|| OpIdx
>= MI
.getDesc().NumOperands
)
663 unsigned Size
= getOpSize(MI
, OpIdx
);
664 assert(Size
== 8 || Size
== 4);
666 uint8_t OpType
= (Size
== 8) ?
667 AMDGPU::OPERAND_REG_IMM_INT64
: AMDGPU::OPERAND_REG_IMM_INT32
;
668 return isInlineConstant(MO
, OpType
);
671 return isInlineConstant(MO
, MI
.getDesc().OpInfo
[OpIdx
].OperandType
);
674 bool isInlineConstant(const MachineOperand
&MO
) const {
675 const MachineInstr
*Parent
= MO
.getParent();
676 return isInlineConstant(*Parent
, Parent
->getOperandNo(&MO
));
679 bool isLiteralConstant(const MachineOperand
&MO
,
680 const MCOperandInfo
&OpInfo
) const {
681 return MO
.isImm() && !isInlineConstant(MO
, OpInfo
.OperandType
);
684 bool isLiteralConstant(const MachineInstr
&MI
, int OpIdx
) const {
685 const MachineOperand
&MO
= MI
.getOperand(OpIdx
);
686 return MO
.isImm() && !isInlineConstant(MI
, OpIdx
);
689 // Returns true if this operand could potentially require a 32-bit literal
690 // operand, but not necessarily. A FrameIndex for example could resolve to an
691 // inline immediate value that will not require an additional 4-bytes; this
692 // assumes that it will.
693 bool isLiteralConstantLike(const MachineOperand
&MO
,
694 const MCOperandInfo
&OpInfo
) const;
696 bool isImmOperandLegal(const MachineInstr
&MI
, unsigned OpNo
,
697 const MachineOperand
&MO
) const;
699 /// Return true if this 64-bit VALU instruction has a 32-bit encoding.
700 /// This function will return false if you pass it a 32-bit instruction.
701 bool hasVALU32BitEncoding(unsigned Opcode
) const;
703 /// Returns true if this operand uses the constant bus.
704 bool usesConstantBus(const MachineRegisterInfo
&MRI
,
705 const MachineOperand
&MO
,
706 const MCOperandInfo
&OpInfo
) const;
708 /// Return true if this instruction has any modifiers.
709 /// e.g. src[012]_mod, omod, clamp.
710 bool hasModifiers(unsigned Opcode
) const;
712 bool hasModifiersSet(const MachineInstr
&MI
,
713 unsigned OpName
) const;
714 bool hasAnyModifiersSet(const MachineInstr
&MI
) const;
716 bool canShrink(const MachineInstr
&MI
,
717 const MachineRegisterInfo
&MRI
) const;
719 MachineInstr
*buildShrunkInst(MachineInstr
&MI
,
720 unsigned NewOpcode
) const;
722 bool verifyInstruction(const MachineInstr
&MI
,
723 StringRef
&ErrInfo
) const override
;
725 unsigned getVALUOp(const MachineInstr
&MI
) const;
727 /// Return the correct register class for \p OpNo. For target-specific
728 /// instructions, this will return the register class that has been defined
729 /// in tablegen. For generic instructions, like REG_SEQUENCE it will return
730 /// the register class of its machine operand.
731 /// to infer the correct register class base on the other operands.
732 const TargetRegisterClass
*getOpRegClass(const MachineInstr
&MI
,
733 unsigned OpNo
) const;
735 /// Return the size in bytes of the operand OpNo on the given
736 // instruction opcode.
737 unsigned getOpSize(uint16_t Opcode
, unsigned OpNo
) const {
738 const MCOperandInfo
&OpInfo
= get(Opcode
).OpInfo
[OpNo
];
740 if (OpInfo
.RegClass
== -1) {
741 // If this is an immediate operand, this must be a 32-bit literal.
742 assert(OpInfo
.OperandType
== MCOI::OPERAND_IMMEDIATE
);
746 return RI
.getRegSizeInBits(*RI
.getRegClass(OpInfo
.RegClass
)) / 8;
749 /// This form should usually be preferred since it handles operands
750 /// with unknown register classes.
751 unsigned getOpSize(const MachineInstr
&MI
, unsigned OpNo
) const {
752 const MachineOperand
&MO
= MI
.getOperand(OpNo
);
754 if (unsigned SubReg
= MO
.getSubReg()) {
755 assert(RI
.getRegSizeInBits(*RI
.getSubClassWithSubReg(
756 MI
.getParent()->getParent()->getRegInfo().
757 getRegClass(MO
.getReg()), SubReg
)) >= 32 &&
758 "Sub-dword subregs are not supported");
759 return RI
.getSubRegIndexLaneMask(SubReg
).getNumLanes() * 4;
762 return RI
.getRegSizeInBits(*getOpRegClass(MI
, OpNo
)) / 8;
765 /// Legalize the \p OpIndex operand of this instruction by inserting
766 /// a MOV. For example:
767 /// ADD_I32_e32 VGPR0, 15
770 /// ADD_I32_e32 VGPR0, VGPR1
772 /// If the operand being legalized is a register, then a COPY will be used
774 void legalizeOpWithMove(MachineInstr
&MI
, unsigned OpIdx
) const;
776 /// Check if \p MO is a legal operand if it was the \p OpIdx Operand
778 bool isOperandLegal(const MachineInstr
&MI
, unsigned OpIdx
,
779 const MachineOperand
*MO
= nullptr) const;
781 /// Check if \p MO would be a valid operand for the given operand
782 /// definition \p OpInfo. Note this does not attempt to validate constant bus
783 /// restrictions (e.g. literal constant usage).
784 bool isLegalVSrcOperand(const MachineRegisterInfo
&MRI
,
785 const MCOperandInfo
&OpInfo
,
786 const MachineOperand
&MO
) const;
788 /// Check if \p MO (a register operand) is a legal register for the
789 /// given operand description.
790 bool isLegalRegOperand(const MachineRegisterInfo
&MRI
,
791 const MCOperandInfo
&OpInfo
,
792 const MachineOperand
&MO
) const;
794 /// Legalize operands in \p MI by either commuting it or inserting a
796 void legalizeOperandsVOP2(MachineRegisterInfo
&MRI
, MachineInstr
&MI
) const;
798 /// Fix operands in \p MI to satisfy constant bus requirements.
799 void legalizeOperandsVOP3(MachineRegisterInfo
&MRI
, MachineInstr
&MI
) const;
801 /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only
802 /// be used when it is know that the value in SrcReg is same across all
803 /// threads in the wave.
804 /// \returns The SGPR register that \p SrcReg was copied to.
805 unsigned readlaneVGPRToSGPR(unsigned SrcReg
, MachineInstr
&UseMI
,
806 MachineRegisterInfo
&MRI
) const;
808 void legalizeOperandsSMRD(MachineRegisterInfo
&MRI
, MachineInstr
&MI
) const;
810 void legalizeGenericOperand(MachineBasicBlock
&InsertMBB
,
811 MachineBasicBlock::iterator I
,
812 const TargetRegisterClass
*DstRC
,
813 MachineOperand
&Op
, MachineRegisterInfo
&MRI
,
814 const DebugLoc
&DL
) const;
816 /// Legalize all operands in this instruction. This function may create new
817 /// instructions and control-flow around \p MI. If present, \p MDT is
819 void legalizeOperands(MachineInstr
&MI
,
820 MachineDominatorTree
*MDT
= nullptr) const;
822 /// Replace this instruction's opcode with the equivalent VALU
823 /// opcode. This function will also move the users of \p MI to the
824 /// VALU if necessary. If present, \p MDT is updated.
825 void moveToVALU(MachineInstr
&MI
, MachineDominatorTree
*MDT
= nullptr) const;
827 void insertWaitStates(MachineBasicBlock
&MBB
,MachineBasicBlock::iterator MI
,
830 void insertNoop(MachineBasicBlock
&MBB
,
831 MachineBasicBlock::iterator MI
) const override
;
833 void insertReturn(MachineBasicBlock
&MBB
) const;
834 /// Return the number of wait states that result from executing this
836 static unsigned getNumWaitStates(const MachineInstr
&MI
);
838 /// Returns the operand named \p Op. If \p MI does not have an
839 /// operand named \c Op, this function returns nullptr.
841 MachineOperand
*getNamedOperand(MachineInstr
&MI
, unsigned OperandName
) const;
844 const MachineOperand
*getNamedOperand(const MachineInstr
&MI
,
845 unsigned OpName
) const {
846 return getNamedOperand(const_cast<MachineInstr
&>(MI
), OpName
);
849 /// Get required immediate operand
850 int64_t getNamedImmOperand(const MachineInstr
&MI
, unsigned OpName
) const {
851 int Idx
= AMDGPU::getNamedOperandIdx(MI
.getOpcode(), OpName
);
852 return MI
.getOperand(Idx
).getImm();
855 uint64_t getDefaultRsrcDataFormat() const;
856 uint64_t getScratchRsrcWords23() const;
858 bool isLowLatencyInstruction(const MachineInstr
&MI
) const;
859 bool isHighLatencyInstruction(const MachineInstr
&MI
) const;
861 /// Return the descriptor of the target-specific machine instruction
862 /// that corresponds to the specified pseudo or native opcode.
863 const MCInstrDesc
&getMCOpcodeFromPseudo(unsigned Opcode
) const {
864 return get(pseudoToMCOpcode(Opcode
));
867 unsigned isStackAccess(const MachineInstr
&MI
, int &FrameIndex
) const;
868 unsigned isSGPRStackAccess(const MachineInstr
&MI
, int &FrameIndex
) const;
870 unsigned isLoadFromStackSlot(const MachineInstr
&MI
,
871 int &FrameIndex
) const override
;
872 unsigned isStoreToStackSlot(const MachineInstr
&MI
,
873 int &FrameIndex
) const override
;
875 unsigned getInstBundleSize(const MachineInstr
&MI
) const;
876 unsigned getInstSizeInBytes(const MachineInstr
&MI
) const override
;
878 bool mayAccessFlatAddressSpace(const MachineInstr
&MI
) const;
880 bool isNonUniformBranchInstr(MachineInstr
&Instr
) const;
882 void convertNonUniformIfRegion(MachineBasicBlock
*IfEntry
,
883 MachineBasicBlock
*IfEnd
) const;
885 void convertNonUniformLoopRegion(MachineBasicBlock
*LoopEntry
,
886 MachineBasicBlock
*LoopEnd
) const;
888 std::pair
<unsigned, unsigned>
889 decomposeMachineOperandsTargetFlags(unsigned TF
) const override
;
891 ArrayRef
<std::pair
<int, const char *>>
892 getSerializableTargetIndices() const override
;
894 ArrayRef
<std::pair
<unsigned, const char *>>
895 getSerializableDirectMachineOperandTargetFlags() const override
;
897 ScheduleHazardRecognizer
*
898 CreateTargetPostRAHazardRecognizer(const InstrItineraryData
*II
,
899 const ScheduleDAG
*DAG
) const override
;
901 ScheduleHazardRecognizer
*
902 CreateTargetPostRAHazardRecognizer(const MachineFunction
&MF
) const override
;
904 bool isBasicBlockPrologue(const MachineInstr
&MI
) const override
;
906 /// Return a partially built integer add instruction without carry.
907 /// Caller must add source operands.
908 /// For pre-GFX9 it will generate unused carry destination operand.
909 /// TODO: After GFX9 it should return a no-carry operation.
910 MachineInstrBuilder
getAddNoCarry(MachineBasicBlock
&MBB
,
911 MachineBasicBlock::iterator I
,
913 unsigned DestReg
) const;
915 static bool isKillTerminator(unsigned Opcode
);
916 const MCInstrDesc
&getKillTerminatorFromPseudo(unsigned Opcode
) const;
918 static bool isLegalMUBUFImmOffset(unsigned Imm
) {
919 return isUInt
<12>(Imm
);
922 /// \brief Return a target-specific opcode if Opcode is a pseudo instruction.
923 /// Return -1 if the target-specific opcode for the pseudo instruction does
924 /// not exist. If Opcode is not a pseudo instruction, this is identity.
925 int pseudoToMCOpcode(int Opcode
) const;
928 /// \brief Returns true if a reg:subreg pair P has a TRC class
929 inline bool isOfRegClass(const TargetInstrInfo::RegSubRegPair
&P
,
930 const TargetRegisterClass
&TRC
,
931 MachineRegisterInfo
&MRI
) {
932 auto *RC
= MRI
.getRegClass(P
.Reg
);
935 auto *TRI
= MRI
.getTargetRegisterInfo();
936 return RC
== TRI
->getMatchingSuperRegClass(RC
, &TRC
, P
.SubReg
);
939 /// \brief Create RegSubRegPair from a register MachineOperand
941 TargetInstrInfo::RegSubRegPair
getRegSubRegPair(const MachineOperand
&O
) {
943 return TargetInstrInfo::RegSubRegPair(O
.getReg(), O
.getSubReg());
946 /// \brief Return the SubReg component from REG_SEQUENCE
947 TargetInstrInfo::RegSubRegPair
getRegSequenceSubReg(MachineInstr
&MI
,
950 /// \brief Return the defining instruction for a given reg:subreg pair
951 /// skipping copy like instructions and subreg-manipulation pseudos.
952 /// Following another subreg of a reg:subreg isn't supported.
953 MachineInstr
*getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair
&P
,
954 MachineRegisterInfo
&MRI
);
956 /// \brief Return true if EXEC mask isnt' changed between the def and
957 /// all uses of VReg. Currently if def and uses are in different BBs -
958 /// simply return false. Should be run on SSA.
959 bool isEXECMaskConstantBetweenDefAndUses(unsigned VReg
,
960 MachineRegisterInfo
&MRI
);
965 int getVOPe64(uint16_t Opcode
);
968 int getVOPe32(uint16_t Opcode
);
971 int getSDWAOp(uint16_t Opcode
);
974 int getDPPOp32(uint16_t Opcode
);
977 int getBasicFromSDWAOp(uint16_t Opcode
);
980 int getCommuteRev(uint16_t Opcode
);
983 int getCommuteOrig(uint16_t Opcode
);
986 int getAddr64Inst(uint16_t Opcode
);
988 /// Check if \p Opcode is an Addr64 opcode.
990 /// \returns \p Opcode if it is an Addr64 opcode, otherwise -1.
992 int getIfAddr64Inst(uint16_t Opcode
);
995 int getMUBUFNoLdsInst(uint16_t Opcode
);
998 int getAtomicRetOp(uint16_t Opcode
);
1001 int getAtomicNoRetOp(uint16_t Opcode
);
1004 int getSOPKOp(uint16_t Opcode
);
1007 int getGlobalSaddrOp(uint16_t Opcode
);
1009 const uint64_t RSRC_DATA_FORMAT
= 0xf00000000000LL
;
1010 const uint64_t RSRC_ELEMENT_SIZE_SHIFT
= (32 + 19);
1011 const uint64_t RSRC_INDEX_STRIDE_SHIFT
= (32 + 21);
1012 const uint64_t RSRC_TID_ENABLE
= UINT64_C(1) << (32 + 23);
1014 // For MachineOperands.
1016 TF_LONG_BRANCH_FORWARD
= 1 << 0,
1017 TF_LONG_BRANCH_BACKWARD
= 1 << 1
1020 } // end namespace AMDGPU
1023 namespace KernelInputOffsets
{
1025 /// Offsets in bytes from the start of the input buffer
1038 } // end namespace KernelInputOffsets
1039 } // end namespace SI
1041 } // end namespace llvm
1043 #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H