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)) {
119 assert(Inst.mayLoadOrStore() ||
121 HWEvents E = HWEvents::NONE;
122 if (TII.mayAccessVMEMThroughFlat(Inst)) {
123 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
124 E |= HWEvents::VMEM_GROUP;
126 }
127
128 if (TII.mayAccessLDSThroughFlat(Inst, TgSplit))
129 E |= HWEvents::LDS_ACCESS;
130
132 E |= HWEvents::ASYNC_ACCESS;
133
134 return E;
135 }
136
138 return HWEvents::TENSOR_ACCESS;
139
140 if (SIInstrInfo::isVMEM(Inst) &&
142 Inst.getOpcode() == AMDGPU::BUFFER_INV ||
143 Inst.getOpcode() == AMDGPU::BUFFER_WBL2)) {
144 // BUFFER_INV increments VM_CNT. BUFFER_WBL2 also needs tracking because an
145 // S_WAITCNT vmcnt(0) must follow it to ensure the writeback has completed.
147 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
148 E |= HWEvents::VMEM_GROUP;
149 if (ST.vmemWriteNeedsExpWaitcnt() &&
150 (Inst.mayStore() || SIInstrInfo::isAtomicRet(Inst)))
151 E |= HWEvents::VMW_GPR_LOCK;
152
153 return E;
154 }
155
156 if (TII.isSMRD(Inst)) {
157 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
158 return HWEvents::SMEM_GROUP | HWEvents::SMEM_ACCESS;
159 return HWEvents::SMEM_ACCESS;
160 }
161
162 if (SIInstrInfo::isLDSDIR(Inst)) {
163 return HWEvents::EXP_LDS_ACCESS;
164 }
165
166 if (SIInstrInfo::isEXP(Inst)) {
167 int64_t Imm = TII.getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
169 return HWEvents::EXP_PARAM_ACCESS;
171 return HWEvents::EXP_POS_ACCESS;
172 return HWEvents::EXP_GPR_LOCK;
173 }
174
176 return HWEvents::SCC_WRITE;
177 }
178
179 switch (Inst.getOpcode()) {
180 case AMDGPU::S_SENDMSG:
181 case AMDGPU::S_SENDMSG_RTN_B32:
182 case AMDGPU::S_SENDMSG_RTN_B64:
183 case AMDGPU::S_SENDMSGHALT:
184 return HWEvents::SQ_MESSAGE;
185 case AMDGPU::S_MEMTIME:
186 case AMDGPU::S_MEMREALTIME:
187 case AMDGPU::S_GET_BARRIER_STATE_M0:
188 case AMDGPU::S_GET_BARRIER_STATE_IMM:
189 return HWEvents::SMEM_ACCESS;
190 }
191
192 return HWEvents::NONE;
193}
194
196 bool IsExpertMode, bool TgSplit) {
197 const SIInstrInfo &TII = *ST.getInstrInfo();
198
199 if (IsExpertMode)
200 return getEventsForImpl(Inst, ST, TII, TgSplit) |
202 return getEventsForImpl(Inst, ST, TII, TgSplit);
203}
204} // namespace AMDGPU
205
207 ListSeparator LS(" | ");
208#define AMDGPU_HW_EVENT(E, V) \
209 if (Events & AMDGPU::HWEvents::E) \
210 OS << LS << #E << " ";
211#include "AMDGPUHWEvents.def"
212 return OS;
213}
214
215} // 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)