]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/MCA/HardwareUnits/LSUnit.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / MCA / HardwareUnits / LSUnit.cpp
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
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
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';
48 }
49 #endif
50
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
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
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
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;
95 }
96
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!");
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
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