1 //===----------------------- LSUnit.cpp --------------------------*- 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 /// A Load-Store Unit for the llvm-mca tool.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/MCA/HardwareUnits/LSUnit.h"
15 #include "llvm/MCA/Instruction.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/raw_ostream.h"
19 #define DEBUG_TYPE "llvm-mca"
24 LSUnitBase::LSUnitBase(const MCSchedModel
&SM
, unsigned LQ
, unsigned SQ
,
26 : LQSize(LQ
), SQSize(SQ
), UsedLQEntries(0), UsedSQEntries(0),
27 NoAlias(AssumeNoAlias
), NextGroupID(1) {
28 if (SM
.hasExtraProcessorInfo()) {
29 const MCExtraProcessorInfo
&EPI
= SM
.getExtraProcessorInfo();
30 if (!LQSize
&& EPI
.LoadQueueID
) {
31 const MCProcResourceDesc
&LdQDesc
= *SM
.getProcResource(EPI
.LoadQueueID
);
32 LQSize
= std::max(0, LdQDesc
.BufferSize
);
35 if (!SQSize
&& EPI
.StoreQueueID
) {
36 const MCProcResourceDesc
&StQDesc
= *SM
.getProcResource(EPI
.StoreQueueID
);
37 SQSize
= std::max(0, StQDesc
.BufferSize
);
42 LSUnitBase::~LSUnitBase() {}
44 void LSUnitBase::cycleEvent() {
45 for (const std::pair
<unsigned, std::unique_ptr
<MemoryGroup
>> &G
: Groups
)
46 G
.second
->cycleEvent();
50 void 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';
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';
69 unsigned LSUnit::dispatch(const InstRef
&IR
) {
70 const InstrDesc
&Desc
= IR
.getInstruction()->getDesc();
71 unsigned IsMemBarrier
= Desc
.HasSideEffects
;
72 assert((Desc
.MayLoad
|| Desc
.MayStore
) && "Not a memory operation!");
80 // Always create a new group for store operations.
82 // A store may not pass a previous store or store barrier.
83 unsigned NewGID
= createMemoryGroup();
84 MemoryGroup
&NewGroup
= getGroup(NewGID
);
85 NewGroup
.addInstruction();
87 // A store may not pass a previous load or load barrier.
88 unsigned ImmediateLoadDominator
=
89 std::max(CurrentLoadGroupID
, CurrentLoadBarrierGroupID
);
90 if (ImmediateLoadDominator
) {
91 MemoryGroup
&IDom
= getGroup(ImmediateLoadDominator
);
92 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << ImmediateLoadDominator
93 << ") --> (" << NewGID
<< ")\n");
94 IDom
.addSuccessor(&NewGroup
);
96 if (CurrentStoreGroupID
) {
97 MemoryGroup
&StoreGroup
= getGroup(CurrentStoreGroupID
);
98 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID
99 << ") --> (" << NewGID
<< ")\n");
100 StoreGroup
.addSuccessor(&NewGroup
);
103 CurrentStoreGroupID
= NewGID
;
105 CurrentLoadGroupID
= NewGID
;
107 CurrentLoadBarrierGroupID
= NewGID
;
113 assert(Desc
.MayLoad
&& "Expected a load!");
115 // Always create a new memory group if this is the first load of the sequence.
117 // A load may not pass a previous store unless flag 'NoAlias' is set.
118 // A load may pass a previous load.
119 // A younger load cannot pass a older load barrier.
120 // A load barrier cannot pass a older load.
121 bool ShouldCreateANewGroup
= !CurrentLoadGroupID
|| IsMemBarrier
||
122 CurrentLoadGroupID
<= CurrentStoreGroupID
||
123 CurrentLoadGroupID
<= CurrentLoadBarrierGroupID
;
124 if (ShouldCreateANewGroup
) {
125 unsigned NewGID
= createMemoryGroup();
126 MemoryGroup
&NewGroup
= getGroup(NewGID
);
127 NewGroup
.addInstruction();
129 if (!assumeNoAlias() && CurrentStoreGroupID
) {
130 MemoryGroup
&StGroup
= getGroup(CurrentStoreGroupID
);
131 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID
132 << ") --> (" << NewGID
<< ")\n");
133 StGroup
.addSuccessor(&NewGroup
);
135 if (CurrentLoadBarrierGroupID
) {
136 MemoryGroup
&LdGroup
= getGroup(CurrentLoadBarrierGroupID
);
137 LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentLoadBarrierGroupID
138 << ") --> (" << NewGID
<< ")\n");
139 LdGroup
.addSuccessor(&NewGroup
);
142 CurrentLoadGroupID
= NewGID
;
144 CurrentLoadBarrierGroupID
= NewGID
;
148 MemoryGroup
&Group
= getGroup(CurrentLoadGroupID
);
149 Group
.addInstruction();
150 return CurrentLoadGroupID
;
153 LSUnit::Status
LSUnit::isAvailable(const InstRef
&IR
) const {
154 const InstrDesc
&Desc
= IR
.getInstruction()->getDesc();
155 if (Desc
.MayLoad
&& isLQFull())
156 return LSUnit::LSU_LQUEUE_FULL
;
157 if (Desc
.MayStore
&& isSQFull())
158 return LSUnit::LSU_SQUEUE_FULL
;
159 return LSUnit::LSU_AVAILABLE
;
162 void LSUnitBase::onInstructionExecuted(const InstRef
&IR
) {
163 unsigned GroupID
= IR
.getInstruction()->getLSUTokenID();
164 auto It
= Groups
.find(GroupID
);
165 assert(It
!= Groups
.end() && "Instruction not dispatched to the LS unit");
166 It
->second
->onInstructionExecuted();
167 if (It
->second
->isExecuted())
171 void LSUnitBase::onInstructionRetired(const InstRef
&IR
) {
172 const InstrDesc
&Desc
= IR
.getInstruction()->getDesc();
173 bool IsALoad
= Desc
.MayLoad
;
174 bool IsAStore
= Desc
.MayStore
;
175 assert((IsALoad
|| IsAStore
) && "Expected a memory operation!");
179 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR
.getSourceIndex()
180 << " has been removed from the load queue.\n");
185 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR
.getSourceIndex()
186 << " has been removed from the store queue.\n");
190 void LSUnit::onInstructionExecuted(const InstRef
&IR
) {
191 const Instruction
&IS
= *IR
.getInstruction();
195 LSUnitBase::onInstructionExecuted(IR
);
196 unsigned GroupID
= IS
.getLSUTokenID();
197 if (!isValidGroupID(GroupID
)) {
198 if (GroupID
== CurrentLoadGroupID
)
199 CurrentLoadGroupID
= 0;
200 if (GroupID
== CurrentStoreGroupID
)
201 CurrentStoreGroupID
= 0;
202 if (GroupID
== CurrentLoadBarrierGroupID
)
203 CurrentLoadBarrierGroupID
= 0;