LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
SparseAnalysis.h
Go to the documentation of this file.
1//===- SparseAnalysis.h - Sparse data-flow analysis -----------------------===//
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/SparseAnalysis.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/SparseAnalysis.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
37#include <llvm/ADT/SmallPtrSet.h>
38
39namespace llzk::dataflow {
40
41using AbstractSparseLattice = mlir::dataflow::AbstractSparseLattice;
42
43//===----------------------------------------------------------------------===//
44// AbstractSparseForwardDataFlowAnalysis
45//===----------------------------------------------------------------------===//
46
61class AbstractSparseForwardDataFlowAnalysis : public mlir::DataFlowAnalysis {
62public:
65 mlir::LogicalResult initialize(mlir::Operation *top) override;
66
72 mlir::LogicalResult visit(mlir::ProgramPoint *point) override;
73
74protected:
75 explicit AbstractSparseForwardDataFlowAnalysis(mlir::DataFlowSolver &solver);
76
79 virtual mlir::LogicalResult visitOperationImpl(
80 mlir::Operation *op, mlir::ArrayRef<const AbstractSparseLattice *> operandLattices,
81 mlir::ArrayRef<AbstractSparseLattice *> resultLattices
82 ) = 0;
83
86 mlir::CallOpInterface call, mlir::ArrayRef<const AbstractSparseLattice *> argumentLattices,
87 mlir::ArrayRef<AbstractSparseLattice *> resultLattices
88 ) = 0;
89
95 mlir::Operation *op, const mlir::RegionSuccessor &successor,
96 mlir::ArrayRef<AbstractSparseLattice *> argLattices, unsigned firstIndex
97 ) = 0;
98
100 virtual AbstractSparseLattice *getLatticeElement(mlir::Value value) = 0;
101
104 const AbstractSparseLattice *getLatticeElementFor(mlir::ProgramPoint *point, mlir::Value value);
105
107 virtual void setToEntryState(AbstractSparseLattice *lattice) = 0;
108 void setAllToEntryStates(mlir::ArrayRef<AbstractSparseLattice *> lattices);
109
111 void join(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs);
112
114 mlir::SymbolTableCollection tables;
115
116private:
118 mlir::LogicalResult initializeRecursively(mlir::Operation *op);
119
123 mlir::LogicalResult visitOperation(mlir::Operation *op);
124
130 void visitBlock(mlir::Block *block);
131
136 void visitRegionSuccessors(
137 mlir::ProgramPoint *point, mlir::RegionBranchOpInterface branch,
138 mlir::RegionBranchPoint successor, mlir::ArrayRef<AbstractSparseLattice *> lattices
139 );
140};
141
142//===----------------------------------------------------------------------===//
143// SparseForwardDataFlowAnalysis
144//===----------------------------------------------------------------------===//
145
150template <typename StateT>
152 static_assert(
153 std::is_base_of<AbstractSparseLattice, StateT>::value,
154 "analysis state class expected to subclass AbstractSparseLattice"
155 );
156
157public:
158 explicit SparseForwardDataFlowAnalysis(mlir::DataFlowSolver &s)
160
163 virtual mlir::LogicalResult visitOperation(
164 mlir::Operation *op, mlir::ArrayRef<const StateT *> operands, mlir::ArrayRef<StateT *> results
165 ) = 0;
166
169 virtual void visitExternalCall(
170 mlir::CallOpInterface call, mlir::ArrayRef<const StateT *> argumentLattices,
171 mlir::ArrayRef<StateT *> resultLattices
172 ) {
173 setAllToEntryStates(resultLattices);
174 }
175
183 mlir::Operation *op, const mlir::RegionSuccessor &successor,
184 mlir::ArrayRef<StateT *> argLattices, unsigned firstIndex
185 ) {
186 setAllToEntryStates(argLattices.take_front(firstIndex));
187 setAllToEntryStates(argLattices.drop_front(firstIndex + successor.getSuccessorInputs().size()));
188 }
189
190protected:
192 StateT *getLatticeElement(mlir::Value value) override { return getOrCreate<StateT>(value); }
193
196 const StateT *getLatticeElementFor(mlir::ProgramPoint *point, mlir::Value value) {
197 return static_cast<const StateT *>(
199 );
200 }
201
203 virtual void setToEntryState(StateT *lattice) = 0;
204 void setAllToEntryStates(mlir::ArrayRef<StateT *> lattices) {
206 {reinterpret_cast<AbstractSparseLattice *const *>(lattices.begin()), lattices.size()}
207 );
208 }
209
210private:
213 llvm::LogicalResult visitOperationImpl(
214 mlir::Operation *op, mlir::ArrayRef<const AbstractSparseLattice *> operandLattices,
215 mlir::ArrayRef<AbstractSparseLattice *> resultLattices
216 ) override {
217 return visitOperation(
218 op,
219 {reinterpret_cast<const StateT *const *>(operandLattices.begin()), operandLattices.size()},
220 {reinterpret_cast<StateT *const *>(resultLattices.begin()), resultLattices.size()}
221 );
222 }
223 void visitExternalCallImpl(
224 mlir::CallOpInterface call, mlir::ArrayRef<const AbstractSparseLattice *> argumentLattices,
225 mlir::ArrayRef<AbstractSparseLattice *> resultLattices
226 ) override {
228 call,
229 {reinterpret_cast<const StateT *const *>(argumentLattices.begin()),
230 argumentLattices.size()},
231 {reinterpret_cast<StateT *const *>(resultLattices.begin()), resultLattices.size()}
232 );
233 }
234 void visitNonControlFlowArgumentsImpl(
235 mlir::Operation *op, const mlir::RegionSuccessor &successor,
236 mlir::ArrayRef<AbstractSparseLattice *> argLattices, unsigned firstIndex
237 ) override {
239 op, successor, {reinterpret_cast<StateT *const *>(argLattices.begin()), argLattices.size()},
240 firstIndex
241 );
242 }
243 void setToEntryState(AbstractSparseLattice *lattice) override {
244 return setToEntryState(reinterpret_cast<StateT *>(lattice));
245 }
246};
247
248} // namespace llzk::dataflow
mlir::LogicalResult visit(mlir::ProgramPoint *point) override
Visit a program point.
mlir::LogicalResult initialize(mlir::Operation *top) override
Initialize the analysis by visiting every owner of an SSA value: all operations and blocks.
virtual mlir::LogicalResult visitOperationImpl(mlir::Operation *op, mlir::ArrayRef< const AbstractSparseLattice * > operandLattices, mlir::ArrayRef< AbstractSparseLattice * > resultLattices)=0
The operation transfer function.
virtual AbstractSparseLattice * getLatticeElement(mlir::Value value)=0
Get the lattice element of a value.
AbstractSparseForwardDataFlowAnalysis(mlir::DataFlowSolver &solver)
void setAllToEntryStates(mlir::ArrayRef< AbstractSparseLattice * > lattices)
const AbstractSparseLattice * getLatticeElementFor(mlir::ProgramPoint *point, mlir::Value value)
Get a read-only lattice element for a value and add it as a dependency to a program point.
void join(AbstractSparseLattice *lhs, const AbstractSparseLattice &rhs)
Join the lattice element and propagate and update if it changed.
virtual void setToEntryState(AbstractSparseLattice *lattice)=0
Set the given lattice element(s) at control flow entry point(s).
mlir::SymbolTableCollection tables
LLZK: Added for use of symbol helper caching.
virtual void visitNonControlFlowArgumentsImpl(mlir::Operation *op, const mlir::RegionSuccessor &successor, mlir::ArrayRef< AbstractSparseLattice * > argLattices, unsigned firstIndex)=0
Given an operation with region control-flow, the lattices of the operands, and a region successor,...
virtual void visitExternalCallImpl(mlir::CallOpInterface call, mlir::ArrayRef< const AbstractSparseLattice * > argumentLattices, mlir::ArrayRef< AbstractSparseLattice * > resultLattices)=0
The transfer function for calls to external functions.
const StateT * getLatticeElementFor(mlir::ProgramPoint *point, mlir::Value value)
Get the lattice element for a value and create a dependency on the provided program point.
virtual void visitNonControlFlowArguments(mlir::Operation *op, const mlir::RegionSuccessor &successor, mlir::ArrayRef< StateT * > argLattices, unsigned firstIndex)
Given an operation with possible region control-flow, the lattices of the operands,...
SparseForwardDataFlowAnalysis(mlir::DataFlowSolver &s)
void setAllToEntryStates(mlir::ArrayRef< StateT * > lattices)
virtual void visitExternalCall(mlir::CallOpInterface call, mlir::ArrayRef< const StateT * > argumentLattices, mlir::ArrayRef< StateT * > resultLattices)
Visit a call operation to an externally defined function given the lattices of its arguments.
virtual mlir::LogicalResult visitOperation(mlir::Operation *op, mlir::ArrayRef< const StateT * > operands, mlir::ArrayRef< StateT * > results)=0
Visit an operation with the lattices of its operands.
virtual void setToEntryState(StateT *lattice)=0
Set the given lattice element(s) at control flow entry point(s).
StateT * getLatticeElement(mlir::Value value) override
Get the lattice element for a value.
mlir::dataflow::AbstractSparseLattice AbstractSparseLattice