LLVM  9.0.0svn
LSUnit.cpp
Go to the documentation of this file.
1 //===----------------------- LSUnit.cpp --------------------------*- C++-*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// A Load-Store Unit for the llvm-mca tool.
11 ///
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/MCA/Instruction.h"
16 #include "llvm/Support/Debug.h"
18 
19 #define DEBUG_TYPE "llvm-mca"
20 
21 namespace llvm {
22 namespace mca {
23 
24 LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ,
25  bool AssumeNoAlias)
26  : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) {
27  if (SM.hasExtraProcessorInfo()) {
29  if (!LQ_Size && EPI.LoadQueueID) {
30  const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID);
31  LQ_Size = LdQDesc.BufferSize;
32  }
33 
34  if (!SQ_Size && EPI.StoreQueueID) {
35  const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID);
36  SQ_Size = StQDesc.BufferSize;
37  }
38  }
39 }
40 
41 #ifndef NDEBUG
42 void LSUnit::dump() const {
43  dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n';
44  dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n';
45  dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n';
46  dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n';
47 }
48 #endif
49 
50 void LSUnit::assignLQSlot(unsigned Index) {
51  assert(!isLQFull());
52  assert(LoadQueue.count(Index) == 0);
53 
54  LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index
55  << ",slot=" << LoadQueue.size() << ">\n");
56  LoadQueue.insert(Index);
57 }
58 
59 void LSUnit::assignSQSlot(unsigned Index) {
60  assert(!isSQFull());
61  assert(StoreQueue.count(Index) == 0);
62 
63  LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index
64  << ",slot=" << StoreQueue.size() << ">\n");
65  StoreQueue.insert(Index);
66 }
67 
68 void LSUnit::dispatch(const InstRef &IR) {
69  const InstrDesc &Desc = IR.getInstruction()->getDesc();
70  unsigned IsMemBarrier = Desc.HasSideEffects;
71  assert((Desc.MayLoad || Desc.MayStore) && "Not a memory operation!");
72 
73  const unsigned Index = IR.getSourceIndex();
74  if (Desc.MayLoad) {
75  if (IsMemBarrier)
76  LoadBarriers.insert(Index);
77  assignLQSlot(Index);
78  }
79 
80  if (Desc.MayStore) {
81  if (IsMemBarrier)
82  StoreBarriers.insert(Index);
83  assignSQSlot(Index);
84  }
85 }
86 
88  const InstrDesc &Desc = IR.getInstruction()->getDesc();
89  if (Desc.MayLoad && isLQFull())
91  if (Desc.MayStore && isSQFull())
93  return LSUnit::LSU_AVAILABLE;
94 }
95 
96 unsigned LSUnit::isReady(const InstRef &IR) const {
97  const InstrDesc &Desc = IR.getInstruction()->getDesc();
98  const unsigned Index = IR.getSourceIndex();
99  bool IsALoad = Desc.MayLoad;
100  bool IsAStore = Desc.MayStore;
101  assert((IsALoad || IsAStore) && "Not a memory operation!");
102  assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!");
103  assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!");
104 
105  if (IsALoad && !LoadBarriers.empty()) {
106  unsigned LoadBarrierIndex = *LoadBarriers.begin();
107  // A younger load cannot pass a older load barrier.
108  if (Index > LoadBarrierIndex)
109  return LoadBarrierIndex;
110  // A load barrier cannot pass a older load.
111  if (Index == LoadBarrierIndex && Index != *LoadQueue.begin())
112  return *LoadQueue.begin();
113  }
114 
115  if (IsAStore && !StoreBarriers.empty()) {
116  unsigned StoreBarrierIndex = *StoreBarriers.begin();
117  // A younger store cannot pass a older store barrier.
118  if (Index > StoreBarrierIndex)
119  return StoreBarrierIndex;
120  // A store barrier cannot pass a older store.
121  if (Index == StoreBarrierIndex && Index != *StoreQueue.begin())
122  return *StoreQueue.begin();
123  }
124 
125  // A load may not pass a previous store unless flag 'NoAlias' is set.
126  // A load may pass a previous load.
127  if (NoAlias && IsALoad)
128  return Index;
129 
130  if (StoreQueue.size()) {
131  // A load may not pass a previous store.
132  // A store may not pass a previous store.
133  if (Index > *StoreQueue.begin())
134  return *StoreQueue.begin();
135  }
136 
137  // Okay, we are older than the oldest store in the queue.
138  // If there are no pending loads, then we can say for sure that this
139  // instruction is ready.
140  if (isLQEmpty())
141  return Index;
142 
143  // Check if there are no older loads.
144  if (Index <= *LoadQueue.begin())
145  return Index;
146 
147  // There is at least one younger load.
148  //
149  // A load may pass a previous load.
150  if (IsALoad)
151  return Index;
152 
153  // A store may not pass a previous load.
154  return *LoadQueue.begin();
155 }
156 
158  const InstrDesc &Desc = IR.getInstruction()->getDesc();
159  const unsigned Index = IR.getSourceIndex();
160  bool IsALoad = Desc.MayLoad;
161  bool IsAStore = Desc.MayStore;
162 
163  if (IsALoad) {
164  if (LoadQueue.erase(Index)) {
165  LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
166  << " has been removed from the load queue.\n");
167  }
168  if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) {
169  LLVM_DEBUG(
170  dbgs() << "[LSUnit]: Instruction idx=" << Index
171  << " has been removed from the set of load barriers.\n");
172  LoadBarriers.erase(Index);
173  }
174  }
175 
176  if (IsAStore) {
177  if (StoreQueue.erase(Index)) {
178  LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
179  << " has been removed from the store queue.\n");
180  }
181 
182  if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) {
183  LLVM_DEBUG(
184  dbgs() << "[LSUnit]: Instruction idx=" << Index
185  << " has been removed from the set of store barriers.\n");
186  StoreBarriers.erase(Index);
187  }
188  }
189 }
190 
191 } // namespace mca
192 } // namespace llvm
Instruction * getInstruction()
Definition: Instruction.h:531
Status isAvailable(const InstRef &IR) const
Definition: LSUnit.cpp:87
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition: MCSchedule.h:339
The two locations do not alias at all.
Definition: AliasAnalysis.h:84
virtual unsigned isReady(const InstRef &IR) const
Definition: LSUnit.cpp:96
void onInstructionExecuted(const InstRef &IR)
Definition: LSUnit.cpp:157
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:521
bool erase(const T &V)
Definition: SmallSet.h:207
void dump() const
Definition: LSUnit.cpp:42
A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...
unsigned getSourceIndex() const
Definition: Instruction.h:530
LLVM_NODISCARD bool empty() const
Definition: SmallSet.h:155
const_iterator begin() const
Definition: SmallSet.h:223
Provide extra details about the machine processor.
Definition: MCSchedule.h:177
const InstrDesc & getDesc() const
Definition: Instruction.h:404
bool hasExtraProcessorInfo() const
Definition: MCSchedule.h:315
size_type size() const
Definition: SmallSet.h:159
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:180
LSUnit(const MCSchedModel &SM, unsigned LQ=0, unsigned SQ=0, bool AssumeNoAlias=false)
Definition: LSUnit.cpp:24
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:132
An instruction descriptor.
Definition: Instruction.h:337
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
void dispatch(const InstRef &IR)
Definition: LSUnit.cpp:68
const MCExtraProcessorInfo & getExtraProcessorInfo() const
Definition: MCSchedule.h:322
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define LLVM_DEBUG(X)
Definition: Debug.h:122
Machine model for scheduling, bundling, and heuristics.
Definition: MCSchedule.h:244
Statically lint checks LLVM IR
Definition: Lint.cpp:192
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition: SmallSet.h:164