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"
57 using ParentTy::PointerUnion;
62 template <
typename OpT,
typename = std::enable_if_t<
63 std::is_convertible<OpT, Operation *>::value &&
64 !std::is_same<OpT, Operation *>::value>>
68 void print(raw_ostream &os)
const;
94 virtual void print(raw_ostream &os)
const = 0;
115 template <
typename ConcreteT,
typename Value>
126 template <
typename ValueT>
129 value(std::forward<ValueT>(value)) {}
133 template <
typename... Args>
135 return uniquer.
get<ConcreteT>({}, std::forward<Args>(args)...);
139 template <
typename ValueT>
142 return new (alloc.
allocate<ConcreteT>())
143 ConcreteT(std::forward<ValueT>(value));
151 return point->
getTypeID() == TypeID::get<ConcreteT>();
168 :
public PointerUnion<GenericLatticeAnchor *, ProgramPoint, Value> {
171 using ParentTy::PointerUnion;
176 template <
typename OpT,
typename = std::enable_if_t<
177 std::is_convertible<OpT, Operation *>::value &&
178 !std::is_same<OpT, Operation *>::value>>
185 void print(raw_ostream &os)
const;
192 class DataFlowAnalysis;
209 interprocedural = enable;
217 bool interprocedural =
true;
244 template <
typename AnalysisT,
typename... Args>
245 AnalysisT *
load(Args &&...args);
253 template <
typename StateT,
typename AnchorT>
256 analysisStates.find({
LatticeAnchor(anchor), TypeID::get<StateT>()});
257 if (it == analysisStates.end())
259 return static_cast<const StateT *
>(it->second.get());
263 template <
typename AnchorT>
267 for (
auto it = analysisStates.begin(); it != analysisStates.end(); ++it) {
268 if (it->first.first == la)
269 analysisStates.erase(it);
275 template <
typename AnchorT,
typename... Args>
277 return AnchorT::get(uniquer, std::forward<Args>(args)...);
283 using WorkItem = std::pair<ProgramPoint, DataFlowAnalysis *>;
289 template <
typename StateT,
typename AnchorT>
306 std::queue<WorkItem> worklist;
353 virtual void print(raw_ostream &os)
const = 0;
354 LLVM_DUMP_METHOD
void dump()
const;
374 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
460 template <
typename AnchorT>
466 template <
typename AnchorT,
typename... Args>
474 template <
typename StateT,
typename AnchorT>
482 template <
typename StateT,
typename AnchorT>
484 StateT *state = getOrCreate<StateT>(anchor);
492 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
505 template <
typename AnalysisT,
typename... Args>
507 childAnalyses.emplace_back(
new AnalysisT(*
this, std::forward<Args>(args)...));
508 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
509 childAnalyses.back().get()->debugName = llvm::getTypeName<AnalysisT>();
511 return static_cast<AnalysisT *
>(childAnalyses.back().get());
514 template <
typename StateT,
typename AnchorT>
516 std::unique_ptr<AnalysisState> &state =
517 analysisStates[{
LatticeAnchor(anchor), TypeID::get<StateT>()}];
519 state = std::unique_ptr<StateT>(
new StateT(anchor));
520 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
521 state->debugName = llvm::getTypeName<StateT>();
524 return static_cast<StateT *
>(state.get());
543 :
public DenseMapInfo<mlir::LatticeAnchor::ParentTy> {};
550 template <
typename To>
552 :
public CastInfo<To, mlir::LatticeAnchor::PointerUnion> {};
554 template <
typename To>
556 :
public CastInfo<To, const mlir::LatticeAnchor::PointerUnion> {};
558 template <
typename To>
560 :
public CastInfo<To, mlir::ProgramPoint::PointerUnion> {};
562 template <
typename To>
564 :
public CastInfo<To, const mlir::ProgramPoint::PointerUnion> {};
Base class for generic analysis states.
AnalysisState(LatticeAnchor anchor)
Create the analysis state at the given lattice anchor.
LLVM_DUMP_METHOD void dump() const
LatticeAnchor getAnchor() const
Returns the lattice anchor this state is located at.
void addDependency(ProgramPoint point, DataFlowAnalysis *analysis)
Add a dependency to this analysis state on a lattice anchor and an analysis.
virtual void print(raw_ostream &os) const =0
Print the contents of the analysis state.
virtual void onUpdate(DataFlowSolver *solver) const
This function is called by the solver when the analysis state is updated to enqueue more work items.
LatticeAnchor anchor
The lattice anchor to which the state belongs.
Block represents an ordered list of Operations.
Base class for all data-flow analyses.
void propagateIfChanged(AnalysisState *state, ChangeResult changed)
Propagate an update to a state if it changed.
virtual LogicalResult visit(ProgramPoint point)=0
Visit the given program point.
AnchorT * getLatticeAnchor(Args &&...args)
Get or create a custom lattice anchor.
virtual ~DataFlowAnalysis()
StateT * getOrCreate(AnchorT anchor)
Get the analysis state associated with the lattice anchor.
const StateT * getOrCreateFor(ProgramPoint dependent, AnchorT anchor)
Get a read-only analysis state for the given point and create a dependency on dependent.
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.
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 lattice anchor on this analysis.
void registerAnchorKind()
Register a custom lattice anchor class.
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.
void enqueue(WorkItem item)
Push a work item onto the worklist.
void eraseState(AnchorT anchor)
Erase any analysis state associated with the given lattice anchor.
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(AnchorT anchor) const
Lookup an analysis state for the given lattice anchor.
const DataFlowConfig & getConfig() const
Get the configuration of the solver.
AnchorT * getLatticeAnchor(Args &&...args)
Get a uniqued lattice anchor instance.
StateT * getOrCreateState(AnchorT anchor)
Get the state associated with the given lattice anchor.
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 lattice anchor based on a concrete lattice anchor type and a content key.
bool operator==(const Value &value) const
Two lattice anchors are equal if their values are equal.
static ConcreteT * construct(StorageUniquer::StorageAllocator &alloc, ValueT &&value)
Allocate space for a lattice anchor and construct it in-place.
static bool classof(const GenericLatticeAnchor *point)
Provide LLVM-style RTTI using type IDs.
GenericLatticeAnchorBase(ValueT &&value)
Construct an instance of the lattice anchor using the provided value and the type ID of the concrete ...
const Value & getValue() const
Get the contents of the lattice anchor.
static ConcreteT * get(StorageUniquer &uniquer, Args &&...args)
Get a uniqued instance of this lattice anchor class with the given arguments.
Abstract class for generic lattice anchor.
virtual void print(raw_ostream &os) const =0
Print the lattice anchor.
TypeID getTypeID() const
Get the abstract lattice anchor's type identifier.
virtual Location getLoc() const =0
Get a derived source location for the lattice anchor.
GenericLatticeAnchor(TypeID typeID)
Create an abstract lattice anchor with type identifier.
virtual ~GenericLatticeAnchor()
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...
The OpAsmOpInterface, see OpAsmInterface.td for more details.
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)
Fundamental IR components are supported as first-class lattice anchor.
LatticeAnchor(Block *block)
LatticeAnchor(ParentTy point=nullptr)
Allow implicit conversion from the parent type.
LatticeAnchor(Operation *op)
Location getLoc() const
Get the source location of the lattice anchor.
LatticeAnchor(OpT op)
Allow implicit conversions from operation wrappers.
void print(raw_ostream &os) const
Print the lattice anchor.
Program point represents a specific location in the execution of a program.
ProgramPoint(ParentTy point=nullptr)
Allow implicit conversion from the parent type.
ProgramPoint(OpT op)
Allow implicit conversions from operation wrappers.
void print(raw_ostream &os) const
Print the program point.