LLVM  8.0.1
LSUnit.cpp
Go to the documentation of this file.
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 
16 #include "llvm/MCA/Instruction.h"
17 #include "llvm/Support/Debug.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()) {
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 
89  const InstrDesc &Desc = IR.getInstruction()->getDesc();
90  if (Desc.MayLoad && isLQFull())
92  if (Desc.MayStore && isSQFull())
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 
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
Instruction * getInstruction()
Definition: Instruction.h:488
Status isAvailable(const InstRef &IR) const
Definition: LSUnit.cpp:88
virtual bool isReady(const InstRef &IR) const
Definition: LSUnit.cpp:97
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition: MCSchedule.h:339
The two locations do not alias at all.
Definition: AliasAnalysis.h:84
void onInstructionExecuted(const InstRef &IR)
Definition: LSUnit.cpp:155
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:478
bool erase(const T &V)
Definition: SmallSet.h:208
void dump() const
Definition: LSUnit.cpp:43
A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...
unsigned getSourceIndex() const
Definition: Instruction.h:487
LLVM_NODISCARD bool empty() const
Definition: SmallSet.h:156
const_iterator begin() const
Definition: SmallSet.h:224
Provide extra details about the machine processor.
Definition: MCSchedule.h:177
const InstrDesc & getDesc() const
Definition: Instruction.h:382
bool hasExtraProcessorInfo() const
Definition: MCSchedule.h:315
size_type size() const
Definition: SmallSet.h:160
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn&#39;t already there.
Definition: SmallSet.h:181
LSUnit(const MCSchedModel &SM, unsigned LQ=0, unsigned SQ=0, bool AssumeNoAlias=false)
Definition: LSUnit.cpp:25
Define a kind of processor resource that will be modeled by the scheduler.
Definition: MCSchedule.h:32
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
An instruction descriptor.
Definition: Instruction.h:322
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
void dispatch(const InstRef &IR)
Definition: LSUnit.cpp:69
const MCExtraProcessorInfo & getExtraProcessorInfo() const
Definition: MCSchedule.h:322
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define LLVM_DEBUG(X)
Definition: Debug.h:123
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:244
Statically lint checks LLVM IR
Definition: Lint.cpp:193
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition: SmallSet.h:165