LLVM 22.0.0git
DependencyGraph.h
Go to the documentation of this file.
1//===- DependencyGraph.h ----------------------------------------*- 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//
9// This file declares the dependency graph used by the vectorizer's instruction
10// scheduler.
11//
12// The nodes of the graph are objects of the `DGNode` class. Each `DGNode`
13// object points to an instruction.
14// The edges between `DGNode`s are implicitly defined by an ordered set of
15// predecessor nodes, to save memory.
16// Finally the whole dependency graph is an object of the `DependencyGraph`
17// class, which also provides the API for creating/extending the graph from
18// input Sandbox IR.
19//
20//===----------------------------------------------------------------------===//
21
22#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
23#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
24
25#include "llvm/ADT/DenseMap.h"
32
33namespace llvm::sandboxir {
34
35class DependencyGraph;
36class MemDGNode;
37class SchedBundle;
38
39/// SubclassIDs for isa/dyn_cast etc.
40enum class DGNodeID {
41 DGNode,
43};
44
45class DGNode;
46class MemDGNode;
47class DependencyGraph;
48
49// Defined in Transforms/Vectorize/SandboxVectorizer/Interval.cpp
50extern template class LLVM_TEMPLATE_ABI Interval<MemDGNode>;
51
52/// Iterate over both def-use and mem dependencies.
57 DGNode *N = nullptr;
58 DependencyGraph *DAG = nullptr;
59
60 PredIterator(const User::op_iterator &OpIt, const User::op_iterator &OpItE,
62 DependencyGraph &DAG)
63 : OpIt(OpIt), OpItE(OpItE), MemIt(MemIt), N(N), DAG(&DAG) {}
64 PredIterator(const User::op_iterator &OpIt, const User::op_iterator &OpItE,
66 : OpIt(OpIt), OpItE(OpItE), N(N), DAG(&DAG) {}
67 friend class DGNode; // For constructor
68 friend class MemDGNode; // For constructor
69
70 /// Skip iterators that don't point instructions or are outside \p DAG,
71 /// starting from \p OpIt and ending before \p OpItE.n
72 LLVM_ABI static User::op_iterator skipBadIt(User::op_iterator OpIt,
74 const DependencyGraph &DAG);
75
76public:
77 using difference_type = std::ptrdiff_t;
78 using value_type = DGNode *;
81 using iterator_category = std::input_iterator_tag;
83 LLVM_ABI PredIterator &operator++();
85 auto Copy = *this;
86 ++(*this);
87 return Copy;
88 }
89 LLVM_ABI bool operator==(const PredIterator &Other) const;
90 bool operator!=(const PredIterator &Other) const { return !(*this == Other); }
91};
92
93/// A DependencyGraph Node that points to an Instruction and contains memory
94/// dependency edges.
96protected:
98 // TODO: Use a PointerIntPair for SubclassID and I.
99 /// For isa/dyn_cast etc.
101 /// The number of unscheduled successors.
102 unsigned UnscheduledSuccs = 0;
103 /// This is true if this node has been scheduled.
104 bool Scheduled = false;
105 /// The scheduler bundle that this node belongs to.
106 SchedBundle *SB = nullptr;
107
108 void setSchedBundle(SchedBundle &SB);
109 void clearSchedBundle() { this->SB = nullptr; }
110 friend class SchedBundle; // For setSchedBundle(), clearSchedBundle().
111
112 DGNode(Instruction *I, DGNodeID ID) : I(I), SubclassID(ID) {}
113 friend class MemDGNode; // For constructor.
114 friend class DependencyGraph; // For UnscheduledSuccs
115
116public:
117 DGNode(Instruction *I) : I(I), SubclassID(DGNodeID::DGNode) {
118 assert(!isMemDepNodeCandidate(I) && "Expected Non-Mem instruction, ");
119 }
120 DGNode(const DGNode &Other) = delete;
121 virtual ~DGNode();
122 /// \Returns the number of unscheduled successors.
123 unsigned getNumUnscheduledSuccs() const { return UnscheduledSuccs; }
124 // TODO: Make this private?
126 assert(UnscheduledSuccs > 0 && "Counting error!");
127 --UnscheduledSuccs;
128 }
129 void incrUnscheduledSuccs() { ++UnscheduledSuccs; }
131 UnscheduledSuccs = 0;
132 Scheduled = false;
133 }
134 /// \Returns true if all dependent successors have been scheduled.
135 bool ready() const { return UnscheduledSuccs == 0; }
136 /// \Returns true if this node has been scheduled.
137 bool scheduled() const { return Scheduled; }
138 void setScheduled(bool NewVal) { Scheduled = NewVal; }
139 /// \Returns the scheduling bundle that this node belongs to, or nullptr.
140 SchedBundle *getSchedBundle() const { return SB; }
141 /// \Returns true if this is before \p Other in program order.
142 bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); }
145 return PredIterator(
146 PredIterator::skipBadIt(I->op_begin(), I->op_end(), DAG), I->op_end(),
147 this, DAG);
148 }
150 return PredIterator(I->op_end(), I->op_end(), this, DAG);
151 }
153 return const_cast<DGNode *>(this)->preds_begin(DAG);
154 }
156 return const_cast<DGNode *>(this)->preds_end(DAG);
157 }
158 /// \Returns a range of DAG predecessors nodes. If this is a MemDGNode then
159 /// this will also include the memory dependency predecessors.
160 /// Please note that this can include the same node more than once, if for
161 /// example it's both a use-def predecessor and a mem dep predecessor.
163 return make_range(preds_begin(DAG), preds_end(DAG));
164 }
165
167 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
168 auto IID = II->getIntrinsicID();
169 return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave;
170 }
171 return false;
172 }
173
174 /// \Returns true if intrinsic \p I touches memory. This is used by the
175 /// dependency graph.
177 auto IID = I->getIntrinsicID();
178 return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe;
179 }
180
181 /// We consider \p I as a Memory Dependency Candidate instruction if it
182 /// reads/write memory or if it has side-effects. This is used by the
183 /// dependency graph.
186 return I->mayReadOrWriteMemory() &&
187 (!(II = dyn_cast<IntrinsicInst>(I)) || isMemIntrinsic(II));
188 }
189
190 /// \Returns true if \p I is fence like. It excludes non-mem intrinsics.
191 static bool isFenceLike(Instruction *I) {
193 return I->isFenceLike() &&
194 (!(II = dyn_cast<IntrinsicInst>(I)) || isMemIntrinsic(II));
195 }
196
197 /// \Returns true if \p I is a memory dependency candidate instruction.
199 AllocaInst *Alloca;
200 return isMemDepCandidate(I) ||
201 ((Alloca = dyn_cast<AllocaInst>(I)) &&
202 Alloca->isUsedWithInAlloca()) ||
203 isStackSaveOrRestoreIntrinsic(I) || isFenceLike(I);
204 }
205
206 Instruction *getInstruction() const { return I; }
207
208#ifndef NDEBUG
209 virtual void print(raw_ostream &OS, bool PrintDeps = true) const;
211 N.print(OS);
212 return OS;
213 }
214 LLVM_DUMP_METHOD void dump() const;
215#endif // NDEBUG
216};
217
218/// A DependencyGraph Node for instructions that may read/write memory, or have
219/// some ordering constraints, like with stacksave/stackrestore and
220/// alloca/inalloca.
221class MemDGNode final : public DGNode {
222 MemDGNode *PrevMemN = nullptr;
223 MemDGNode *NextMemN = nullptr;
224 /// Memory predecessors.
225 DenseSet<MemDGNode *> MemPreds;
226 /// Memory successors.
227 DenseSet<MemDGNode *> MemSuccs;
228 friend class PredIterator; // For MemPreds.
229 /// Creates both edges: this<->N.
230 void setNextNode(MemDGNode *N) {
231 assert(N != this && "About to point to self!");
232 NextMemN = N;
233 if (NextMemN != nullptr)
234 NextMemN->PrevMemN = this;
235 }
236 /// Creates both edges: N<->this.
237 void setPrevNode(MemDGNode *N) {
238 assert(N != this && "About to point to self!");
239 PrevMemN = N;
240 if (PrevMemN != nullptr)
241 PrevMemN->NextMemN = this;
242 }
243 friend class DependencyGraph; // For setNextNode(), setPrevNode().
244 void detachFromChain() {
245 if (PrevMemN != nullptr)
246 PrevMemN->NextMemN = NextMemN;
247 if (NextMemN != nullptr)
248 NextMemN->PrevMemN = PrevMemN;
249 PrevMemN = nullptr;
250 NextMemN = nullptr;
251 }
252
253public:
255 assert(isMemDepNodeCandidate(I) && "Expected Mem instruction!");
256 }
257 static bool classof(const DGNode *Other) {
258 return Other->SubclassID == DGNodeID::MemDGNode;
259 }
261 auto OpEndIt = I->op_end();
262 return PredIterator(PredIterator::skipBadIt(I->op_begin(), OpEndIt, DAG),
263 OpEndIt, MemPreds.begin(), this, DAG);
264 }
266 return PredIterator(I->op_end(), I->op_end(), MemPreds.end(), this, DAG);
267 }
268 /// \Returns the previous Mem DGNode in instruction order.
269 MemDGNode *getPrevNode() const { return PrevMemN; }
270 /// \Returns the next Mem DGNode in instruction order.
271 MemDGNode *getNextNode() const { return NextMemN; }
272 /// Adds the mem dependency edge PredN->this. This also increments the
273 /// UnscheduledSuccs counter of the predecessor if this node has not been
274 /// scheduled.
275 void addMemPred(MemDGNode *PredN) {
276 [[maybe_unused]] auto Inserted = MemPreds.insert(PredN).second;
277 assert(Inserted && "PredN already exists!");
278 assert(PredN != this && "Trying to add a dependency to self!");
279 PredN->MemSuccs.insert(this);
280 if (!Scheduled) {
281 ++PredN->UnscheduledSuccs;
282 }
283 }
284 /// Removes the memory dependency PredN->this. This also updates the
285 /// UnscheduledSuccs counter of PredN if this node has not been scheduled.
287 MemPreds.erase(PredN);
288 PredN->MemSuccs.erase(this);
289 if (!Scheduled) {
290 PredN->decrUnscheduledSuccs();
291 }
292 }
293 /// \Returns true if there is a memory dependency N->this.
294 bool hasMemPred(DGNode *N) const {
295 if (auto *MN = dyn_cast<MemDGNode>(N))
296 return MemPreds.count(MN);
297 return false;
298 }
299 /// \Returns all memory dependency predecessors. Used by tests.
301 return make_range(MemPreds.begin(), MemPreds.end());
302 }
303 /// \Returns all memory dependency successors.
305 return make_range(MemSuccs.begin(), MemSuccs.end());
306 }
307#ifndef NDEBUG
308 virtual void print(raw_ostream &OS, bool PrintDeps = true) const override;
309#endif // NDEBUG
310};
311
312/// Convenience builders for a MemDGNode interval.
314public:
315 /// Scans the instruction chain in \p Intvl top-down, returning the top-most
316 /// MemDGNode, or nullptr.
318 const DependencyGraph &DAG);
319 /// Scans the instruction chain in \p Intvl bottom-up, returning the
320 /// bottom-most MemDGNode, or nullptr.
322 const DependencyGraph &DAG);
323 /// Given \p Instrs it finds their closest mem nodes in the interval and
324 /// returns the corresponding mem range. Note: BotN (or its neighboring mem
325 /// node) is included in the range.
327 DependencyGraph &DAG);
328 static Interval<MemDGNode> makeEmpty() { return {}; }
329};
330
332private:
334 /// The DAG spans across all instructions in this interval.
335 Interval<Instruction> DAGInterval;
336
337 Context *Ctx = nullptr;
338 std::optional<Context::CallbackID> CreateInstrCB;
339 std::optional<Context::CallbackID> EraseInstrCB;
340 std::optional<Context::CallbackID> MoveInstrCB;
341 std::optional<Context::CallbackID> SetUseCB;
342
343 std::unique_ptr<BatchAAResults> BatchAA;
344
345 enum class DependencyType {
346 ReadAfterWrite, ///> Memory dependency write -> read
347 WriteAfterWrite, ///> Memory dependency write -> write
348 WriteAfterRead, ///> Memory dependency read -> write
349 Control, ///> Control-related dependency, like with PHI/Terminator
350 Other, ///> Currently used for stack related instrs
351 None, ///> No memory/other dependency
352 };
353 /// \Returns the dependency type depending on whether instructions may
354 /// read/write memory or whether they are some specific opcode-related
355 /// restrictions.
356 /// Note: It does not check whether a memory dependency is actually correct,
357 /// as it won't call AA. Therefore it returns the worst-case dep type.
358 static DependencyType getRoughDepType(Instruction *FromI, Instruction *ToI);
359
360 // TODO: Implement AABudget.
361 /// \Returns true if there is a memory/other dependency \p SrcI->DstI.
362 bool alias(Instruction *SrcI, Instruction *DstI, DependencyType DepType);
363
364 bool hasDep(sandboxir::Instruction *SrcI, sandboxir::Instruction *DstI);
365
366 /// Go through all mem nodes in \p SrcScanRange and try to add dependencies to
367 /// \p DstN.
368 void scanAndAddDeps(MemDGNode &DstN, const Interval<MemDGNode> &SrcScanRange);
369
370 /// Sets the UnscheduledSuccs of all DGNodes in \p NewInterval based on
371 /// def-use edges.
372 void setDefUseUnscheduledSuccs(const Interval<Instruction> &NewInterval);
373
374 /// Create DAG nodes for instrs in \p NewInterval and update the MemNode
375 /// chain.
376 void createNewNodes(const Interval<Instruction> &NewInterval);
377
378 /// Helper for `notify*Instr()`. \Returns the first MemDGNode that comes
379 /// before \p N, skipping \p SkipN, including or excluding \p N based on
380 /// \p IncludingN, or nullptr if not found.
381 MemDGNode *getMemDGNodeBefore(DGNode *N, bool IncludingN,
382 MemDGNode *SkipN = nullptr) const;
383 /// Helper for `notifyMoveInstr()`. \Returns the first MemDGNode that comes
384 /// after \p N, skipping \p SkipN, including or excluding \p N based on \p
385 /// IncludingN, or nullptr if not found.
386 MemDGNode *getMemDGNodeAfter(DGNode *N, bool IncludingN,
387 MemDGNode *SkipN = nullptr) const;
388
389 /// Called by the callbacks when a new instruction \p I has been created.
390 LLVM_ABI void notifyCreateInstr(Instruction *I);
391 /// Called by the callbacks when instruction \p I is about to get
392 /// deleted.
393 LLVM_ABI void notifyEraseInstr(Instruction *I);
394 /// Called by the callbacks when instruction \p I is about to be moved to
395 /// \p To.
396 LLVM_ABI void notifyMoveInstr(Instruction *I, const BBIterator &To);
397 /// Called by the callbacks when \p U's source is about to be set to \p NewSrc
398 LLVM_ABI void notifySetUse(const Use &U, Value *NewSrc);
399
400public:
401 /// This constructor also registers callbacks.
403 : Ctx(&Ctx), BatchAA(std::make_unique<BatchAAResults>(AA)) {
404 CreateInstrCB = Ctx.registerCreateInstrCallback(
405 [this](Instruction *I) { notifyCreateInstr(I); });
406 EraseInstrCB = Ctx.registerEraseInstrCallback(
407 [this](Instruction *I) { notifyEraseInstr(I); });
408 MoveInstrCB = Ctx.registerMoveInstrCallback(
409 [this](Instruction *I, const BBIterator &To) {
410 notifyMoveInstr(I, To);
411 });
412 SetUseCB = Ctx.registerSetUseCallback(
413 [this](const Use &U, Value *NewSrc) { notifySetUse(U, NewSrc); });
414 }
416 if (CreateInstrCB)
417 Ctx->unregisterCreateInstrCallback(*CreateInstrCB);
418 if (EraseInstrCB)
419 Ctx->unregisterEraseInstrCallback(*EraseInstrCB);
420 if (MoveInstrCB)
421 Ctx->unregisterMoveInstrCallback(*MoveInstrCB);
422 if (SetUseCB)
423 Ctx->unregisterSetUseCallback(*SetUseCB);
424 }
425
427 auto It = InstrToNodeMap.find(I);
428 return It != InstrToNodeMap.end() ? It->second.get() : nullptr;
429 }
430 /// Like getNode() but returns nullptr if \p I is nullptr.
432 if (I == nullptr)
433 return nullptr;
434 return getNode(I);
435 }
437 auto [It, NotInMap] = InstrToNodeMap.try_emplace(I);
438 if (NotInMap) {
440 It->second = std::make_unique<MemDGNode>(I);
441 else
442 It->second = std::make_unique<DGNode>(I);
443 }
444 return It->second.get();
445 }
446 /// Build/extend the dependency graph such that it includes \p Instrs. Returns
447 /// the range of instructions added to the DAG.
449 /// \Returns the range of instructions included in the DAG.
450 Interval<Instruction> getInterval() const { return DAGInterval; }
451 void clear() {
452 InstrToNodeMap.clear();
453 DAGInterval = {};
454 }
455#ifndef NDEBUG
456 /// \Returns true if the DAG's state is clear. Used in assertions.
457 bool empty() const {
458 bool IsEmpty = InstrToNodeMap.empty();
459 assert(IsEmpty == DAGInterval.empty() &&
460 "Interval and InstrToNodeMap out of sync!");
461 return IsEmpty;
462 }
463 void print(raw_ostream &OS) const;
464 LLVM_DUMP_METHOD void dump() const;
465#endif // NDEBUG
466};
467} // namespace llvm::sandboxir
468
469#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_TEMPLATE_ABI
Definition: Compiler.h:214
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:638
This file defines the DenseMap class.
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1328
#define I(x, y, z)
Definition: MD5.cpp:58
std::pair< uint64_t, uint64_t > Interval
uint64_t IntrinsicInst * II
raw_pwrite_stream & OS
A private abstract base class describing the concept of an individual alias analysis implementation.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
Represent a node in the directed graph.
Definition: DirectedGraph.h:73
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:177
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition: DenseMap.h:245
bool empty() const
Definition: DenseMap.h:119
iterator end()
Definition: DenseMap.h:87
Implements a dense probed hash-table based set.
Definition: DenseSet.h:263
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:194
DenseSetIterator< false > iterator
Definition: DenseSet.h:154
bool erase(const ValueT &V)
Definition: DenseSet.h:100
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition: DenseSet.h:174
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
Definition: Instruction.h:2255
Iterator for Instructions in a `BasicBlock.
Definition: BasicBlock.h:24
LLVM_ABI void unregisterSetUseCallback(CallbackID ID)
Definition: Context.cpp:775
LLVM_ABI CallbackID registerSetUseCallback(SetUseCallback CB)
Register a callback that gets called when a Use gets set.
Definition: Context.cpp:768
LLVM_ABI CallbackID registerCreateInstrCallback(CreateInstrCallback CB)
Register a callback that gets called right after a SandboxIR instruction is created.
Definition: Context.cpp:742
LLVM_ABI void unregisterCreateInstrCallback(CallbackID ID)
Definition: Context.cpp:749
LLVM_ABI void unregisterMoveInstrCallback(CallbackID ID)
Definition: Context.cpp:762
LLVM_ABI void unregisterEraseInstrCallback(CallbackID ID)
Definition: Context.cpp:735
LLVM_ABI CallbackID registerMoveInstrCallback(MoveInstrCallback CB)
Register a callback that gets called when a SandboxIR instruction is about to be moved.
Definition: Context.cpp:755
LLVM_ABI CallbackID registerEraseInstrCallback(EraseInstrCallback CB)
Register a callback that gets called when a SandboxIR instruction is about to be removed from its par...
Definition: Context.cpp:728
A DependencyGraph Node that points to an Instruction and contains memory dependency edges.
static bool isMemDepCandidate(Instruction *I)
We consider I as a Memory Dependency Candidate instruction if it reads/write memory or if it has side...
virtual iterator preds_end(DependencyGraph &DAG)
static bool isMemIntrinsic(IntrinsicInst *I)
\Returns true if intrinsic I touches memory.
iterator preds_begin(DependencyGraph &DAG) const
DGNode(Instruction *I, DGNodeID ID)
unsigned getNumUnscheduledSuccs() const
\Returns the number of unscheduled successors.
bool scheduled() const
\Returns true if this node has been scheduled.
unsigned UnscheduledSuccs
The number of unscheduled successors.
void setScheduled(bool NewVal)
bool ready() const
\Returns true if all dependent successors have been scheduled.
iterator_range< iterator > preds(DependencyGraph &DAG) const
\Returns a range of DAG predecessors nodes.
iterator preds_end(DependencyGraph &DAG) const
static bool isMemDepNodeCandidate(Instruction *I)
\Returns true if I is a memory dependency candidate instruction.
SchedBundle * getSchedBundle() const
\Returns the scheduling bundle that this node belongs to, or nullptr.
DGNodeID SubclassID
For isa/dyn_cast etc.
DGNode(const DGNode &Other)=delete
static bool isFenceLike(Instruction *I)
\Returns true if I is fence like. It excludes non-mem intrinsics.
Instruction * getInstruction() const
static bool isStackSaveOrRestoreIntrinsic(Instruction *I)
bool comesBefore(const DGNode *Other)
\Returns true if this is before Other in program order.
friend raw_ostream & operator<<(raw_ostream &OS, DGNode &N)
virtual iterator preds_begin(DependencyGraph &DAG)
Interval< Instruction > getInterval() const
\Returns the range of instructions included in the DAG.
bool empty() const
\Returns true if the DAG's state is clear. Used in assertions.
LLVM_DUMP_METHOD void dump() const
DGNode * getNode(Instruction *I) const
DependencyGraph(AAResults &AA, Context &Ctx)
This constructor also registers callbacks.
DGNode * getNodeOrNull(Instruction *I) const
Like getNode() but returns nullptr if I is nullptr.
void print(raw_ostream &OS) const
DGNode * getOrCreateNode(Instruction *I)
LLVM_ABI Interval< Instruction > extend(ArrayRef< Instruction * > Instrs)
Build/extend the dependency graph such that it includes Instrs.
A sandboxir::User with operands, opcode and linked with previous/next instructions in an instruction ...
Definition: Instruction.h:43
Convenience builders for a MemDGNode interval.
static LLVM_ABI MemDGNode * getBotMemDGNode(const Interval< Instruction > &Intvl, const DependencyGraph &DAG)
Scans the instruction chain in Intvl bottom-up, returning the bottom-most MemDGNode,...
static Interval< MemDGNode > makeEmpty()
static LLVM_ABI MemDGNode * getTopMemDGNode(const Interval< Instruction > &Intvl, const DependencyGraph &DAG)
Scans the instruction chain in Intvl top-down, returning the top-most MemDGNode, or nullptr.
static LLVM_ABI Interval< MemDGNode > make(const Interval< Instruction > &Instrs, DependencyGraph &DAG)
Given Instrs it finds their closest mem nodes in the interval and returns the corresponding mem range...
A DependencyGraph Node for instructions that may read/write memory, or have some ordering constraints...
iterator preds_end(DependencyGraph &DAG) override
iterator preds_begin(DependencyGraph &DAG) override
bool hasMemPred(DGNode *N) const
\Returns true if there is a memory dependency N->this.
static bool classof(const DGNode *Other)
iterator_range< DenseSet< MemDGNode * >::const_iterator > memPreds() const
\Returns all memory dependency predecessors. Used by tests.
MemDGNode * getNextNode() const
\Returns the next Mem DGNode in instruction order.
iterator_range< DenseSet< MemDGNode * >::const_iterator > memSuccs() const
\Returns all memory dependency successors.
void removeMemPred(MemDGNode *PredN)
Removes the memory dependency PredN->this.
MemDGNode * getPrevNode() const
\Returns the previous Mem DGNode in instruction order.
void addMemPred(MemDGNode *PredN)
Adds the mem dependency edge PredN->this.
Iterator for the Use edges of a User's operands.
Definition: User.h:24
Iterate over both def-use and mem dependencies.
bool operator!=(const PredIterator &Other) const
std::input_iterator_tag iterator_category
The nodes that need to be scheduled back-to-back in a single scheduling cycle form a SchedBundle.
Definition: Scheduler.h:108
Represents a Def-use/Use-def edge in SandboxIR.
Definition: Use.h:33
A SandboxIR Value has users. This is the base class.
Definition: Value.h:66
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
DGNodeID
SubclassIDs for isa/dyn_cast etc.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
APInt operator*(APInt a, uint64_t RHS)
Definition: APInt.h:2235
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
@ None
Definition: CodeGenData.h:107
@ Other
Any other memory.
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
#define N