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 // The VGLOBAL tensor ops are the only VMEM FLAT instructions that do
124 // not increment xcnt.
125 if (ST.hasWaitXcnt() && ST.isXNACKEnabled() &&
126 Inst.getOpcode() != AMDGPU::TENSOR_SAVE &&
127 Inst.getOpcode() != AMDGPU::TENSOR_STOP)
128 E |= HWEvents::VMEM_GROUP;
130 }
131
132 if (TII.mayAccessLDSThroughFlat(Inst, TgSplit))
133 E |= HWEvents::LDS_ACCESS;
134
136 E |= HWEvents::ASYNC_ACCESS;
137
138 return E;
139 }
140
142 return HWEvents::TENSOR_ACCESS;
143
144 if (SIInstrInfo::isVMEM(Inst) &&
146 Inst.getOpcode() == AMDGPU::BUFFER_INV ||
147 Inst.getOpcode() == AMDGPU::BUFFER_WBL2)) {
148 // BUFFER_INV increments VM_CNT. BUFFER_WBL2 also needs tracking because an
149 // S_WAITCNT vmcnt(0) must follow it to ensure the writeback has completed.
151 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
152 E |= HWEvents::VMEM_GROUP;
153 if (ST.vmemWriteNeedsExpWaitcnt() &&
154 (Inst.mayStore() || SIInstrInfo::isAtomicRet(Inst)))
155 E |= HWEvents::VMW_GPR_LOCK;
156
157 return E;
158 }
159
160 if (TII.isSMRD(Inst)) {
161 if (ST.hasWaitXcnt() && ST.isXNACKEnabled())
162 return HWEvents::SMEM_GROUP | HWEvents::SMEM_ACCESS;
163 return HWEvents::SMEM_ACCESS;
164 }
165
166 if (SIInstrInfo::isLDSDIR(Inst)) {
167 return HWEvents::EXP_LDS_ACCESS;
168 }
169
170 if (SIInstrInfo::isEXP(Inst)) {
171 int64_t Imm = TII.getNamedOperand(Inst, AMDGPU::OpName::tgt)->getImm();
173 return HWEvents::EXP_PARAM_ACCESS;
175 return HWEvents::EXP_POS_ACCESS;
176 return HWEvents::EXP_GPR_LOCK;
177 }
178
180 return HWEvents::SCC_WRITE;
181 }
182
183 switch (Inst.getOpcode()) {
184 case AMDGPU::S_SENDMSG:
185 case AMDGPU::S_SENDMSG_RTN_B32:
186 case AMDGPU::S_SENDMSG_RTN_B64:
187 case AMDGPU::S_SENDMSGHALT:
188 return HWEvents::SQ_MESSAGE;
189 case AMDGPU::S_MEMTIME:
190 case AMDGPU::S_MEMREALTIME:
191 case AMDGPU::S_GET_BARRIER_STATE_M0:
192 case AMDGPU::S_GET_BARRIER_STATE_IMM:
193 return HWEvents::SMEM_ACCESS;
194 }
195
196 return HWEvents::NONE;
197}
198
200 bool IsExpertMode, bool TgSplit) {
201 const SIInstrInfo &TII = *ST.getInstrInfo();
202
203 if (IsExpertMode)
204 return getEventsForImpl(Inst, ST, TII, TgSplit) |
206 return getEventsForImpl(Inst, ST, TII, TgSplit);
207}
208} // namespace AMDGPU
209
211 ListSeparator LS(" | ");
212#define AMDGPU_HW_EVENT(E, V) \
213 if (Events & AMDGPU::HWEvents::E) \
214 OS << LS << #E << " ";
215#include "AMDGPUHWEvents.def"
216 return OS;
217}
218
219} // 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)