1 //===----------------------- LSUnit.cpp --------------------------*- C++-*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// A Load-Store Unit for the llvm-mca tool.
13 //===----------------------------------------------------------------------===//
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"
20 #define DEBUG_TYPE "llvm-mca"
25 LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ,
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;
35 if (!SQ_Size && EPI.StoreQueueID) {
36 const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID);
37 SQ_Size = StQDesc.BufferSize;
43 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';
51 void LSUnit::assignLQSlot(unsigned Index) {
53 assert(LoadQueue.count(Index) == 0);
55 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index
56 << ",slot=" << LoadQueue.size() << ">\n");
57 LoadQueue.insert(Index);
60 void LSUnit::assignSQSlot(unsigned Index) {
62 assert(StoreQueue.count(Index) == 0);
64 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index
65 << ",slot=" << StoreQueue.size() << ">\n");
66 StoreQueue.insert(Index);
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!");
74 const unsigned Index = IR.getSourceIndex();
77 LoadBarriers.insert(Index);
83 StoreBarriers.insert(Index);
88 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;
97 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!");
106 if (IsALoad && !LoadBarriers.empty()) {
107 unsigned LoadBarrierIndex = *LoadBarriers.begin();
108 // A younger load cannot pass a older load barrier.
109 if (Index > LoadBarrierIndex)
111 // A load barrier cannot pass a older load.
112 if (Index == LoadBarrierIndex && Index != *LoadQueue.begin())
116 if (IsAStore && !StoreBarriers.empty()) {
117 unsigned StoreBarrierIndex = *StoreBarriers.begin();
118 // A younger store cannot pass a older store barrier.
119 if (Index > StoreBarrierIndex)
121 // A store barrier cannot pass a older store.
122 if (Index == StoreBarrierIndex && Index != *StoreQueue.begin())
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)
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())
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.
144 // Check if there are no older loads.
145 if (Index <= *LoadQueue.begin())
148 // There is at least one younger load.
150 // A store may not pass a previous load.
151 // A load may pass a previous load.
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;
162 if (LoadQueue.erase(Index)) {
163 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
164 << " has been removed from the load queue.\n");
166 if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) {
168 dbgs() << "[LSUnit]: Instruction idx=" << Index
169 << " has been removed from the set of load barriers.\n");
170 LoadBarriers.erase(Index);
175 if (StoreQueue.erase(Index)) {
176 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
177 << " has been removed from the store queue.\n");
180 if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) {
182 dbgs() << "[LSUnit]: Instruction idx=" << Index
183 << " has been removed from the set of store barriers.\n");
184 StoreBarriers.erase(Index);