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;
193 interprocedural = enable;
201 bool interprocedural =
true;
228 template <
typename AnalysisT,
typename... Args>
229 AnalysisT *
load(Args &&...args);
237 template <
typename StateT,
typename Po
intT>
239 auto it = analysisStates.find({
ProgramPoint(point), TypeID::get<StateT>()});
240 if (it == analysisStates.end())
242 return static_cast<const StateT *
>(it->second.get());
247 template <
typename PointT,
typename... Args>
249 return PointT::get(uniquer, std::forward<Args>(args)...);
255 using WorkItem = std::pair<ProgramPoint, DataFlowAnalysis *>;
261 template <
typename StateT,
typename Po
intT>
278 std::queue<WorkItem> worklist;
325 virtual void print(raw_ostream &os)
const = 0;
326 LLVM_DUMP_METHOD
void dump()
const;
346 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
432 template <
typename Po
intT>
438 template <
typename PointT,
typename... Args>
446 template <
typename StateT,
typename Po
intT>
454 template <
typename StateT,
typename Po
intT>
456 StateT *state = getOrCreate<StateT>(point);
464 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
477 template <
typename AnalysisT,
typename... Args>
479 childAnalyses.emplace_back(
new AnalysisT(*
this, std::forward<Args>(args)...));
480 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
481 childAnalyses.back().get()->debugName = llvm::getTypeName<AnalysisT>();
483 return static_cast<AnalysisT *
>(childAnalyses.back().get());
486 template <
typename StateT,
typename Po
intT>
488 std::unique_ptr<AnalysisState> &state =
489 analysisStates[{
ProgramPoint(point), TypeID::get<StateT>()}];
491 state = std::unique_ptr<StateT>(
new StateT(point));
492 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
493 state->debugName = llvm::getTypeName<StateT>();
496 return static_cast<StateT *
>(state.get());
518 template <
typename To>
520 :
public CastInfo<To, mlir::ProgramPoint::PointerUnion> {};
522 template <
typename To>
524 :
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()
const DataFlowConfig & getSolverConfig() const
Return the configuration of the solver used for this analysis.
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.
Configuration class for data flow solver and child analyses.
DataFlowConfig & setInterprocedural(bool enable)
Set whether the solver should operate interpocedurally, i.e.
bool isInterprocedural() const
Return true if the solver operates interprocedurally, false otherwise.
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 DataFlowConfig & getConfig() const
Get the configuration of the solver.
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 ...
DataFlowSolver(const DataFlowConfig &config=DataFlowConfig())
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.