LLVM 20.0.0git
LSUnit.cpp
Go to the documentation of this file.
1//===----------------------- LSUnit.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/// \file
9///
10/// A Load-Store Unit for the llvm-mca tool.
11///
12//===----------------------------------------------------------------------===//
13
16#include "llvm/Support/Debug.h"
18
19#define DEBUG_TYPE "llvm-mca"
20
21namespace llvm {
22namespace mca {
23
24LSUnitBase::LSUnitBase(const MCSchedModel &SM, unsigned LQ, unsigned SQ,
25 bool AssumeNoAlias)
26 : LQSize(LQ), SQSize(SQ), UsedLQEntries(0), UsedSQEntries(0),
27 NoAlias(AssumeNoAlias), NextGroupID(1) {
28 if (SM.hasExtraProcessorInfo()) {
30 if (!LQSize && EPI.LoadQueueID) {
31 const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID);
32 LQSize = std::max(0, LdQDesc.BufferSize);
33 }
34
35 if (!SQSize && EPI.StoreQueueID) {
36 const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID);
37 SQSize = std::max(0, StQDesc.BufferSize);
38 }
39 }
40}
41
42LSUnitBase::~LSUnitBase() = default;
43
45 for (const std::pair<unsigned, std::unique_ptr<MemoryGroup>> &G : Groups)
46 G.second->cycleEvent();
47}
48
49#ifndef NDEBUG
50void LSUnitBase::dump() const {
51 dbgs() << "[LSUnit] LQ_Size = " << getLoadQueueSize() << '\n';
52 dbgs() << "[LSUnit] SQ_Size = " << getStoreQueueSize() << '\n';
53 dbgs() << "[LSUnit] NextLQSlotIdx = " << getUsedLQEntries() << '\n';
54 dbgs() << "[LSUnit] NextSQSlotIdx = " << getUsedSQEntries() << '\n';
55 dbgs() << "\n";
56 for (const auto &GroupIt : Groups) {
57 const MemoryGroup &Group = *GroupIt.second;
58 dbgs() << "[LSUnit] Group (" << GroupIt.first << "): "
59 << "[ #Preds = " << Group.getNumPredecessors()
60 << ", #GIssued = " << Group.getNumExecutingPredecessors()
61 << ", #GExecuted = " << Group.getNumExecutedPredecessors()
62 << ", #Inst = " << Group.getNumInstructions()
63 << ", #IIssued = " << Group.getNumExecuting()
64 << ", #IExecuted = " << Group.getNumExecuted() << '\n';
65 }
66}
67#endif
68
69unsigned LSUnit::dispatch(const InstRef &IR) {
70 const Instruction &IS = *IR.getInstruction();
71 bool IsStoreBarrier = IS.isAStoreBarrier();
72 bool IsLoadBarrier = IS.isALoadBarrier();
73 assert((IS.getMayLoad() || IS.getMayStore()) && "Not a memory operation!");
74
75 if (IS.getMayLoad())
77 if (IS.getMayStore())
79
80 if (IS.getMayStore()) {
81 unsigned NewGID = createMemoryGroup();
82 MemoryGroup &NewGroup = getGroup(NewGID);
83 NewGroup.addInstruction();
84
85 // A store may not pass a previous load or load barrier.
86 unsigned ImmediateLoadDominator =
87 std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID);
88 if (ImmediateLoadDominator) {
89 MemoryGroup &IDom = getGroup(ImmediateLoadDominator);
90 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << ImmediateLoadDominator
91 << ") --> (" << NewGID << ")\n");
92 IDom.addSuccessor(&NewGroup, !assumeNoAlias());
93 }
94
95 // A store may not pass a previous store barrier.
96 if (CurrentStoreBarrierGroupID) {
97 MemoryGroup &StoreGroup = getGroup(CurrentStoreBarrierGroupID);
98 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("
99 << CurrentStoreBarrierGroupID
100 << ") --> (" << NewGID << ")\n");
101 StoreGroup.addSuccessor(&NewGroup, true);
102 }
103
104 // A store may not pass a previous store.
105 if (CurrentStoreGroupID &&
106 (CurrentStoreGroupID != CurrentStoreBarrierGroupID)) {
107 MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID);
108 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID
109 << ") --> (" << NewGID << ")\n");
110 StoreGroup.addSuccessor(&NewGroup, !assumeNoAlias());
111 }
112
113
114 CurrentStoreGroupID = NewGID;
115 if (IsStoreBarrier)
116 CurrentStoreBarrierGroupID = NewGID;
117
118 if (IS.getMayLoad()) {
119 CurrentLoadGroupID = NewGID;
120 if (IsLoadBarrier)
121 CurrentLoadBarrierGroupID = NewGID;
122 }
123
124 return NewGID;
125 }
126
127 assert(IS.getMayLoad() && "Expected a load!");
128
129 unsigned ImmediateLoadDominator =
130 std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID);
131
132 // A new load group is created if we are in one of the following situations:
133 // 1) This is a load barrier (by construction, a load barrier is always
134 // assigned to a different memory group).
135 // 2) There is no load in flight (by construction we always keep loads and
136 // stores into separate memory groups).
137 // 3) There is a load barrier in flight. This load depends on it.
138 // 4) There is an intervening store between the last load dispatched to the
139 // LSU and this load. We always create a new group even if this load
140 // does not alias the last dispatched store.
141 // 5) There is no intervening store and there is an active load group.
142 // However that group has already started execution, so we cannot add
143 // this load to it.
144 bool ShouldCreateANewGroup =
145 IsLoadBarrier || !ImmediateLoadDominator ||
146 CurrentLoadBarrierGroupID == ImmediateLoadDominator ||
147 ImmediateLoadDominator <= CurrentStoreGroupID ||
148 getGroup(ImmediateLoadDominator).isExecuting();
149
150 if (ShouldCreateANewGroup) {
151 unsigned NewGID = createMemoryGroup();
152 MemoryGroup &NewGroup = getGroup(NewGID);
153 NewGroup.addInstruction();
154
155 // A load may not pass a previous store or store barrier
156 // unless flag 'NoAlias' is set.
157 if (!assumeNoAlias() && CurrentStoreGroupID) {
158 MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID);
159 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID
160 << ") --> (" << NewGID << ")\n");
161 StoreGroup.addSuccessor(&NewGroup, true);
162 }
163
164 // A load barrier may not pass a previous load or load barrier.
165 if (IsLoadBarrier) {
166 if (ImmediateLoadDominator) {
167 MemoryGroup &LoadGroup = getGroup(ImmediateLoadDominator);
168 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("
169 << ImmediateLoadDominator
170 << ") --> (" << NewGID << ")\n");
171 LoadGroup.addSuccessor(&NewGroup, true);
172 }
173 } else {
174 // A younger load cannot pass a older load barrier.
175 if (CurrentLoadBarrierGroupID) {
176 MemoryGroup &LoadGroup = getGroup(CurrentLoadBarrierGroupID);
177 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("
178 << CurrentLoadBarrierGroupID
179 << ") --> (" << NewGID << ")\n");
180 LoadGroup.addSuccessor(&NewGroup, true);
181 }
182 }
183
184 CurrentLoadGroupID = NewGID;
185 if (IsLoadBarrier)
186 CurrentLoadBarrierGroupID = NewGID;
187 return NewGID;
188 }
189
190 // A load may pass a previous load.
191 MemoryGroup &Group = getGroup(CurrentLoadGroupID);
192 Group.addInstruction();
193 return CurrentLoadGroupID;
194}
195
197 const Instruction &IS = *IR.getInstruction();
198 if (IS.getMayLoad() && isLQFull())
200 if (IS.getMayStore() && isSQFull())
203}
204
206 unsigned GroupID = IR.getInstruction()->getLSUTokenID();
207 auto It = Groups.find(GroupID);
208 assert(It != Groups.end() && "Instruction not dispatched to the LS unit");
209 It->second->onInstructionExecuted(IR);
210 if (It->second->isExecuted())
211 Groups.erase(It);
212}
213
215 const Instruction &IS = *IR.getInstruction();
216 bool IsALoad = IS.getMayLoad();
217 bool IsAStore = IS.getMayStore();
218 assert((IsALoad || IsAStore) && "Expected a memory operation!");
219
220 if (IsALoad) {
222 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex()
223 << " has been removed from the load queue.\n");
224 }
225
226 if (IsAStore) {
228 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex()
229 << " has been removed from the store queue.\n");
230 }
231}
232
234 const Instruction &IS = *IR.getInstruction();
235 if (!IS.isMemOp())
236 return;
237
239 unsigned GroupID = IS.getLSUTokenID();
240 if (!isValidGroupID(GroupID)) {
241 if (GroupID == CurrentLoadGroupID)
242 CurrentLoadGroupID = 0;
243 if (GroupID == CurrentStoreGroupID)
244 CurrentStoreGroupID = 0;
245 if (GroupID == CurrentLoadBarrierGroupID)
246 CurrentLoadBarrierGroupID = 0;
247 if (GroupID == CurrentStoreBarrierGroupID)
248 CurrentStoreBarrierGroupID = 0;
249 }
250}
251
252} // namespace mca
253} // namespace llvm
#define LLVM_DEBUG(X)
Definition: Debug.h:101
A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...
Legalize the Machine IR a function s Machine IR
Definition: Legalizer.cpp:81
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
#define G(x, y, z)
Definition: MD5.cpp:56
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:720
bool isAStoreBarrier() const
Definition: Instruction.h:545
An instruction propagated through the simulated instruction pipeline.
Definition: Instruction.h:600
unsigned getLSUTokenID() const
Definition: Instruction.h:656
virtual void onInstructionExecuted(const InstRef &IR)
Definition: LSUnit.cpp:205
bool isLQFull() const
Definition: LSUnit.h:266
unsigned getUsedSQEntries() const
Definition: LSUnit.h:234
void acquireSQSlot()
Definition: LSUnit.h:236
bool isValidGroupID(unsigned Index) const
Definition: LSUnit.h:268
const MemoryGroup & getGroup(unsigned Index) const
Definition: LSUnit.h:301
unsigned createMemoryGroup()
Definition: LSUnit.h:311
void releaseLQSlot()
Definition: LSUnit.h:237
virtual void cycleEvent()
Definition: LSUnit.cpp:44
unsigned getUsedLQEntries() const
Definition: LSUnit.h:233
bool assumeNoAlias() const
Definition: LSUnit.h:240
virtual void onInstructionRetired(const InstRef &IR)
Definition: LSUnit.cpp:214
unsigned getLoadQueueSize() const
Returns the total number of entries in the load queue.
Definition: LSUnit.h:228
bool isSQFull() const
Definition: LSUnit.h:265
LSUnitBase(const MCSchedModel &SM, unsigned LoadQueueSize, unsigned StoreQueueSize, bool AssumeNoAlias)
Definition: LSUnit.cpp:24
void dump() const
Definition: LSUnit.cpp:50
unsigned getStoreQueueSize() const
Returns the total number of entries in the store queue.
Definition: LSUnit.h:231
void acquireLQSlot()
Definition: LSUnit.h:235
void releaseSQSlot()
Definition: LSUnit.h:238
Status isAvailable(const InstRef &IR) const override
Returns LSU_AVAILABLE if there are enough load/store queue entries to accomodate instruction IR.
Definition: LSUnit.cpp:196
void onInstructionExecuted(const InstRef &IR) override
Definition: LSUnit.cpp:233
unsigned dispatch(const InstRef &IR) override
Allocates LS resources for instruction IR.
Definition: LSUnit.cpp:69
A node of a memory dependency graph.
Definition: LSUnit.h:35
bool isExecuting() const
Definition: LSUnit.h:107
unsigned getNumExecuted() const
Definition: LSUnit.h:70
unsigned getNumExecutingPredecessors() const
Definition: LSUnit.h:62
unsigned getNumExecuting() const
Definition: LSUnit.h:69
unsigned getNumExecutedPredecessors() const
Definition: LSUnit.h:65
unsigned getNumInstructions() const
Definition: LSUnit.h:68
unsigned getNumPredecessors() const
Definition: LSUnit.h:61
void addSuccessor(MemoryGroup *Group, bool IsDataDependent)
Definition: LSUnit.h:79
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
Provide extra details about the machine processor.
Definition: MCSchedule.h:186
Define a kind of processor resource that will be modeled by the scheduler.
Definition: MCSchedule.h:31
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:253
bool hasExtraProcessorInfo() const
Definition: MCSchedule.h:329
const MCExtraProcessorInfo & getExtraProcessorInfo() const
Definition: MCSchedule.h:336
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition: MCSchedule.h:353