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) {}
102 unsigned UnscheduledSuccs = 0;
104 bool Scheduled =
false;
118 assert(!isMemDepNodeCandidate(
I) &&
"Expected Non-Mem instruction, ");
126 assert(UnscheduledSuccs > 0 &&
"Counting error!");
131 UnscheduledSuccs = 0;
135 bool ready()
const {
return UnscheduledSuccs == 0; }
146 PredIterator::skipBadIt(
I->op_begin(),
I->op_end(), DAG),
I->op_end(),
153 return const_cast<DGNode *
>(
this)->preds_begin(DAG);
156 return const_cast<DGNode *
>(
this)->preds_end(DAG);
163 return make_range(preds_begin(DAG), preds_end(DAG));
167 if (
auto *
II = dyn_cast<IntrinsicInst>(
I)) {
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() &&
187 (!(
II = dyn_cast<IntrinsicInst>(
I)) || isMemIntrinsic(
II));
193 return I->isFenceLike() &&
194 (!(
II = dyn_cast<IntrinsicInst>(
I)) || isMemIntrinsic(
II));
200 return isMemDepCandidate(
I) ||
201 ((Alloca = dyn_cast<AllocaInst>(
I)) &&
203 isStackSaveOrRestoreIntrinsic(
I) || isFenceLike(
I);
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;
255 assert(isMemDepNodeCandidate(
I) &&
"Expected Mem instruction!");
261 auto OpEndIt =
I->op_end();
262 return PredIterator(PredIterator::skipBadIt(
I->op_begin(), OpEndIt, DAG),
263 OpEndIt, MemPreds.
begin(),
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);
295 if (
auto *MN = dyn_cast<MemDGNode>(
N))
296 return MemPreds.
count(MN);
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 {
410 notifyMoveInstr(
I, To);
413 [
this](
const Use &U,
Value *NewSrc) { notifySetUse(U, NewSrc); });
427 auto It = InstrToNodeMap.
find(
I);
428 return It != InstrToNodeMap.
end() ? It->second.get() :
nullptr;
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();
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::optional< std::vector< StOtherPiece > > Other
std::pair< uint64_t, uint64_t > Interval
uint64_t IntrinsicInst * II
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),...
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.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
std::pair< iterator, bool > insert(const ValueT &V)
DenseSetIterator< false > iterator
bool erase(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
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.
Iterator for Instructions in a `BasicBlock.
LLVM_ABI void unregisterSetUseCallback(CallbackID ID)
LLVM_ABI CallbackID registerSetUseCallback(SetUseCallback CB)
Register a callback that gets called when a Use gets set.
LLVM_ABI CallbackID registerCreateInstrCallback(CreateInstrCallback CB)
Register a callback that gets called right after a SandboxIR instruction is created.
LLVM_ABI void unregisterCreateInstrCallback(CallbackID ID)
LLVM_ABI void unregisterMoveInstrCallback(CallbackID ID)
LLVM_ABI void unregisterEraseInstrCallback(CallbackID ID)
LLVM_ABI CallbackID registerMoveInstrCallback(MoveInstrCallback CB)
Register a callback that gets called when a SandboxIR instruction is about to be moved.
LLVM_ABI CallbackID registerEraseInstrCallback(EraseInstrCallback CB)
Register a callback that gets called when a SandboxIR instruction is about to be removed from its par...
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.
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.
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
Iterator for the Use edges of a User's operands.
Iterate over both def-use and mem dependencies.
std::ptrdiff_t difference_type
PredIterator operator++(int)
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.
Represents a Def-use/Use-def edge in SandboxIR.
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.
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)
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.