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) {}
159 PredIterator::skipBadIt(
I->op_begin(),
I->op_end(), DAG),
I->op_end(),
181 auto IID =
II->getIntrinsicID();
182 return IID == Intrinsic::stackrestore || IID == Intrinsic::stacksave;
190 auto IID =
I->getIntrinsicID();
191 return IID != Intrinsic::sideeffect && IID != Intrinsic::pseudoprobe;
199 return I->mayReadOrWriteMemory() &&
206 return I->isFenceLike() &&
244 assert(
N !=
this &&
"About to point to self!");
246 if (NextMemN !=
nullptr)
247 NextMemN->PrevMemN =
this;
251 assert(
N !=
this &&
"About to point to self!");
253 if (PrevMemN !=
nullptr)
254 PrevMemN->NextMemN =
this;
257 void detachFromChain() {
258 if (PrevMemN !=
nullptr)
259 PrevMemN->NextMemN = NextMemN;
260 if (NextMemN !=
nullptr)
261 NextMemN->PrevMemN = PrevMemN;
274 auto OpEndIt =
I->op_end();
275 return PredIterator(PredIterator::skipBadIt(
I->op_begin(), OpEndIt, DAG),
276 OpEndIt, MemPreds.begin(),
this, DAG);
279 return PredIterator(
I->op_end(),
I->op_end(), MemPreds.end(),
this, DAG);
289 [[maybe_unused]]
auto Inserted = MemPreds.insert(PredN).second;
290 assert(Inserted &&
"PredN already exists!");
291 assert(PredN !=
this &&
"Trying to add a dependency to self!");
292 PredN->MemSuccs.insert(
this);
301 MemPreds.erase(PredN);
302 PredN->MemSuccs.erase(
this);
311 return MemPreds.count(MN);
316 return make_range(MemPreds.begin(), MemPreds.end());
320 return make_range(MemSuccs.begin(), MemSuccs.end());
353 std::optional<Context::CallbackID> CreateInstrCB;
354 std::optional<Context::CallbackID> EraseInstrCB;
355 std::optional<Context::CallbackID> MoveInstrCB;
356 std::optional<Context::CallbackID> SetUseCB;
358 std::unique_ptr<BatchAAResults> BatchAA;
360 enum class DependencyType {
419 CreateInstrCB = Ctx.registerCreateInstrCallback(
421 EraseInstrCB = Ctx.registerEraseInstrCallback(
423 MoveInstrCB = Ctx.registerMoveInstrCallback(
425 notifyMoveInstr(
I, To);
427 SetUseCB = Ctx.registerSetUseCallback(
428 [
this](
const Use &U,
Value *NewSrc) { notifySetUse(U, NewSrc); });
432 Ctx->unregisterCreateInstrCallback(*CreateInstrCB);
434 Ctx->unregisterEraseInstrCallback(*EraseInstrCB);
436 Ctx->unregisterMoveInstrCallback(*MoveInstrCB);
438 Ctx->unregisterSetUseCallback(*SetUseCB);
442 auto It = InstrToNodeMap.find(
I);
443 return It != InstrToNodeMap.end() ? It->second.get() :
nullptr;
452 auto [It, NotInMap] = InstrToNodeMap.try_emplace(
I);
455 It->second = std::make_unique<MemDGNode>(
I);
457 It->second = std::make_unique<DGNode>(
I);
459 return It->second.get();
467 InstrToNodeMap.clear();
473 bool IsEmpty = InstrToNodeMap.empty();
474 assert(IsEmpty == DAGInterval.empty() &&
475 "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.
bool validUnscheduledSuccs() const
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.
std::optional< unsigned > UnscheduledSuccs
The number of unscheduled successors.
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.