LLVM 24.0.0git
AMDGPUHWEvents.cpp
Go to the documentation of this file.
1//===- AMDGPUHWEvents.cpp ---------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AMDGPUHWEvents.h"
10#include "GCNSubtarget.h"
11#include "SIInstrInfo.h"
13#include "llvm/Support/Debug.h"
15
16namespace llvm {
17namespace AMDGPU {
18
19#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
20LLVM_DUMP_METHOD void HWEvents::dump() const { dbgs() << *this << "\n"; }
21#endif
22
24 const SIInstrInfo &TII) {
25 if (TII.isVALU(Inst, /*AllowLDSDMA=*/false)) {
26 // Core/Side-, DP-, XDL- and TRANS-MACC VALU instructions complete
27 // out-of-order with respect to each other, so each of these classes
28 // has its own event.
29
30 if (TII.isXDL(Inst))
31 return HWEvents::VGPR_XDL_READ | HWEvents::VGPR_XDL_WRITE;
32
33 if (TII.isTRANS(Inst))
34 return HWEvents::VGPR_TRANS_READ | HWEvents::VGPR_TRANS_WRITE;
35
37 return HWEvents::VGPR_DPMACC_READ | HWEvents::VGPR_DPMACC_WRITE;
38
39 return HWEvents::VGPR_CSMACC_READ | HWEvents::VGPR_CSMACC_WRITE;
40 }
41
42 // FLAT and LDS instructions may read their VGPR sources out-of-order
43 // with respect to each other and all other VMEM instructions, so
44 // each of these also has a separate event.
45
46 if (TII.isFLAT(Inst))
47 return HWEvents::VGPR_FLAT_READ;
48
49 if (TII.isDS(Inst))
50 return HWEvents::VGPR_LDS_READ;
51
52 if (TII.isVMEM(Inst) || TII.isVIMAGE(Inst) || TII.isVSAMPLE(Inst))
53 return HWEvents::VGPR_VMEM_READ;
54
55 // Otherwise, no hazard.
56 return HWEvents::NONE;
57}
58
60 const SIInstrInfo &TII) {
61 switch (Inst.getOpcode()) {
62 case AMDGPU::GLOBAL_INV:
63 case AMDGPU::BUFFER_INV:
64 return HWEvents::VMEM_INV_ACCESS; // tracked using loadcnt/vmcnt, but
65 // doesn't write VGPRs
66 case AMDGPU::GLOBAL_WB:
67 case AMDGPU::GLOBAL_WBINV:
68 return HWEvents::VMEM_WRITE_ACCESS; // tracked using storecnt
69 default:
70 break;
71 }
72
74 // LDS DMA loads are also stores, but on the LDS side. On the VMEM side
75 // these should use VM_CNT.
77 return HWEvents::VMEM_READ_ACCESS;
78
79 if (Inst.mayStore() &&
80 (!Inst.mayLoad() || SIInstrInfo::isAtomicNoRet(Inst))) {
81 if (TII.mayAccessScratch(Inst))
82 return HWEvents::SCRATCH_WRITE_ACCESS;
83 return HWEvents::VMEM_WRITE_ACCESS;
84 }
85
86 if (SIInstrInfo::isFLAT(Inst))
87 return HWEvents::VMEM_READ_ACCESS;
88
89 if (SIInstrInfo::isImage(Inst)) {
91 const AMDGPU::MIMGBaseOpcodeInfo *BaseInfo =
92 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
93
94 if (BaseInfo->BVH)
95 return HWEvents::VMEM_BVH_READ_ACCESS;
96
97 // We have to make an additional check for isVSAMPLE here since some
98 // instructions don't have a sampler, but are still classified as sampler
99 // instructions for the purposes of e.g. waitcnt.
100 if (BaseInfo->Sampler || BaseInfo->MSAA || SIInstrInfo::isVSAMPLE(Inst))
101 return HWEvents::VMEM_SAMPLER_READ_ACCESS;
102 }
103
104 return HWEvents::VMEM_READ_ACCESS;
105}
106
108 const GCNSubtarget &ST, const SIInstrInfo &TII,
109 bool TgSplit) {
110 if (TII.isDS(Inst) && TII.usesLGKM_CNT(Inst)) {
111 if (TII.isAlwaysGDS(Inst.getOpcode()) ||
112 TII.hasModifiersSet(Inst, AMDGPU::OpName::gds))
113 return HWEvents::GDS_ACCESS | HWEvents::GDS_GPR_LOCK;
114
115 return HWEvents::LDS_ACCESS;
116 }
117
118 if (TII.isFLAT(Inst)) {
121 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
122 E |= HWEvents::VMEM_GROUP;
123 return E;
124 }
125
126 assert(Inst.mayLoadOrStore());
127 HWEvents E = HWEvents::NONE;
128 if (TII.mayAccessVMEMThroughFlat(Inst)) {
129 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
130 E |= HWEvents::VMEM_GROUP;
132 }
133
134 if (TII.mayAccessLDSThroughFlat(Inst, TgSplit))
135 E |= HWEvents::LDS_ACCESS;
136
138 E |= HWEvents::ASYNC_ACCESS;
139
140 return E;
141 }
142
144 return HWEvents::TENSOR_ACCESS;
145
146 if (SIInstrInfo::isVMEM(Inst) &&
148 Inst.getOpcode() == AMDGPU::BUFFER_INV ||
149 Inst.getOpcode() == AMDGPU::BUFFER_WBL2)) {
150 // BUFFER_INV increments VM_CNT. BUFFER_WBL2 also needs tracking because an
151 // S_WAITCNT vmcnt(0) must follow it to ensure the writeback has completed.
153 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
154 E |= HWEvents::VMEM_GROUP;
155 if (ST.vmemWriteNeedsExpWaitcnt() &&
156 (Inst.mayStore() || SIInstrInfo::isAtomicRet(Inst)))
157 E |= HWEvents::VMW_GPR_LOCK;
158
159 return E;
160 }
161
162 if (TII.isSMRD(Inst)) {
163 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
164 return HWEvents::SMEM_GROUP | HWEvents::SMEM_ACCESS;
165 return HWEvents::SMEM_ACCESS;
166 }
167
168 if (SIInstrInfo::isLDSDIR(Inst)) {
169 return HWEvents::EXP_LDS_ACCESS;
170 }
171
172 if (SIInstrInfo::isEXP(Inst)) {
173 int64_t Imm = TII.getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
175 return HWEvents::EXP_PARAM_ACCESS;
177 return HWEvents::EXP_POS_ACCESS;
178 return HWEvents::EXP_GPR_LOCK;
179 }
180
182 return HWEvents::SCC_WRITE;
183 }
184
185 switch (Inst.getOpcode()) {
186 case AMDGPU::S_SENDMSG:
187 case AMDGPU::S_SENDMSG_RTN_B32:
188 case AMDGPU::S_SENDMSG_RTN_B64:
189 case AMDGPU::S_SENDMSGHALT:
190 return HWEvents::SQ_MESSAGE;
191 case AMDGPU::S_MEMTIME:
192 case AMDGPU::S_MEMREALTIME:
193 case AMDGPU::S_GET_BARRIER_STATE_M0:
194 case AMDGPU::S_GET_BARRIER_STATE_IMM:
195 return HWEvents::SMEM_ACCESS;
196 }
197
198 return HWEvents::NONE;
199}
200
202 bool IsExpertMode, bool TgSplit) {
203 const SIInstrInfo &TII = *ST.getInstrInfo();
204
205 if (IsExpertMode)
206 return getEventsForImpl(Inst, ST, TII, TgSplit) |
208 return getEventsForImpl(Inst, ST, TII, TgSplit);
209}
210} // namespace AMDGPU
211
213 ListSeparator LS(" | ");
214#define AMDGPU_HW_EVENT(E, V) \
215 if (Events & AMDGPU::HWEvents::E) \
216 OS << LS << #E << " ";
217#include "AMDGPUHWEvents.def"
218 return OS;
219}
220
221} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:690
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Interface definition for SIInstrInfo.
This file contains some functions that are useful when dealing with strings.
Bit mask of hardware events.
A helper class to return the specified delimiter string after the first invocation of operator String...
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
static bool isVMEM(const MachineInstr &MI)
static bool isEXP(const MachineInstr &MI)
static bool mayWriteLDSThroughDMA(const MachineInstr &MI)
static bool usesTENSOR_CNT(const MachineInstr &MI)
static bool isLDSDIR(const MachineInstr &MI)
static bool isVSAMPLE(const MachineInstr &MI)
static bool isAtomicRet(const MachineInstr &MI)
static bool isImage(const MachineInstr &MI)
static bool isGFX12CacheInvOrWBInst(unsigned Opc)
static bool isSBarrierSCCWrite(unsigned Opcode)
static bool usesASYNC_CNT(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
static bool isAtomicNoRet(const MachineInstr &MI)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
bool isDPMACCInstruction(unsigned Opc)
static HWEvents getExpertSchedulingEventType(const MachineInstr &Inst, const SIInstrInfo &TII)
HWEvents getSimplifiedVMEMEventsFor(const MachineInstr &Inst, const SIInstrInfo &TII)
HWEvents getEventsFor(const MachineInstr &Inst, const GCNSubtarget &ST, bool IsExpertMode, bool TgSplit)
bool getMUBUFIsBufferInv(unsigned Opc)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
static HWEvents getEventsForImpl(const MachineInstr &Inst, const GCNSubtarget &ST, const SIInstrInfo &TII, bool TgSplit)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)