LLVM 24.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"
33
34namespace llvm::sandboxir {
35
36class DependencyGraph;
37class MemDGNode;
38class SchedBundle;
39
44#ifndef NDEBUG
45StringLiteral schedDirectionToStr(SchedDirection Dir);
46#endif
47
48/// SubclassIDs for isa/dyn_cast etc.
49enum class DGNodeID {
52};
53
54class DGNode;
55class MemDGNode;
56class DependencyGraph;
57
58// Defined in Transforms/Vectorize/SandboxVectorizer/Interval.cpp
59extern template class LLVM_TEMPLATE_ABI Interval<MemDGNode>;
60
61/// Iterate over both def-use and mem dependencies.
62class PredIterator {
66 DGNode *N = nullptr;
67 DependencyGraph *DAG = nullptr;
68
69 PredIterator(const User::op_iterator &OpIt, const User::op_iterator &OpItE,
71 DependencyGraph &DAG)
72 : OpIt(OpIt), OpItE(OpItE), MemIt(MemIt), N(N), DAG(&DAG) {}
73 PredIterator(const User::op_iterator &OpIt, const User::op_iterator &OpItE,
74 DGNode *N, DependencyGraph &DAG)
75 : OpIt(OpIt), OpItE(OpItE), N(N), DAG(&DAG) {}
76 friend class DGNode; // For constructor
77 friend class MemDGNode; // For constructor
78
79 /// Skip iterators that don't point instructions or are outside \p DAG,
80 /// starting from \p OpIt and ending before \p OpItE.n
81 LLVM_ABI static User::op_iterator skipBadIt(User::op_iterator OpIt,
83 const DependencyGraph &DAG);
84
85public:
86 using difference_type = std::ptrdiff_t;
87 using value_type = DGNode *;
90 using iterator_category = std::input_iterator_tag;
92 LLVM_ABI PredIterator &operator++();
93 PredIterator operator++(int) {
94 auto Copy = *this;
95 ++(*this);
96 return Copy;
97 }
98 LLVM_ABI bool operator==(const PredIterator &Other) const;
99 bool operator!=(const PredIterator &Other) const { return !(*this == Other); }
100};
101
102/// Iterate over both def-use and mem dependencies.
103class SuccIterator {
104 User::user_iterator UserIt;
105 User::user_iterator UserItE;
107 DGNode *N = nullptr;
108 DependencyGraph *DAG = nullptr;
109
110 SuccIterator(const Value::user_iterator &UserIt,
111 const Value::user_iterator &UserItE,
113 DependencyGraph &DAG)
114 : UserIt(UserIt), UserItE(UserItE), MemIt(MemIt), N(N), DAG(&DAG) {}
115 SuccIterator(const User::user_iterator &UserIt,
116 const User::user_iterator &UserItE, DGNode *N,
117 DependencyGraph &DAG)
118 : UserIt(UserIt), UserItE(UserItE), N(N), DAG(&DAG) {}
119 friend class DGNode; // For constructor
120 friend class MemDGNode; // For constructor
121
122 /// Skip iterators that don't point to instructions or are outside \p DAG,
123 /// starting from \p OpIt and ending before \p OpItE.
125 skipOutOfScope(User::user_iterator UserIt, User::user_iterator UserItE,
126 const DependencyGraph &DAG);
127
128public:
129 using difference_type = std::ptrdiff_t;
133 using iterator_category = std::input_iterator_tag;
135 LLVM_ABI SuccIterator &operator++();
136 SuccIterator operator++(int) {
137 auto Copy = *this;
138 ++(*this);
139 return Copy;
140 }
141 LLVM_ABI bool operator==(const SuccIterator &Other) const;
142 bool operator!=(const SuccIterator &Other) const { return !(*this == Other); }
143};
144
145/// A DependencyGraph Node that points to an Instruction and contains memory
146/// dependency edges.
148protected:
150 // TODO: Use a PointerIntPair for SubclassID and I.
151 /// For isa/dyn_cast etc.
153 /// The number of unscheduled successors (predecessors) depending on the
154 /// scheduling direction. Optional represents whether the value is
155 /// meaningless, e.g., after a node gets scheduled.
156 std::optional<unsigned> UnscheduledDeps = 0;
157 /// This is true if this node has been scheduled.
158 bool Scheduled = false;
159 /// The scheduler bundle that this node belongs to.
160 SchedBundle *SB = nullptr;
161
163 void clearSchedBundle() { this->SB = nullptr; }
164 friend class SchedBundle; // For setSchedBundle(), clearSchedBundle().
165
167 friend class MemDGNode; // For constructor.
168 friend class DependencyGraph; // For UnscheduledSuccs
169
170public:
172 assert(!isMemDepNodeCandidate(I) && "Expected Non-Mem instruction, ");
173 }
174 DGNode(const DGNode &Other) = delete;
175 virtual ~DGNode();
176 /// \Returns the number of unscheduled successors.
177 unsigned getNumUnscheduledDeps() const {
178 assert((bool)UnscheduledDeps && "Invalid UnscheduledDeps!");
179 return *UnscheduledDeps;
180 }
181#ifndef NDEBUG
182 /// \returns true if unscheduled successors(predecessors) contains valid data
183 /// (for testing).
184 bool validUnscheduledDeps() const { return (bool)UnscheduledDeps; }
185#endif
186 // TODO: Make this private?
188 assert(*UnscheduledDeps > 0 && "Counting error!");
190 }
192
194 UnscheduledDeps = 0;
195 Scheduled = false;
196 }
197 /// \Returns true if all dependent successors (or predecessors during top-down
198 /// scheduling) have been scheduled.
199 bool ready() const { return UnscheduledDeps == 0; }
200 /// \Returns true if this node has been scheduled.
201 bool scheduled() const { return Scheduled; }
203 Scheduled = true;
204 // UnscheduledDeps is meaningless from this point on, so prohibit its use.
205 UnscheduledDeps = std::nullopt;
206 }
207 /// \Returns the scheduling bundle that this node belongs to, or nullptr.
208 SchedBundle *getSchedBundle() const { return SB; }
209 /// \Returns true if this is before \p Other in program order.
210 bool comesBefore(const DGNode *Other) { return I->comesBefore(Other->I); }
213 return PredIterator(
214 PredIterator::skipBadIt(I->op_begin(), I->op_end(), DAG), I->op_end(),
215 this, DAG);
216 }
218 return PredIterator(I->op_end(), I->op_end(), this, DAG);
219 }
221 return const_cast<DGNode *>(this)->preds_begin(DAG);
222 }
224 return const_cast<DGNode *>(this)->preds_end(DAG);
225 }
226 /// \Returns a range of DAG predecessors nodes. If this is a MemDGNode then
227 /// this will also include the memory dependency predecessors.
228 /// Please note that this can include the same node more than once, if for
229 /// example it's both a use-def predecessor and a mem dep predecessor.
233
236 return SuccIterator(
237 SuccIterator::skipOutOfScope(I->user_begin(), I->user_end(), DAG),
238 I->user_end(), this, DAG);
239 }
241 return SuccIterator(I->user_end(), I->user_end(), this, DAG);
242 }
244 return const_cast<DGNode *>(this)->succs_begin(DAG);
245 }
247 return const_cast<DGNode *>(this)->succs_end(DAG);
248 }
249 /// \Returns a range of DAG successor nodes. If this is a MemDGNode then
250 /// this will also include the memory dependency successors.
251 /// Please note that this can include the same node more than once, if for
252 /// example it's both a use-def predecessor and a mem dep successor.
256
258 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
259 auto IID = II->getIntrinsicID();
260 return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave;
261 }
262 return false;
263 }
264
265 /// \Returns true if intrinsic \p I touches memory. This is used by the
266 /// dependency graph.
268 auto IID = I->getIntrinsicID();
269 return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe;
270 }
271
272 /// We consider \p I as a Memory Dependency Candidate instruction if it
273 /// reads/write memory or if it has side-effects. This is used by the
274 /// dependency graph.
277 return I->mayReadOrWriteMemory() &&
279 }
280
281 /// \Returns true if \p I is fence like. It excludes non-mem intrinsics.
282 static bool isFenceLike(Instruction *I) {
284 return I->isFenceLike() &&
286 }
287
288 /// \Returns true if \p I is a memory dependency candidate instruction.
290 AllocaInst *Alloca;
291 return isMemDepCandidate(I) ||
292 ((Alloca = dyn_cast<AllocaInst>(I)) &&
293 Alloca->isUsedWithInAlloca()) ||
295 }
296
297 Instruction *getInstruction() const { return I; }
298
299#ifndef NDEBUG
300 virtual void print(raw_ostream &OS, bool PrintDeps = true) const;
302 N.print(OS);
303 return OS;
304 }
305 LLVM_DUMP_METHOD void dump() const;
306#endif // NDEBUG
307};
308
309/// A DependencyGraph Node for instructions that may read/write memory, or have
310/// some ordering constraints, like with stacksave/stackrestore and
311/// alloca/inalloca.
312class MemDGNode final : public DGNode {
313 MemDGNode *PrevMemN = nullptr;
314 MemDGNode *NextMemN = nullptr;
315 /// Memory predecessors.
316 DenseSet<MemDGNode *> MemPreds;
317 /// Memory successors.
318 DenseSet<MemDGNode *> MemSuccs;
319 friend class PredIterator; // For MemPreds.
320 friend class SuccIterator; // For MemSuccs.
321 /// Creates both edges: this<->N.
322 void setNextNode(MemDGNode *N) {
323 assert(N != this && "About to point to self!");
324 NextMemN = N;
325 if (NextMemN != nullptr)
326 NextMemN->PrevMemN = this;
327 }
328 /// Creates both edges: N<->this.
329 void setPrevNode(MemDGNode *N) {
330 assert(N != this && "About to point to self!");
331 PrevMemN = N;
332 if (PrevMemN != nullptr)
333 PrevMemN->NextMemN = this;
334 }
335 friend class DependencyGraph; // For setNextNode(), setPrevNode().
336 void detachFromChain() {
337 if (PrevMemN != nullptr)
338 PrevMemN->NextMemN = NextMemN;
339 if (NextMemN != nullptr)
340 NextMemN->PrevMemN = PrevMemN;
341 PrevMemN = nullptr;
342 NextMemN = nullptr;
343 }
344
345public:
347 assert(isMemDepNodeCandidate(I) && "Expected Mem instruction!");
348 }
349 static bool classof(const DGNode *Other) {
350 return Other->SubclassID == DGNodeID::MemDGNode;
351 }
353 auto OpEndIt = I->op_end();
354 return PredIterator(PredIterator::skipBadIt(I->op_begin(), OpEndIt, DAG),
355 OpEndIt, MemPreds.begin(), this, DAG);
356 }
358 return PredIterator(I->op_end(), I->op_end(), MemPreds.end(), this, DAG);
359 }
361 auto UserEndIt = I->user_end();
362 return SuccIterator(
363 SuccIterator::skipOutOfScope(I->user_begin(), UserEndIt, DAG),
364 UserEndIt, MemSuccs.begin(), this, DAG);
365 }
367 return SuccIterator(I->user_end(), I->user_end(), MemSuccs.end(), this,
368 DAG);
369 }
370 /// \Returns the previous Mem DGNode in instruction order.
371 MemDGNode *getPrevNode() const { return PrevMemN; }
372 /// \Returns the next Mem DGNode in instruction order.
373 MemDGNode *getNextNode() const { return NextMemN; }
374
375 // TODO: addMemPred() and removeMemPred() should be private.
376 /// Adds the mem dependency edge PredN->this. This also increments the
377 /// UnscheduledDeps counter of the predecessor if this node has not been
378 /// scheduled.
380 [[maybe_unused]] auto Inserted = MemPreds.insert(PredN).second;
381 assert(Inserted && "PredN already exists!");
382 assert(PredN != this && "Trying to add a dependency to self!");
383 PredN->MemSuccs.insert(this);
384 if (!Scheduled) {
385 if (!PredN->Scheduled) {
386 if (Dir == SchedDirection::BottomUp)
387 PredN->incrUnscheduledDeps();
388 else
390 }
391 }
392 }
393 /// Removes the memory dependency PredN->this. This also updates the
394 /// UnscheduledSuccs counter of PredN if this node has not been scheduled.
396 MemPreds.erase(PredN);
397 PredN->MemSuccs.erase(this);
398 if (!Scheduled) {
399 if (!PredN->Scheduled) {
400 if (Dir == SchedDirection::BottomUp)
401 PredN->decrUnscheduledDeps();
402 else
404 }
405 }
406 }
407
408 /// \Returns true if there is a memory dependency N->this.
409 bool hasMemPred(DGNode *N) const {
410 if (auto *MN = dyn_cast<MemDGNode>(N))
411 return MemPreds.count(MN);
412 return false;
413 }
414 /// \Returns all memory dependency predecessors. Used by tests.
416 return make_range(MemPreds.begin(), MemPreds.end());
417 }
418 /// \Returns all memory dependency successors.
420 return make_range(MemSuccs.begin(), MemSuccs.end());
421 }
422#ifndef NDEBUG
423 void print(raw_ostream &OS, bool PrintDeps = true) const override;
424#endif // NDEBUG
425};
426
427/// Convenience builders for a MemDGNode interval.
429public:
430 /// Scans the instruction chain in \p Intvl top-down, returning the top-most
431 /// MemDGNode, or nullptr.
433 const DependencyGraph &DAG);
434 /// Scans the instruction chain in \p Intvl bottom-up, returning the
435 /// bottom-most MemDGNode, or nullptr.
437 const DependencyGraph &DAG);
438 /// Given \p Instrs it finds their closest mem nodes in the interval and
439 /// returns the corresponding mem range. Note: BotN (or its neighboring mem
440 /// node) is included in the range.
442 DependencyGraph &DAG);
443 static Interval<MemDGNode> makeEmpty() { return {}; }
444};
445
447private:
449 /// The DAG spans across all instructions in this interval.
450 Interval<Instruction> DAGInterval;
451
452 SchedDirection Dir;
453
454 Context *Ctx = nullptr;
455 std::optional<Context::CallbackID> CreateInstrCB;
456 std::optional<Context::CallbackID> EraseInstrCB;
457 std::optional<Context::CallbackID> MoveInstrCB;
458 std::optional<Context::CallbackID> SetUseCB;
459
460 std::unique_ptr<BatchAAResults> BatchAA;
461
462 enum class DependencyType {
463 ReadAfterWrite, ///> Memory dependency write -> read
464 WriteAfterWrite, ///> Memory dependency write -> write
465 WriteAfterRead, ///> Memory dependency read -> write
466 Control, ///> Control-related dependency, like with PHI/Terminator
467 Other, ///> Currently used for stack related instrs
468 None, ///> No memory/other dependency
469 };
470 /// \Returns the dependency type depending on whether instructions may
471 /// read/write memory or whether they are some specific opcode-related
472 /// restrictions.
473 /// Note: It does not check whether a memory dependency is actually correct,
474 /// as it won't call AA. Therefore it returns the worst-case dep type.
475 static DependencyType getRoughDepType(Instruction *FromI, Instruction *ToI);
476
477 // TODO: Implement AABudget.
478 /// \Returns true if there is a memory/other dependency \p SrcI->DstI.
479 bool alias(Instruction *SrcI, Instruction *DstI, DependencyType DepType);
480
481 bool hasDep(sandboxir::Instruction *SrcI, sandboxir::Instruction *DstI);
482
483 /// Go through all mem nodes in \p SrcScanRange and try to add dependencies to
484 /// \p DstN.
485 void scanAndAddDeps(MemDGNode &DstN, const Interval<MemDGNode> &SrcScanRange);
486
487 /// Sets the UnscheduledSuccs of all DGNodes in \p NewInterval based on
488 /// def-use edges.
489 void setDefUseUnscheduledSuccs(const Interval<Instruction> &NewInterval);
490
491 /// Create DAG nodes for instrs in \p NewInterval and update the MemNode
492 /// chain.
493 void createNewNodes(const Interval<Instruction> &NewInterval);
494
495 /// Helper for `notify*Instr()`. \Returns the first MemDGNode that comes
496 /// before \p N, skipping \p SkipN, including or excluding \p N based on
497 /// \p IncludingN, or nullptr if not found.
498 MemDGNode *getMemDGNodeBefore(DGNode *N, bool IncludingN,
499 MemDGNode *SkipN = nullptr) const;
500 /// Helper for `notifyMoveInstr()`. \Returns the first MemDGNode that comes
501 /// after \p N, skipping \p SkipN, including or excluding \p N based on \p
502 /// IncludingN, or nullptr if not found.
503 MemDGNode *getMemDGNodeAfter(DGNode *N, bool IncludingN,
504 MemDGNode *SkipN = nullptr) const;
505
506 /// Called by the callbacks when a new instruction \p I has been created.
507 LLVM_ABI void notifyCreateInstr(Instruction *I);
508 /// Called by the callbacks when instruction \p I is about to get
509 /// deleted.
510 LLVM_ABI void notifyEraseInstr(Instruction *I);
511 /// Called by the callbacks when instruction \p I is about to be moved to
512 /// \p To.
513 LLVM_ABI void notifyMoveInstr(Instruction *I, const BBIterator &To);
514 /// Called by the callbacks when \p U's source is about to be set to \p NewSrc
515 LLVM_ABI void notifySetUse(const Use &U, Value *NewSrc);
516
517public:
518 /// This constructor also registers callbacks.
520 : Dir(Dir), Ctx(&Ctx), BatchAA(std::make_unique<BatchAAResults>(AA)) {
521 CreateInstrCB = Ctx.registerCreateInstrCallback(
522 [this](Instruction *I) { notifyCreateInstr(I); });
523 EraseInstrCB = Ctx.registerEraseInstrCallback(
524 [this](Instruction *I) { notifyEraseInstr(I); });
525 MoveInstrCB = Ctx.registerMoveInstrCallback(
526 [this](Instruction *I, const BBIterator &To) {
527 notifyMoveInstr(I, To);
528 });
529 SetUseCB = Ctx.registerSetUseCallback(
530 [this](const Use &U, Value *NewSrc) { notifySetUse(U, NewSrc); });
531 }
533 if (CreateInstrCB)
534 Ctx->unregisterCreateInstrCallback(*CreateInstrCB);
535 if (EraseInstrCB)
536 Ctx->unregisterEraseInstrCallback(*EraseInstrCB);
537 if (MoveInstrCB)
538 Ctx->unregisterMoveInstrCallback(*MoveInstrCB);
539 if (SetUseCB)
540 Ctx->unregisterSetUseCallback(*SetUseCB);
541 }
542
544 auto It = InstrToNodeMap.find(I);
545 return It != InstrToNodeMap.end() ? It->second.get() : nullptr;
546 }
547 /// Like getNode() but returns nullptr if \p I is nullptr.
549 if (I == nullptr)
550 return nullptr;
551 return getNode(I);
552 }
554 auto [It, NotInMap] = InstrToNodeMap.try_emplace(I);
555 if (NotInMap) {
557 It->second = std::make_unique<MemDGNode>(I);
558 else
559 It->second = std::make_unique<DGNode>(I);
560 }
561 return It->second.get();
562 }
563 /// Build/extend the dependency graph such that it includes \p Instrs. Returns
564 /// the range of instructions added to the DAG.
566 /// \Returns the range of instructions included in the DAG.
567 Interval<Instruction> getInterval() const { return DAGInterval; }
568 void clear() {
569 InstrToNodeMap.clear();
570 DAGInterval = {};
571 }
572 std::optional<Context::CallbackID> getEraseInstrCB() const {
573 return EraseInstrCB;
574 }
575#ifndef NDEBUG
576 /// \Returns true if the DAG's state is clear. Used in assertions.
577 bool empty() const {
578 bool IsEmpty = InstrToNodeMap.empty();
579 assert(IsEmpty == DAGInterval.empty() &&
580 "Interval and InstrToNodeMap out of sync!");
581 return IsEmpty;
582 }
583 void print(raw_ostream &OS) const;
584 LLVM_DUMP_METHOD void dump() const;
585#endif // NDEBUG
586};
587} // namespace llvm::sandboxir
588
589#endif // LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_TEMPLATE_ABI
Definition Compiler.h:216
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:678
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:57
std::pair< uint64_t, uint64_t > Interval
uint64_t IntrinsicInst * II
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.
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
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.
An ArrayRef of Values or Instructions that we can print/dump for debugging.
Definition VecUtils.h:459
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.
bool validUnscheduledDeps() const
iterator preds_begin(DependencyGraph &DAG) const
std::optional< unsigned > UnscheduledDeps
The number of unscheduled successors (predecessors) depending on the scheduling direction.
DGNode(Instruction *I, DGNodeID ID)
unsigned getNumUnscheduledDeps() const
\Returns the number of unscheduled successors.
void setSchedBundle(SchedBundle &SB)
bool scheduled() const
\Returns true if this node has been scheduled.
virtual succ_iterator succs_end(DependencyGraph &DAG)
bool ready() const
\Returns true if all dependent successors (or predecessors during top-down scheduling) have been sche...
succ_iterator succs_end(DependencyGraph &DAG) const
iterator_range< iterator > preds(DependencyGraph &DAG) const
\Returns a range of DAG predecessors nodes.
iterator preds_end(DependencyGraph &DAG) const
SchedBundle * SB
The scheduler bundle that this node belongs to.
bool Scheduled
This is true if this node has been scheduled.
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.
iterator_range< succ_iterator > succs(DependencyGraph &DAG) const
\Returns a range of DAG successor nodes.
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.
virtual succ_iterator succs_begin(DependencyGraph &DAG)
friend raw_ostream & operator<<(raw_ostream &OS, DGNode &N)
virtual iterator preds_begin(DependencyGraph &DAG)
succ_iterator succs_begin(DependencyGraph &DAG) const
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
LLVM_ABI Interval< Instruction > extend(BndlRef< Instruction * > Instrs)
Build/extend the dependency graph such that it includes Instrs.
DGNode * getNodeOrNull(Instruction *I) const
Like getNode() but returns nullptr if I is nullptr.
std::optional< Context::CallbackID > getEraseInstrCB() const
void print(raw_ostream &OS) const
DependencyGraph(SchedDirection Dir, AAResults &AA, Context &Ctx)
This constructor also registers callbacks.
DGNode * getOrCreateNode(Instruction *I)
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)
void addMemPred(MemDGNode *PredN, SchedDirection Dir)
Adds the mem dependency edge PredN->this.
void removeMemPred(MemDGNode *PredN, SchedDirection Dir)
Removes the memory dependency PredN->this.
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.
succ_iterator succs_begin(DependencyGraph &DAG) override
MemDGNode * getPrevNode() const
\Returns the previous Mem DGNode in instruction order.
succ_iterator succs_end(DependencyGraph &DAG) override
Iterate over both def-use and mem dependencies.
bool operator!=(const PredIterator &Other) const
LLVM_ABI PredIterator & operator++()
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:128
Iterate over both def-use and mem dependencies.
LLVM_ABI SuccIterator & operator++()
bool operator!=(const SuccIterator &Other) const
std::input_iterator_tag iterator_category
Represents a Def-use/Use-def edge in SandboxIR.
Definition Use.h:43
OperandUseIterator op_iterator
Definition User.h:98
A SandboxIR Value has users. This is the base class.
Definition Value.h:72
mapped_iterator< sandboxir::UserUseIterator, UseToUser > user_iterator
Definition Value.h:239
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
Abstract Attribute helper functions.
Definition Attributor.h:165
StringLiteral schedDirectionToStr(SchedDirection Dir)
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)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
APInt operator*(APInt a, uint64_t RHS)
Definition APInt.h:2261
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
@ Other
Any other memory.
Definition ModRef.h:68
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N