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::dataflow {
38
39//===----------------------------------------------------------------------===//
40// Utilities
41//===----------------------------------------------------------------------===//
42
50void markAllOpsAsLive(mlir::DataFlowSolver &solver, mlir::Operation *top);
51
52//===----------------------------------------------------------------------===//
53// AbstractDenseForwardDataFlowAnalysis
54//===----------------------------------------------------------------------===//
55
56using AbstractDenseLattice = mlir::dataflow::AbstractDenseLattice;
57using CallControlFlowAction = mlir::dataflow::CallControlFlowAction;
58
72class AbstractDenseForwardDataFlowAnalysis : public mlir::DataFlowAnalysis {
73public:
74 using mlir::DataFlowAnalysis::DataFlowAnalysis;
75
78 mlir::LogicalResult initialize(mlir::Operation *top) override;
79
87 mlir::LogicalResult visit(mlir::ProgramPoint *point) override;
88
89protected:
92 virtual mlir::LogicalResult visitOperationImpl(
93 mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after
94 ) = 0;
95
97 virtual AbstractDenseLattice *getLattice(mlir::LatticeAnchor anchor) = 0;
98
104 getLatticeFor(mlir::ProgramPoint *dependent, mlir::LatticeAnchor anchor);
105
108 virtual void setToEntryState(AbstractDenseLattice *lattice) = 0;
109
112 propagateIfChanged(lhs, lhs->join(rhs));
113 }
114
119 virtual mlir::LogicalResult processOperation(mlir::Operation *op);
120
129 mlir::RegionBranchOpInterface /*branch*/, std::optional<unsigned> regionFrom,
130 std::optional<unsigned> regionTo, const AbstractDenseLattice &before,
132 ) {
133 join(after, before);
134 }
135
144 mlir::CallOpInterface /*call*/, CallControlFlowAction action,
145 const AbstractDenseLattice &before, AbstractDenseLattice *after
146 ) {
147 join(after, before);
148 // Note that `setToEntryState` may be a "partial fixpoint" for some
149 // lattices, e.g., lattices that are lists of maps of other lattices will
150 // only set fixpoint for "known" lattices.
151 if (action == CallControlFlowAction::ExternalCallee) {
152 setToEntryState(after);
153 }
154 }
155
160 mlir::ProgramPoint *point, mlir::RegionBranchOpInterface branch, AbstractDenseLattice *after
161 );
162
164 mlir::SymbolTableCollection tables;
165
166private:
169 void visitBlock(mlir::Block *block);
170
173 void visitCallOperation(
174 mlir::CallOpInterface call, const AbstractDenseLattice &before, AbstractDenseLattice *after
175 );
176};
177
178//===----------------------------------------------------------------------===//
179// DenseForwardDataFlowAnalysis
180//===----------------------------------------------------------------------===//
181
190template <typename LatticeT>
192 static_assert(
193 std::is_base_of<AbstractDenseLattice, LatticeT>::value,
194 "analysis state class expected to subclass AbstractDenseLattice"
195 );
196
197public:
198 using AbstractDenseForwardDataFlowAnalysis::AbstractDenseForwardDataFlowAnalysis;
199
203 virtual mlir::LogicalResult
204 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::LatticeAnchor anchor) override {
263 return getOrCreate<LatticeT>(anchor);
264 }
265
268 virtual void setToEntryState(LatticeT *lattice) = 0;
269 void setToEntryState(AbstractDenseLattice *lattice) override {
270 setToEntryState(static_cast<LatticeT *>(lattice));
271 }
272
275 mlir::LogicalResult visitOperationImpl(
276 mlir::Operation *op, const AbstractDenseLattice &before, AbstractDenseLattice *after
277 ) final {
278 return visitOperation(
279 op, static_cast<const LatticeT &>(before), static_cast<LatticeT *>(after)
280 );
281 }
283 mlir::CallOpInterface call, CallControlFlowAction action, const AbstractDenseLattice &before,
285 ) final {
287 call, action, static_cast<const LatticeT &>(before), static_cast<LatticeT *>(after)
288 );
289 }
291 mlir::RegionBranchOpInterface branch, std::optional<unsigned> regionFrom,
292 std::optional<unsigned> regionTo, const AbstractDenseLattice &before,
294 ) final {
296 branch, regionFrom, regionTo, static_cast<const LatticeT &>(before),
297 static_cast<LatticeT *>(after)
298 );
299 }
300};
301
302} // namespace llzk::dataflow
LLZK: This class has been ported from the MLIR DenseAnalysis utilities to allow for the use of custom...
void join(AbstractDenseLattice *lhs, const AbstractDenseLattice &rhs)
Join a lattice with another and propagate an update if it changed.
virtual void visitCallControlFlowTransfer(mlir::CallOpInterface, CallControlFlowAction action, const AbstractDenseLattice &before, AbstractDenseLattice *after)
Propagate the dense lattice forward along the call control flow edge, which can be either entering or...
virtual mlir::LogicalResult processOperation(mlir::Operation *op)
Visit an operation.
virtual AbstractDenseLattice * getLattice(mlir::LatticeAnchor anchor)=0
Get the dense lattice on the given lattice anchor.
mlir::LogicalResult visit(mlir::ProgramPoint *point) override
Visit a program point that modifies the state of the program.
void visitRegionBranchOperation(mlir::ProgramPoint *point, mlir::RegionBranchOpInterface branch, AbstractDenseLattice *after)
Visit a program point within a region branch operation with predecessors in it.
mlir::SymbolTableCollection tables
LLZK: Added for use of symbol helper caching.
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;...
virtual void visitRegionBranchControlFlowTransfer(mlir::RegionBranchOpInterface, 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...
const AbstractDenseLattice * getLatticeFor(mlir::ProgramPoint *dependent, mlir::LatticeAnchor anchor)
Get the dense lattice on the given lattice anchor and add dependent as its dependency.
virtual mlir::LogicalResult 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.
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...
void setToEntryState(AbstractDenseLattice *lattice) override
Set the dense lattice at control flow entry point and propagate an update if it changed.
mlir::LogicalResult 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 mlir::LogicalResult visitOperation(mlir::Operation *op, const LatticeT &before, LatticeT *after)=0
Visit an operation with the dense lattice before its execution.
virtual void setToEntryState(LatticeT *lattice)=0
Set the dense lattice at control flow entry point and propagate an update if it changed.
LatticeT * getLattice(mlir::LatticeAnchor anchor) override
Get the dense lattice on this lattice anchor.
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(DataFlowSolver &solver, Operation *top)
mlir::dataflow::AbstractDenseLattice AbstractDenseLattice
mlir::dataflow::CallControlFlowAction CallControlFlowAction