LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
ConstraintDependencyGraph.h
Go to the documentation of this file.
1//===-- ConstraintDependencyGraph.h -----------------------------*- 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//===----------------------------------------------------------------------===//
9
10#pragma once
11
16
17#include <mlir/Pass/AnalysisManager.h>
18
19#include <llvm/ADT/EquivalenceClasses.h>
20
21namespace mlir {
22
23class DataFlowSolver;
24
25} // namespace mlir
26
27namespace llzk {
28
29using ConstrainRefRemappings = std::vector<std::pair<ConstrainRef, ConstrainRefLatticeValue>>;
30
36public:
37 using dataflow::DenseForwardDataFlowAnalysis<ConstrainRefLattice>::DenseForwardDataFlowAnalysis;
38
40 mlir::CallOpInterface call, dataflow::CallControlFlowAction action,
41 const ConstrainRefLattice &before, ConstrainRefLattice *after
42 ) override;
43
48 void visitOperation(
49 mlir::Operation *op, const ConstrainRefLattice &before, ConstrainRefLattice *after
50 ) override;
51
52protected:
53 void setToEntryState(ConstrainRefLattice *lattice) override {
54 // the entry state is empty, so do nothing.
55 }
56
57 // Perform a standard union of operands into the results value.
58 mlir::ChangeResult fallbackOpUpdate(
59 mlir::Operation *op, const ConstrainRefLattice::ValueMap &operandVals,
60 const ConstrainRefLattice &before, ConstrainRefLattice *after
61 );
62
63 // Perform the update for either a array.read op or an array.extract op, which
64 // operate very similarly: index into the first operand using a variable number
65 // of provided indices.
68 const ConstrainRefLattice &before, ConstrainRefLattice *after
69 );
70
71private:
72 mlir::SymbolTableCollection tables;
73};
74
102public:
114 static mlir::FailureOr<ConstraintDependencyGraph> compute(
115 mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver,
116 mlir::AnalysisManager &am, bool runIntraprocedural
117 );
118
120 void dump() const;
123 void print(mlir::raw_ostream &os) const;
124
133
143
144 const ConstrainRefLattice::Ref2Val &getRef2Val() const { return ref2Val; }
145
146 /*
147 Rule of three, needed for the mlir::SymbolTableCollection, which has no copy constructor.
148 Since the mlir::SymbolTableCollection is a caching mechanism, we simply allow default, empty
149 construction for copies.
150 */
151
153 : mod(other.mod), structDef(other.structDef), runIntraprocedural(other.runIntraprocedural),
154 signalSets(other.signalSets), constantSets(other.constantSets), ref2Val(other.ref2Val),
155 tables() {}
156
158 mod = other.mod;
159 structDef = other.structDef;
160 runIntraprocedural = other.runIntraprocedural;
161 signalSets = other.signalSets;
162 constantSets = other.constantSets;
163 ref2Val = other.ref2Val;
164 return *this;
165 }
166 virtual ~ConstraintDependencyGraph() = default;
167
168private:
169 mlir::ModuleOp mod;
170 // Using mutable because many operations are not const by default, even for "const"-like
171 // operations, like "getName()", and this reduces const_casts.
172 mutable component::StructDefOp structDef;
173 bool runIntraprocedural;
174
175 // Transitive closure only over signals.
176 llvm::EquivalenceClasses<ConstrainRef> signalSets;
177 // A simple set mapping of constants, as we do not want to compute a transitive closure over
178 // constants.
179 std::unordered_map<ConstrainRef, ConstrainRefSet, ConstrainRef::Hash> constantSets;
180
181 // Maps references to the values where they are found.
183
184 // Also mutable for caching within otherwise const lookup operations.
185 mutable mlir::SymbolTableCollection tables;
186
193 mlir::ModuleOp m, component::StructDefOp s, bool intraprocedural = false
194 )
195 : mod(m), structDef(s), runIntraprocedural(intraprocedural) {}
196
202 mlir::LogicalResult computeConstraints(mlir::DataFlowSolver &solver, mlir::AnalysisManager &am);
203
210 void walkConstrainOp(mlir::DataFlowSolver &solver, mlir::Operation *emitOp);
211};
212
215 bool runIntraprocedural = false;
216
218};
219
225 : public StructAnalysis<ConstraintDependencyGraph, CDGAnalysisContext> {
226public:
229
230 mlir::LogicalResult runAnalysis(
231 mlir::DataFlowSolver &solver, mlir::AnalysisManager &moduleAnalysisManager,
233 ) override {
234 return runAnalysis(solver, moduleAnalysisManager, ctx.runIntraproceduralAnalysis());
235 }
236
239 mlir::LogicalResult runAnalysis(
240 mlir::DataFlowSolver &solver, mlir::AnalysisManager &moduleAnalysisManager,
241 bool runIntraprocedural
242 );
243};
244
248 : public ModuleAnalysis<
249 ConstraintDependencyGraph, CDGAnalysisContext, ConstraintDependencyGraphStructAnalysis> {
250
251public:
254
255 void setIntraprocedural(bool runIntraprocedural) { intraprocedural = runIntraprocedural; }
256
257protected:
258 void initializeSolver() override { (void)solver.load<ConstrainRefAnalysis>(); }
259
260 CDGAnalysisContext getContext() override { return {.runIntraprocedural = intraprocedural}; }
261
262private:
263 bool intraprocedural = false;
264};
265
266} // namespace llzk
Convenience classes for a frequent pattern of dataflow analysis used in LLZK, where an analysis is ru...
The dataflow analysis that computes the set of references that LLZK operations use and produce.
void visitCallControlFlowTransfer(mlir::CallOpInterface call, dataflow::CallControlFlowAction action, const ConstrainRefLattice &before, ConstrainRefLattice *after) override
Hook for customizing the behavior of lattice propagation along the call control flow edges.
mlir::ChangeResult fallbackOpUpdate(mlir::Operation *op, const ConstrainRefLattice::ValueMap &operandVals, const ConstrainRefLattice &before, ConstrainRefLattice *after)
void setToEntryState(ConstrainRefLattice *lattice) override
Set the dense lattice at control flow entry point and propagate an update if it changed.
void arraySubdivisionOpUpdate(array::ArrayAccessOpInterface op, const ConstrainRefLattice::ValueMap &operandVals, const ConstrainRefLattice &before, ConstrainRefLattice *after)
void visitOperation(mlir::Operation *op, const ConstrainRefLattice &before, ConstrainRefLattice *after) override
Propagate constrain reference lattice values from operands to results.
A lattice for use in dense analysis.
mlir::DenseMap< ValueTy, ConstrainRefLatticeValue > ValueMap
mlir::DenseMap< ConstrainRef, mlir::DenseSet< ValueTy > > Ref2Val
Defines a reference to a llzk object within a constrain function call.
A module-level analysis for constructing ConstraintDependencyGraph objects for all structs in the giv...
ModuleAnalysis(mlir::Operation *op)
Asserts that the analysis is being run on a ModuleOp.
CDGAnalysisContext getContext() override
Create and return a valid Context object.
virtual ~ConstraintDependencyGraphModuleAnalysis()=default
void initializeSolver() override
Initialize the shared dataflow solver with any common analyses required by the contained struct analy...
An analysis wrapper around the ConstraintDependencyGraph for a given struct.
mlir::LogicalResult runAnalysis(mlir::DataFlowSolver &solver, mlir::AnalysisManager &moduleAnalysisManager, CDGAnalysisContext &ctx) override
Perform the analysis and construct the Result output.
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
virtual ~ConstraintDependencyGraphStructAnalysis()=default
static mlir::FailureOr< ConstraintDependencyGraph > compute(mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver, mlir::AnalysisManager &am, bool runIntraprocedural)
Compute a ConstraintDependencyGraph (CDG)
ConstraintDependencyGraph & operator=(const ConstraintDependencyGraph &other)
void print(mlir::raw_ostream &os) const
Print the CDG to the specified output stream.
ConstraintDependencyGraph translate(ConstrainRefRemappings translation) const
Translate the ConstrainRefs in this CDG to that of a different context.
ConstrainRefSet getConstrainingValues(const ConstrainRef &ref) const
Get the values that are connected to the given ref via emitted constraints.
const ConstrainRefLattice::Ref2Val & getRef2Val() const
ConstraintDependencyGraph(const ConstraintDependencyGraph &other)
virtual ~ConstraintDependencyGraph()=default
void dump() const
Dumps the CDG to stderr.
ModuleAnalysis(mlir::Operation *op)
Asserts that the analysis is being run on a ModuleOp.
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
LLZK: This class has been ported so that it can inherit from our port of the AbstractDenseForwardData...
mlir::dataflow::CallControlFlowAction CallControlFlowAction
std::vector< std::pair< ConstrainRef, ConstrainRefLatticeValue > > ConstrainRefRemappings
Parameters and shared objects to pass to child analyses.