LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
DenseAnalysis.h
Go to the documentation of this file.
1//===-- DenseAnalysis.h - Dense data-flow analysis --------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8// Adapted from mlir/include/mlir/Analysis/DataFlow/DenseAnalysis.h.
9// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10// See https://llvm.org/LICENSE.txt for license information.
11// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
12//
13//===----------------------------------------------------------------------===//
27//===----------------------------------------------------------------------===//
28
29#pragma once
30
31#include <mlir/Analysis/DataFlow/DenseAnalysis.h>
32#include <mlir/Analysis/DataFlowFramework.h>
33#include <mlir/IR/SymbolTable.h>
34#include <mlir/Interfaces/CallInterfaces.h>
35#include <mlir/Interfaces/ControlFlowInterfaces.h>
36
37namespace llzk {
38namespace dataflow {
39
40//===----------------------------------------------------------------------===//
41// Utilities
42//===----------------------------------------------------------------------===//
43
51void markAllOpsAsLive(mlir::DataFlowSolver &solver, mlir::Operation *top);
52
53//===----------------------------------------------------------------------===//
54// AbstractDenseForwardDataFlowAnalysis
55//===----------------------------------------------------------------------===//
56
57using AbstractDenseLattice = mlir::dataflow::AbstractDenseLattice;
58using CallControlFlowAction = mlir::dataflow::CallControlFlowAction;
59
75class AbstractDenseForwardDataFlowAnalysis : public mlir::DataFlowAnalysis {
76public:
77 using mlir::DataFlowAnalysis::DataFlowAnalysis;
78
81 mlir::LogicalResult initialize(mlir::Operation *top) override;
82
89 mlir::LogicalResult visit(mlir::ProgramPoint point) override;
90
91protected:
94 virtual void visitOperationImpl(
95 mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after
96 ) = 0;
97
99 virtual AbstractDenseLattice *getLattice(mlir::ProgramPoint point) = 0;
100
105 const AbstractDenseLattice *getLatticeFor(mlir::ProgramPoint dependent, mlir::ProgramPoint point);
106
109 virtual void setToEntryState(AbstractDenseLattice *lattice) = 0;
110
113 propagateIfChanged(lhs, lhs->join(rhs));
114 }
115
120 virtual void processOperation(mlir::Operation *op);
121
130 mlir::RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
131 std::optional<unsigned> regionTo, const AbstractDenseLattice &before,
133 ) {
134 join(after, before);
135 }
136
145 mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before,
147 ) {
148 join(after, before);
149 // Note that `setToEntryState` may be a "partial fixpoint" for some
150 // lattices, e.g., lattices that are lists of maps of other lattices will
151 // only set fixpoint for "known" lattices.
152 if (action == CallControlFlowAction::ExternalCallee) {
153 setToEntryState(after);
154 }
155 }
156
161 mlir::ProgramPoint point, mlir::RegionBranchOpInterface branch, AbstractDenseLattice *after
162 );
163
165 mlir::SymbolTableCollection tables;
166
167private:
170 void visitBlock(mlir::Block *block);
171
174 void visitCallOperation(
175 mlir::CallOpInterface call, const AbstractDenseLattice &before, AbstractDenseLattice *after
176 );
177};
178
179//===----------------------------------------------------------------------===//
180// DenseForwardDataFlowAnalysis
181//===----------------------------------------------------------------------===//
182
191template <typename LatticeT>
193 static_assert(
194 std::is_base_of<AbstractDenseLattice, LatticeT>::value,
195 "analysis state class expected to subclass AbstractDenseLattice"
196 );
197
198public:
199 using AbstractDenseForwardDataFlowAnalysis::AbstractDenseForwardDataFlowAnalysis;
200
204 virtual void visitOperation(mlir::Operation *op, const LatticeT &before, LatticeT *after) = 0;
205
222 mlir::CallOpInterface call, CallControlFlowAction action, const LatticeT &before,
223 LatticeT *after
224 ) {
226 }
227
252 mlir::RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
253 std::optional<unsigned> regionTo, const LatticeT &before, LatticeT *after
254 ) {
256 branch, regionFrom, regionTo, before, after
257 );
258 }
259
260protected:
262 LatticeT *getLattice(mlir::ProgramPoint point) override { return getOrCreate<LatticeT>(point); }
263
266 virtual void setToEntryState(LatticeT *lattice) = 0;
267 void setToEntryState(AbstractDenseLattice *lattice) override {
268 setToEntryState(static_cast<LatticeT *>(lattice));
269 }
270
274 mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after
275 ) final {
276 visitOperation(op, static_cast<const LatticeT &>(before), static_cast<LatticeT *>(after));
277 }
279 mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before,
281 ) final {
283 call, action, static_cast<const LatticeT &>(before), static_cast<LatticeT *>(after)
284 );
285 }
287 mlir::RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
288 std::optional<unsigned> regionTo, const AbstractDenseLattice &before,
290 ) final {
292 branch, regionFrom, regionTo, static_cast<const LatticeT &>(before),
293 static_cast<LatticeT *>(after)
294 );
295 }
296};
297
298} // namespace dataflow
299} // namespace llzk
LLZK: This class has been ported from the MLIR DenseAnalysis utilities to allow for the use of custom...
virtual void visitOperationImpl(mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after)=0
Propagate the dense lattice before the execution of an operation to the lattice after its execution.
void visitRegionBranchOperation(mlir::ProgramPoint point, mlir::RegionBranchOpInterface branch, AbstractDenseLattice *after)
Visit a program point within a region branch operation with predecessors in it.
void join(AbstractDenseLattice *lhs, const AbstractDenseLattice &rhs)
Join a lattice with another and propagate an update if it changed.
virtual void visitCallControlFlowTransfer(mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
const AbstractDenseLattice * getLatticeFor(mlir::ProgramPoint dependent, mlir::ProgramPoint point)
Get the dense lattice after the execution of the given program point and add it as a dependency to a ...
mlir::SymbolTableCollection tables
LLZK: Added for use of symbol helper caching.
virtual void processOperation(mlir::Operation *op)
Visit an operation.
virtual void setToEntryState(AbstractDenseLattice *lattice)=0
Set the dense lattice at control flow entry point and propagate an update if it changed.
mlir::LogicalResult initialize(mlir::Operation *top) override
Initialize the analysis by visiting every program point whose execution may modify the program state;...
mlir::LogicalResult visit(mlir::ProgramPoint point) override
Visit a program point that modifies the state of the program.
virtual AbstractDenseLattice * getLattice(mlir::ProgramPoint point)=0
Get the dense lattice after the execution of the given program point.
virtual void visitRegionBranchControlFlowTransfer(mlir::RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the control flow edge from regionFrom to regionTo regions o...
LLZK: This class has been ported so that it can inherit from our port of the AbstractDenseForwardData...
void visitCallControlFlowTransfer(mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
LatticeT * getLattice(mlir::ProgramPoint point) override
Get the dense lattice after this program point.
void setToEntryState(AbstractDenseLattice *lattice) override
Set the dense lattice at control flow entry point and propagate an update if it changed.
virtual void visitOperation(mlir::Operation *op, const LatticeT &before, LatticeT *after)=0
Visit an operation with the dense lattice before its execution.
void visitOperationImpl(mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Type-erased wrappers that convert the abstract dense lattice to a derived lattice and invoke the virt...
virtual void setToEntryState(LatticeT *lattice)=0
Set the dense lattice at control flow entry point and propagate an update if it changed.
virtual void visitCallControlFlowTransfer(mlir::CallOpInterface call, CallControlFlowAction action, const LatticeT &before, LatticeT *after)
Hook for customizing the behavior of lattice propagation along the call control flow edges.
virtual void visitRegionBranchControlFlowTransfer(mlir::RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const LatticeT &before, LatticeT *after)
Hook for customizing the behavior of lattice propagation along the control flow edges between regions...
void visitRegionBranchControlFlowTransfer(mlir::RegionBranchOpInterface branch, std::optional< unsigned > regionFrom, std::optional< unsigned > regionTo, const AbstractDenseLattice &before, AbstractDenseLattice *after) final
Propagate the dense lattice forward along the control flow edge from regionFrom to regionTo regions o...
void markAllOpsAsLive(mlir::DataFlowSolver &solver, mlir::Operation *top)
LLZK: Added this utility to ensure analysis is performed for all structs in a given module.
mlir::dataflow::AbstractDenseLattice AbstractDenseLattice
mlir::dataflow::CallControlFlowAction CallControlFlowAction