22#ifndef LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
23#define LLVM_TRANSFORMS_VECTORIZE_SANDBOXVECTORIZER_DEPENDENCYGRAPH_H
63 : OpIt(OpIt), OpItE(OpItE), MemIt(MemIt),
N(N), DAG(&DAG) {}
66 : OpIt(OpIt), OpItE(OpItE),
N(N), DAG(&DAG) {}
146 PredIterator::skipBadIt(
I->op_begin(),
I->op_end(), DAG),
I->op_end(),
168 auto IID =
II->getIntrinsicID();
169 return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave;
177 auto IID =
I->getIntrinsicID();
178 return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe;
186 return I->mayReadOrWriteMemory() &&
193 return I->isFenceLike() &&
231 assert(
N !=
this &&
"About to point to self!");
233 if (NextMemN !=
nullptr)
234 NextMemN->PrevMemN =
this;
238 assert(
N !=
this &&
"About to point to self!");
240 if (PrevMemN !=
nullptr)
241 PrevMemN->NextMemN =
this;
244 void detachFromChain() {
245 if (PrevMemN !=
nullptr)
246 PrevMemN->NextMemN = NextMemN;
247 if (NextMemN !=
nullptr)
248 NextMemN->PrevMemN = PrevMemN;
261 auto OpEndIt =
I->op_end();
262 return PredIterator(PredIterator::skipBadIt(
I->op_begin(), OpEndIt, DAG),
263 OpEndIt, MemPreds.begin(),
this, DAG);
266 return PredIterator(
I->op_end(),
I->op_end(), MemPreds.end(),
this, DAG);
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);
287 MemPreds.erase(PredN);
288 PredN->MemSuccs.erase(
this);
296 return MemPreds.count(MN);
301 return make_range(MemPreds.begin(), MemPreds.end());
305 return make_range(MemSuccs.begin(), MemSuccs.end());
338 std::optional<Context::CallbackID> CreateInstrCB;
339 std::optional<Context::CallbackID> EraseInstrCB;
340 std::optional<Context::CallbackID> MoveInstrCB;
341 std::optional<Context::CallbackID> SetUseCB;
343 std::unique_ptr<BatchAAResults> BatchAA;
345 enum class DependencyType {
404 CreateInstrCB = Ctx.registerCreateInstrCallback(
406 EraseInstrCB = Ctx.registerEraseInstrCallback(
408 MoveInstrCB = Ctx.registerMoveInstrCallback(
410 notifyMoveInstr(
I, To);
412 SetUseCB = Ctx.registerSetUseCallback(
413 [
this](
const Use &U,
Value *NewSrc) { notifySetUse(U, NewSrc); });
417 Ctx->unregisterCreateInstrCallback(*CreateInstrCB);
419 Ctx->unregisterEraseInstrCallback(*EraseInstrCB);
421 Ctx->unregisterMoveInstrCallback(*MoveInstrCB);
423 Ctx->unregisterSetUseCallback(*SetUseCB);
427 auto It = InstrToNodeMap.find(
I);
428 return It != InstrToNodeMap.end() ? It->second.get() :
nullptr;
437 auto [It, NotInMap] = InstrToNodeMap.try_emplace(
I);
440 It->second = std::make_unique<MemDGNode>(
I);
442 It->second = std::make_unique<DGNode>(
I);
444 return It->second.get();
452 InstrToNodeMap.clear();
458 bool IsEmpty = InstrToNodeMap.empty();
459 assert(IsEmpty == DAGInterval.empty() &&
460 "Interval and InstrToNodeMap out of sync!");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_TEMPLATE_ABI
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
std::pair< uint64_t, uint64_t > Interval
uint64_t IntrinsicInst * II
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
DenseSetIterator< false > iterator
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
A DependencyGraph Node that points to an Instruction and contains memory dependency edges.
void incrUnscheduledSuccs()
void decrUnscheduledSuccs()
friend class DependencyGraph
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.
void setSchedBundle(SchedBundle &SB)
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
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.
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.
void resetScheduleState()
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 ...
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
friend class DependencyGraph
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(Instruction *I)
MemDGNode * getPrevNode() const
\Returns the previous Mem DGNode in instruction order.
void addMemPred(MemDGNode *PredN)
Adds the mem dependency edge PredN->this.
friend class PredIterator
Iterate over both def-use and mem dependencies.
std::ptrdiff_t difference_type
PredIterator operator++(int)
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.
Represents a Def-use/Use-def edge in SandboxIR.
OperandUseIterator op_iterator
A SandboxIR Value has users. This is the base class.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
Abstract Attribute helper functions.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
APInt operator*(APInt a, uint64_t RHS)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
Implement std::hash so that hash_code can be used in STL containers.