31#include <mlir/IR/BuiltinOps.h>
32#include <mlir/Pass/AnalysisManager.h>
48 structDefOp = mlir::dyn_cast<component::StructDefOp>(op);
50 auto error_message =
"StructAnalysis expects provided op to be a StructDefOp!";
51 op->emitError(error_message);
52 llvm::report_fatal_error(error_message);
55 if (mlir::failed(maybeModOp)) {
56 auto error_message =
"StructAnalysis could not find root module from StructDefOp!";
57 op->emitError(error_message);
58 llvm::report_fatal_error(error_message);
75 mlir::DataFlowSolver &solver, mlir::AnalysisManager &moduleAnalysisManager, Context &ctx
83 ensure(
constructed(), mlir::Twine(__PRETTY_FUNCTION__) +
": result has not been constructed");
95 void setResult(Result &&r) { res = std::make_unique<Result>(r); }
100 std::unique_ptr<Result> res;
108template <
typename Analysis,
typename Result,
typename Context>
110 requires {
requires std::is_base_of<StructAnalysis<Result, Context>, Analysis>::value; };
118template <
typename Result,
typename Context, StructAnalysisType<Result, Context> StructAnalysisTy>
122 using ResultMap = std::map<
132 if (modOp = mlir::dyn_cast<mlir::ModuleOp>(op); !modOp) {
133 auto error_message =
"ModuleAnalysis expects provided op to be an mlir::ModuleOp!";
134 op->emitError(error_message);
135 llvm::report_fatal_error(error_message);
150 ensureResultCreated(op);
151 return results.at(op).get();
154 ResultMap::iterator
begin() {
return results.begin(); }
155 ResultMap::iterator
end() {
return results.end(); }
156 ResultMap::const_iterator
cbegin()
const {
return results.cbegin(); }
157 ResultMap::const_iterator
cend()
const {
return results.cend(); }
159 const mlir::DataFlowSolver &
getSolver()
const {
return solver; }
181 auto res = solver.initializeAndRun(modOp);
182 ensure(res.succeeded(),
"solver failed to run on module!");
186 auto &childAnalysis = am.getChildAnalysis<StructAnalysisTy>(s);
187 if (mlir::failed(childAnalysis.runAnalysis(solver, am, ctx))) {
188 auto error_message =
"StructAnalysis failed to run for " + mlir::Twine(s.getName());
189 s->emitError(error_message);
190 llvm::report_fatal_error(error_message);
192 ensure(results.find(s) == results.end(),
"struct location conflict");
193 results.insert(std::make_pair(s, std::reference_wrapper(childAnalysis.getResult())));
194 return mlir::WalkResult::skip();
199 mlir::ModuleOp modOp;
201 mlir::DataFlowSolver solver;
206 ensure(
hasResult(op),
"Result does not exist for StructDefOp " + mlir::Twine(op.getName()));
This file implements (LLZK-tailored) dense data-flow analysis using the data-flow analysis framework.
virtual void initializeSolver(mlir::DataFlowSolver &solver)=0
Initialize the shared dataflow solver with any common analyses required by the contained struct analy...
virtual Context getContext()=0
Create and return a valid Context object.
ModuleAnalysis(mlir::Operation *op)
Asserts that the analysis is being run on a ModuleOp.
ResultMap::const_iterator cbegin() const
ResultMap::iterator begin()
virtual void runAnalysis(mlir::AnalysisManager &am)
Run the StructAnalysisTy struct analysis on all child structs.
ResultMap::iterator end()
const Result & getResult(component::StructDefOp op) const
Asserts that op has a result and returns it.
void constructChildAnalyses(mlir::AnalysisManager &am)
Construct and run the StructAnalysisTy analyses on each StructDefOp contained in the ModuleOp that is...
ResultMap::const_iterator cend() const
bool hasResult(component::StructDefOp op) const
Checks if op has a result contained in the current result map.
const mlir::DataFlowSolver & getSolver() const
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
component::StructDefOp getStruct() const
Get the current StructDefOp that is under analysis.
virtual mlir::LogicalResult runAnalysis(mlir::DataFlowSolver &solver, mlir::AnalysisManager &moduleAnalysisManager, Context &ctx)=0
Perform the analysis and construct the Result output.
mlir::ModuleOp getModule() const
Get the ModuleOp that is the parent of the StructDefOp that is under analysis.
bool constructed() const
Query if the analysis has constructed a Result object.
void setResult(Result &&r)
Initialize the final Result object.
const Result & getResult() const
Access the result iff it has been created.
Any type that is a subclass of StructAnalysis.
void markAllOpsAsLive(mlir::DataFlowSolver &solver, mlir::Operation *top)
LLZK: Added this utility to ensure analysis is performed for all structs in a given module.
FailureOr< ModuleOp > getRootModule(Operation *from)
void ensure(bool condition, llvm::Twine errMsg)
An empty struct that is used for convenience for analyses that do not require any context.