16 #ifndef MLIR_ANALYSIS_DATAFLOWFRAMEWORK_H
17 #define MLIR_ANALYSIS_DATAFLOWFRAMEWORK_H
21 #include "llvm/ADT/SetVector.h"
22 #include "llvm/Support/Compiler.h"
23 #include "llvm/Support/TypeName.h"
80 virtual void print(raw_ostream &os)
const = 0;
101 template <
typename ConcreteT,
typename Value>
112 template <
typename ValueT>
115 value(std::forward<ValueT>(value)) {}
119 template <
typename... Args>
121 return uniquer.
get<ConcreteT>({}, std::forward<Args>(args)...);
125 template <
typename ValueT>
128 return new (alloc.
allocate<ConcreteT>())
129 ConcreteT(std::forward<ValueT>(value));
137 return point->
getTypeID() == TypeID::get<ConcreteT>();
154 :
public PointerUnion<GenericProgramPoint *, Operation *, Value, Block *> {
158 using ParentTy::PointerUnion;
163 template <
typename OpT,
typename = std::enable_if_t<
164 std::is_convertible<OpT, Operation *>::value &&
165 !std::is_same<OpT, Operation *>::value>>
169 void print(raw_ostream &os)
const;
176 class DataFlowAnalysis;
199 template <
typename AnalysisT,
typename... Args>
200 AnalysisT *
load(Args &&...args);
208 template <
typename StateT,
typename Po
intT>
210 auto it = analysisStates.find({
ProgramPoint(point), TypeID::get<StateT>()});
211 if (it == analysisStates.end())
213 return static_cast<const StateT *
>(it->second.get());
218 template <
typename PointT,
typename... Args>
220 return PointT::get(uniquer, std::forward<Args>(args)...);
226 using WorkItem = std::pair<ProgramPoint, DataFlowAnalysis *>;
232 template <
typename StateT,
typename Po
intT>
243 std::queue<WorkItem> worklist;
290 virtual void print(raw_ostream &os)
const = 0;
291 LLVM_DUMP_METHOD
void dump()
const;
311 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
397 template <
typename Po
intT>
403 template <
typename PointT,
typename... Args>
411 template <
typename StateT,
typename Po
intT>
419 template <
typename StateT,
typename Po
intT>
421 StateT *state = getOrCreate<StateT>(point);
426 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
439 template <
typename AnalysisT,
typename... Args>
441 childAnalyses.emplace_back(
new AnalysisT(*
this, std::forward<Args>(args)...));
442 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
443 childAnalyses.back().get()->debugName = llvm::getTypeName<AnalysisT>();
445 return static_cast<AnalysisT *
>(childAnalyses.back().get());
448 template <
typename StateT,
typename Po
intT>
450 std::unique_ptr<AnalysisState> &state =
451 analysisStates[{
ProgramPoint(point), TypeID::get<StateT>()}];
453 state = std::unique_ptr<StateT>(
new StateT(point));
454 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
455 state->debugName = llvm::getTypeName<StateT>();
458 return static_cast<StateT *
>(state.get());
480 template <
typename To>
482 :
public CastInfo<To, mlir::ProgramPoint::PointerUnion> {};
484 template <
typename To>
486 :
public CastInfo<To, const mlir::ProgramPoint::PointerUnion> {};
Base class for generic analysis states.
ProgramPoint getPoint() const
Returns the program point this state is located at.
LLVM_DUMP_METHOD void dump() const
virtual void print(raw_ostream &os) const =0
Print the contents of the analysis state.
void addDependency(ProgramPoint dependent, DataFlowAnalysis *analysis)
Add a dependency to this analysis state on a program point and an analysis.
virtual void onUpdate(DataFlowSolver *solver) const
This function is called by the solver when the analysis state is updated to enqueue more work items.
ProgramPoint point
The program point to which the state belongs.
AnalysisState(ProgramPoint point)
Create the analysis state at the given program point.
Base class for all data-flow analyses.
void registerPointKind()
Register a custom program point class.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
PointT * getProgramPoint(Args &&...args)
Get or create a custom program point.
virtual LogicalResult visit(ProgramPoint point)=0
Visit the given program point.
const StateT * getOrCreateFor(ProgramPoint dependent, PointT point)
Get a read-only analysis state for the given point and create a dependency on dependent.
virtual ~DataFlowAnalysis()
DataFlowAnalysis(DataFlowSolver &solver)
Create an analysis with a reference to the parent solver.
StateT * getOrCreate(PointT point)
Get the analysis state associated with the program point.
virtual LogicalResult initialize(Operation *top)=0
Initialize the analysis from the provided top-level operation by building an initial dependency graph...
void addDependency(AnalysisState *state, ProgramPoint point)
Create a dependency between the given analysis state and program point on this analysis.
The general data-flow analysis solver.
PointT * getProgramPoint(Args &&...args)
Get a uniqued program point instance.
StateT * getOrCreateState(PointT point)
Get the state associated with the given program point.
void enqueue(WorkItem item)
Push a work item onto the worklist.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to an analysis state if it changed by pushing dependent work items to the back of...
const StateT * lookupState(PointT point) const
Lookup an analysis state for the given program point.
AnalysisT * load(Args &&...args)
Load an analysis into the solver. Return the analysis instance.
LogicalResult initializeAndRun(Operation *top)
Initialize the children analyses starting from the provided top-level operation and run the analysis ...
std::pair< ProgramPoint, DataFlowAnalysis * > WorkItem
A work item on the solver queue is a program point, child analysis pair.
Base class for generic program points based on a concrete program point type and a content key.
static ConcreteT * construct(StorageUniquer::StorageAllocator &alloc, ValueT &&value)
Allocate space for a program point and construct it in-place.
static ConcreteT * get(StorageUniquer &uniquer, Args &&...args)
Get a uniqued instance of this program point class with the given arguments.
static bool classof(const GenericProgramPoint *point)
Provide LLVM-style RTTI using type IDs.
const Value & getValue() const
Get the contents of the program point.
bool operator==(const Value &value) const
Two program points are equal if their values are equal.
GenericProgramPointBase(ValueT &&value)
Construct an instance of the program point using the provided value and the type ID of the concrete t...
Abstract class for generic program points.
virtual void print(raw_ostream &os) const =0
Print the program point.
virtual Location getLoc() const =0
Get a derived source location for the program point.
TypeID getTypeID() const
Get the abstract program point's type identifier.
GenericProgramPoint(TypeID typeID)
Create an abstract program point with type identifier.
virtual ~GenericProgramPoint()
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Operation is the basic unit of execution within MLIR.
This class acts as the base storage that all storage classes must derived from.
This is a utility allocator used to allocate memory for instances of derived types.
T * allocate()
Allocate an instance of the provided type.
A utility class to get or create instances of "storage classes".
Storage * get(function_ref< void(Storage *)> initFn, TypeID id, Args &&...args)
Gets a uniqued instance of 'Storage'.
void registerParametricStorageType(TypeID id)
Register a new parametric storage class, this is necessary to create instances of this class type.
This class provides an efficient unique identifier for a specific C++ type.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Include the generated interface declarations.
Include the generated interface declarations.
ChangeResult & operator|=(ChangeResult &lhs, ChangeResult rhs)
ChangeResult
A result type used to indicate if a change happened.
ChangeResult operator&(ChangeResult lhs, ChangeResult rhs)
ChangeResult operator|(ChangeResult lhs, ChangeResult rhs)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
This class represents an efficient way to signal success or failure.
Fundamental IR components are supported as first-class program points.
ProgramPoint(ParentTy point=nullptr)
Allow implicit conversion from the parent type.
Location getLoc() const
Get the source location of the program point.
ProgramPoint(OpT op)
Allow implicit conversions from operation wrappers.
void print(raw_ostream &os) const
Print the program point.