1 //===----------------------- LSUnit.cpp --------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// A Load-Store Unit for the llvm-mca tool.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/MCA/HardwareUnits/LSUnit.h"
16 #include "llvm/MCA/Instruction.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 #define DEBUG_TYPE "llvm-mca"
21
22 namespace llvm {
23 namespace mca {
24
LSUnit(const MCSchedModel & SM,unsigned LQ,unsigned SQ,bool AssumeNoAlias)25 LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ,
26 bool AssumeNoAlias)
27 : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) {
28 if (SM.hasExtraProcessorInfo()) {
29 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
30 if (!LQ_Size && EPI.LoadQueueID) {
31 const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID);
32 LQ_Size = LdQDesc.BufferSize;
33 }
34
35 if (!SQ_Size && EPI.StoreQueueID) {
36 const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID);
37 SQ_Size = StQDesc.BufferSize;
38 }
39 }
40 }
41
42 #ifndef NDEBUG
dump() const43 void LSUnit::dump() const {
44 dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n';
45 dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n';
46 dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n';
47 dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n';
48 }
49 #endif
50
assignLQSlot(unsigned Index)51 void LSUnit::assignLQSlot(unsigned Index) {
52 assert(!isLQFull());
53 assert(LoadQueue.count(Index) == 0);
54
55 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index
56 << ",slot=" << LoadQueue.size() << ">\n");
57 LoadQueue.insert(Index);
58 }
59
assignSQSlot(unsigned Index)60 void LSUnit::assignSQSlot(unsigned Index) {
61 assert(!isSQFull());
62 assert(StoreQueue.count(Index) == 0);
63
64 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index
65 << ",slot=" << StoreQueue.size() << ">\n");
66 StoreQueue.insert(Index);
67 }
68
dispatch(const InstRef & IR)69 void 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!");
73
74 const unsigned Index = IR.getSourceIndex();
75 if (Desc.MayLoad) {
76 if (IsMemBarrier)
77 LoadBarriers.insert(Index);
78 assignLQSlot(Index);
79 }
80
81 if (Desc.MayStore) {
82 if (IsMemBarrier)
83 StoreBarriers.insert(Index);
84 assignSQSlot(Index);
85 }
86 }
87
isAvailable(const InstRef & IR) const88 LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const {
89 const InstrDesc &Desc = IR.getInstruction()->getDesc();
90 if (Desc.MayLoad && isLQFull())
91 return LSUnit::LSU_LQUEUE_FULL;
92 if (Desc.MayStore && isSQFull())
93 return LSUnit::LSU_SQUEUE_FULL;
94 return LSUnit::LSU_AVAILABLE;
95 }
96
isReady(const InstRef & IR) const97 bool LSUnit::isReady(const InstRef &IR) const {
98 const InstrDesc &Desc = IR.getInstruction()->getDesc();
99 const unsigned Index = IR.getSourceIndex();
100 bool IsALoad = Desc.MayLoad;
101 bool IsAStore = Desc.MayStore;
102 assert((IsALoad || IsAStore) && "Not a memory operation!");
103 assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!");
104 assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!");
105
106 if (IsALoad && !LoadBarriers.empty()) {
107 unsigned LoadBarrierIndex = *LoadBarriers.begin();
108 // A younger load cannot pass a older load barrier.
109 if (Index > LoadBarrierIndex)
110 return false;
111 // A load barrier cannot pass a older load.
112 if (Index == LoadBarrierIndex && Index != *LoadQueue.begin())
113 return false;
114 }
115
116 if (IsAStore && !StoreBarriers.empty()) {
117 unsigned StoreBarrierIndex = *StoreBarriers.begin();
118 // A younger store cannot pass a older store barrier.
119 if (Index > StoreBarrierIndex)
120 return false;
121 // A store barrier cannot pass a older store.
122 if (Index == StoreBarrierIndex && Index != *StoreQueue.begin())
123 return false;
124 }
125
126 // A load may not pass a previous store unless flag 'NoAlias' is set.
127 // A load may pass a previous load.
128 if (NoAlias && IsALoad)
129 return true;
130
131 if (StoreQueue.size()) {
132 // A load may not pass a previous store.
133 // A store may not pass a previous store.
134 if (Index > *StoreQueue.begin())
135 return false;
136 }
137
138 // Okay, we are older than the oldest store in the queue.
139 // If there are no pending loads, then we can say for sure that this
140 // instruction is ready.
141 if (isLQEmpty())
142 return true;
143
144 // Check if there are no older loads.
145 if (Index <= *LoadQueue.begin())
146 return true;
147
148 // There is at least one younger load.
149 //
150 // A store may not pass a previous load.
151 // A load may pass a previous load.
152 return !IsAStore;
153 }
154
onInstructionExecuted(const InstRef & IR)155 void LSUnit::onInstructionExecuted(const InstRef &IR) {
156 const InstrDesc &Desc = IR.getInstruction()->getDesc();
157 const unsigned Index = IR.getSourceIndex();
158 bool IsALoad = Desc.MayLoad;
159 bool IsAStore = Desc.MayStore;
160
161 if (IsALoad) {
162 if (LoadQueue.erase(Index)) {
163 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
164 << " has been removed from the load queue.\n");
165 }
166 if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) {
167 LLVM_DEBUG(
168 dbgs() << "[LSUnit]: Instruction idx=" << Index
169 << " has been removed from the set of load barriers.\n");
170 LoadBarriers.erase(Index);
171 }
172 }
173
174 if (IsAStore) {
175 if (StoreQueue.erase(Index)) {
176 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
177 << " has been removed from the store queue.\n");
178 }
179
180 if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) {
181 LLVM_DEBUG(
182 dbgs() << "[LSUnit]: Instruction idx=" << Index
183 << " has been removed from the set of store barriers.\n");
184 StoreBarriers.erase(Index);
185 }
186 }
187 }
188
189 } // namespace mca
190 } // namespace llvm
191