LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
IntervalAnalysis.h
Go to the documentation of this file.
1//===-- IntervalAnalysis.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#include "llzk/Analysis/Field.h"
27#include "llzk/Util/Compare.h"
28
29#include <mlir/IR/BuiltinOps.h>
30#include <mlir/Pass/AnalysisManager.h>
31#include <mlir/Support/LLVM.h>
32
33#include <llvm/ADT/MapVector.h>
34#include <llvm/Support/SMTAPI.h>
35
36#include <array>
37#include <mutex>
38
39namespace llzk {
40
41/* ExpressionValue */
42
46public:
47 /* Must be default initializable to be a ScalarLatticeValue. */
48 ExpressionValue() : i(), expr(nullptr) {}
49
50 explicit ExpressionValue(const Field &f, llvm::SMTExprRef exprRef)
51 : i(Interval::Entire(f)), expr(exprRef) {}
52
53 ExpressionValue(const Field &f, llvm::SMTExprRef exprRef, llvm::APSInt singleVal)
54 : i(Interval::Degenerate(f, singleVal)), expr(exprRef) {}
55
56 ExpressionValue(llvm::SMTExprRef exprRef, Interval interval) : i(interval), expr(exprRef) {}
57
58 llvm::SMTExprRef getExpr() const { return expr; }
59
60 const Interval &getInterval() const { return i; }
61
62 const Field &getField() const { return i.getField(); }
63
67 ExpressionValue withInterval(const Interval &newInterval) const {
68 return ExpressionValue(expr, newInterval);
69 }
70
71 /* Required to be a ScalarLatticeValue. */
75 return *this;
76 }
77
78 bool operator==(const ExpressionValue &rhs) const;
79
86 friend ExpressionValue
87 intersection(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
88
95 friend ExpressionValue
96 join(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
97
98 // arithmetic ops
99
100 friend ExpressionValue
101 add(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
102
103 friend ExpressionValue
104 sub(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
105
106 friend ExpressionValue
107 mul(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
108
109 friend ExpressionValue
110 div(llvm::SMTSolverRef solver, felt::DivFeltOp op, const ExpressionValue &lhs,
111 const ExpressionValue &rhs);
112
113 friend ExpressionValue
114 mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
115
116 friend ExpressionValue
117 bitAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
118
119 friend ExpressionValue
120 shiftLeft(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
121
122 friend ExpressionValue
123 shiftRight(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
124
125 friend ExpressionValue
126 cmp(llvm::SMTSolverRef solver, boolean::CmpOp op, const ExpressionValue &lhs,
127 const ExpressionValue &rhs);
128
129 friend ExpressionValue
130 boolAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
131
132 friend ExpressionValue
133 boolOr(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
134
135 friend ExpressionValue
136 boolXor(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
137
147 llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &lhs,
148 const ExpressionValue &rhs
149 );
150
151 friend ExpressionValue neg(llvm::SMTSolverRef solver, const ExpressionValue &val);
152
153 friend ExpressionValue notOp(llvm::SMTSolverRef solver, const ExpressionValue &val);
154
155 friend ExpressionValue boolNot(llvm::SMTSolverRef solver, const ExpressionValue &val);
156
157 friend ExpressionValue
158 fallbackUnaryOp(llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &val);
159
160 /* Utility */
161
162 void print(mlir::raw_ostream &os) const;
163
164 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const ExpressionValue &e) {
165 e.print(os);
166 return os;
167 }
168
169 struct Hash {
170 unsigned operator()(const ExpressionValue &e) const {
171 return Interval::Hash {}(e.i) ^ llvm::hash_value(e.expr);
172 }
173 };
174
175private:
176 Interval i;
177 llvm::SMTExprRef expr;
178};
179
180/* IntervalAnalysisLatticeValue */
181
183 : public dataflow::AbstractLatticeValue<IntervalAnalysisLatticeValue, ExpressionValue> {
184public:
185 using AbstractLatticeValue::AbstractLatticeValue;
186};
187
188/* IntervalAnalysisLattice */
189
191
195public:
197 // Map mlir::Values to LatticeValues
198 using ValueMap = mlir::DenseMap<mlir::Value, LatticeValue>;
199 // Map field references to LatticeValues. Used for field reads and writes.
200 // Structure is component value -> field attribute -> latticeValue
201 using FieldMap = mlir::DenseMap<mlir::Value, mlir::DenseMap<mlir::StringAttr, LatticeValue>>;
202 // Expression to interval map for convenience.
203 using ExpressionIntervals = mlir::DenseMap<llvm::SMTExprRef, Interval>;
204 // Tracks all constraints and assignments in insertion order
205 using ConstraintSet = llvm::SetVector<ExpressionValue>;
206
207 using AbstractDenseLattice::AbstractDenseLattice;
208
209 mlir::ChangeResult join(const AbstractDenseLattice &other) override;
210
211 mlir::ChangeResult meet(const AbstractDenseLattice &rhs) override {
212 llvm::report_fatal_error("IntervalDataFlowAnalysis::meet : unsupported");
213 return mlir::ChangeResult::NoChange;
214 }
215
216 void print(mlir::raw_ostream &os) const override;
217
218 mlir::FailureOr<LatticeValue> getValue(mlir::Value v) const;
219 mlir::FailureOr<LatticeValue> getValue(mlir::Value v, mlir::StringAttr f) const;
220
221 mlir::ChangeResult setValue(mlir::Value v, ExpressionValue e);
222 mlir::ChangeResult setValue(mlir::Value v, mlir::StringAttr f, ExpressionValue e);
223
224 mlir::ChangeResult addSolverConstraint(ExpressionValue e);
225
226 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const IntervalAnalysisLattice &l) {
227 l.print(os);
228 return os;
229 }
230
231 const ConstraintSet &getConstraints() const { return constraints; }
232
233 mlir::FailureOr<Interval> findInterval(llvm::SMTExprRef expr) const;
234 mlir::ChangeResult setInterval(llvm::SMTExprRef expr, Interval i);
235
236 size_t size() const { return valMap.size(); }
237
238 const ValueMap &getMap() const { return valMap; }
239
240 ValueMap::iterator begin() { return valMap.begin(); }
241 ValueMap::iterator end() { return valMap.end(); }
242 ValueMap::const_iterator begin() const { return valMap.begin(); }
243 ValueMap::const_iterator end() const { return valMap.end(); }
244
245private:
246 ValueMap valMap;
247 FieldMap fieldMap;
248 ConstraintSet constraints;
249 ExpressionIntervals intervals;
250};
251
252/* IntervalDataFlowAnalysis */
253
255 : public dataflow::DenseForwardDataFlowAnalysis<IntervalAnalysisLattice> {
257 using Lattice = IntervalAnalysisLattice;
258 using LatticeValue = IntervalAnalysisLattice::LatticeValue;
259
260 // Map fields to their symbols
261 using SymbolMap = mlir::DenseMap<ConstrainRef, llvm::SMTExprRef>;
262
263public:
265 mlir::DataFlowSolver &dataflowSolver, llvm::SMTSolverRef smt, const Field &f,
266 bool propInputConstraints
267 )
268 : Base::DenseForwardDataFlowAnalysis(dataflowSolver), _dataflowSolver(dataflowSolver),
269 smtSolver(smt), field(f), propagateInputConstraints(propInputConstraints) {}
270
272 mlir::CallOpInterface call, dataflow::CallControlFlowAction action, const Lattice &before,
273 Lattice *after
274 ) override;
275
276 void visitOperation(mlir::Operation *op, const Lattice &before, Lattice *after) override;
277
282 llvm::SMTExprRef getOrCreateSymbol(const ConstrainRef &r);
283
284private:
285 mlir::DataFlowSolver &_dataflowSolver;
286 llvm::SMTSolverRef smtSolver;
287 SymbolMap refSymbols;
288 std::reference_wrapper<const Field> field;
289 bool propagateInputConstraints;
290 mlir::SymbolTableCollection tables;
291
292 void setToEntryState(Lattice *lattice) override {
293 // initial state should be empty, so do nothing here
294 }
295
296 llvm::SMTExprRef createFeltSymbol(const ConstrainRef &r) const;
297
298 llvm::SMTExprRef createFeltSymbol(mlir::Value val) const;
299
300 llvm::SMTExprRef createFeltSymbol(const char *name) const;
301
302 bool isConstOp(mlir::Operation *op) const {
303 return mlir::isa<
304 felt::FeltConstantOp, mlir::arith::ConstantIndexOp, mlir::arith::ConstantIntOp>(op);
305 }
306
307 llvm::APSInt getConst(mlir::Operation *op) const;
308
309 llvm::SMTExprRef createConstBitvectorExpr(llvm::APSInt v) const {
310 return smtSolver->mkBitvector(v, field.get().bitWidth());
311 }
312
313 llvm::SMTExprRef createConstBoolExpr(bool v) const {
314 return smtSolver->mkBitvector(mlir::APSInt((int)v), field.get().bitWidth());
315 }
316
317 bool isArithmeticOp(mlir::Operation *op) const {
318 return mlir::isa<
319 felt::AddFeltOp, felt::SubFeltOp, felt::MulFeltOp, felt::DivFeltOp, felt::ModFeltOp,
320 felt::NegFeltOp, felt::InvFeltOp, felt::AndFeltOp, felt::OrFeltOp, felt::XorFeltOp,
321 felt::NotFeltOp, felt::ShlFeltOp, felt::ShrFeltOp, boolean::CmpOp, boolean::AndBoolOp,
322 boolean::OrBoolOp, boolean::XorBoolOp, boolean::NotBoolOp>(op);
323 }
324
325 ExpressionValue
326 performBinaryArithmetic(mlir::Operation *op, const LatticeValue &a, const LatticeValue &b);
327
328 ExpressionValue performUnaryArithmetic(mlir::Operation *op, const LatticeValue &a);
329
336 mlir::ChangeResult
337 applyInterval(mlir::Operation *originalOp, Lattice *after, mlir::Value val, Interval newInterval);
338
340 mlir::FailureOr<std::pair<llvm::DenseSet<mlir::Value>, Interval>> getGeneralizedDecompInterval(
341 const ConstrainRefLattice *constrainRefLattice, mlir::Value lhs, mlir::Value rhs
342 );
343
344 bool isBoolOp(mlir::Operation *op) const {
345 return mlir::isa<boolean::AndBoolOp, boolean::OrBoolOp, boolean::XorBoolOp, boolean::NotBoolOp>(
346 op
347 );
348 }
349
350 bool isConversionOp(mlir::Operation *op) const {
351 return mlir::isa<cast::IntToFeltOp, cast::FeltToIndexOp>(op);
352 }
353
354 bool isApplyMapOp(mlir::Operation *op) const { return mlir::isa<polymorphic::ApplyMapOp>(op); }
355
356 bool isAssertOp(mlir::Operation *op) const { return mlir::isa<boolean::AssertOp>(op); }
357
358 bool isReadOp(mlir::Operation *op) const {
359 return mlir::isa<component::FieldReadOp, polymorphic::ConstReadOp, array::ReadArrayOp>(op);
360 }
361
362 bool isWriteOp(mlir::Operation *op) const {
363 return mlir::isa<component::FieldWriteOp, array::WriteArrayOp, array::InsertArrayOp>(op);
364 }
365
366 bool isArrayLengthOp(mlir::Operation *op) const { return mlir::isa<array::ArrayLengthOp>(op); }
367
368 bool isEmitOp(mlir::Operation *op) const {
369 return mlir::isa<constrain::EmitEqualityOp, constrain::EmitContainmentOp>(op);
370 }
371
372 bool isCreateOp(mlir::Operation *op) const {
373 return mlir::isa<component::CreateStructOp, array::CreateArrayOp>(op);
374 }
375
376 bool isExtractArrayOp(mlir::Operation *op) const { return mlir::isa<array::ExtractArrayOp>(op); }
377
378 bool isDefinitionOp(mlir::Operation *op) const {
379 return mlir::isa<
380 component::StructDefOp, function::FuncDefOp, component::FieldDefOp, global::GlobalDefOp,
381 mlir::ModuleOp>(op);
382 }
383
384 bool isCallOp(mlir::Operation *op) const { return mlir::isa<function::CallOp>(op); }
385
386 bool isReturnOp(mlir::Operation *op) const { return mlir::isa<function::ReturnOp>(op); }
387};
388
389/* StructIntervals */
390
394 llvm::SMTSolverRef smtSolver;
395 std::reference_wrapper<const Field> field;
397
398 llvm::SMTExprRef getSymbol(const ConstrainRef &r) { return intervalDFA->getOrCreateSymbol(r); }
399 const Field &getField() const { return field.get(); }
401};
402
403class StructIntervals {
404public:
414 static mlir::FailureOr<StructIntervals> compute(
415 mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver,
417 ) {
418 StructIntervals si(mod, s);
419 if (si.computeIntervals(solver, ctx).failed()) {
420 return mlir::failure();
421 }
422 return si;
423 }
424
425 mlir::LogicalResult computeIntervals(mlir::DataFlowSolver &solver, IntervalAnalysisContext &ctx);
426
427 void print(mlir::raw_ostream &os, bool withConstraints = false, bool printCompute = false) const;
428
429 const llvm::MapVector<ConstrainRef, Interval> &getConstrainIntervals() const {
430 return constrainFieldRanges;
431 }
432
433 const llvm::SetVector<ExpressionValue> getConstrainSolverConstraints() const {
434 return constrainSolverConstraints;
435 }
436
437 const llvm::MapVector<ConstrainRef, Interval> &getComputeIntervals() const {
438 return computeFieldRanges;
439 }
440
441 const llvm::SetVector<ExpressionValue> getComputeSolverConstraints() const {
442 return computeSolverConstraints;
443 }
444
445 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const StructIntervals &si) {
446 si.print(os);
447 return os;
448 }
449
450private:
451 mlir::ModuleOp mod;
452 component::StructDefOp structDef;
453 llvm::SMTSolverRef smtSolver;
454 // llvm::MapVector keeps insertion order for consistent iteration
455 llvm::MapVector<ConstrainRef, Interval> constrainFieldRanges, computeFieldRanges;
456 // llvm::SetVector for the same reasons as above
457 llvm::SetVector<ExpressionValue> constrainSolverConstraints, computeSolverConstraints;
458
459 StructIntervals(mlir::ModuleOp m, component::StructDefOp s) : mod(m), structDef(s) {}
460};
461
462/* StructIntervalAnalysis */
463
465
466class StructIntervalAnalysis : public StructAnalysis<StructIntervals, IntervalAnalysisContext> {
467public:
469 virtual ~StructIntervalAnalysis() = default;
470
471 mlir::LogicalResult runAnalysis(
472 mlir::DataFlowSolver &solver, mlir::AnalysisManager &_, IntervalAnalysisContext &ctx
473 ) override {
474 auto computeRes = StructIntervals::compute(getModule(), getStruct(), solver, ctx);
475 if (mlir::failed(computeRes)) {
476 return mlir::failure();
477 }
478 setResult(std::move(*computeRes));
479 return mlir::success();
480 }
481};
482
483/* ModuleIntervalAnalysis */
484
486 : public ModuleAnalysis<StructIntervals, IntervalAnalysisContext, StructIntervalAnalysis> {
487
488public:
489 ModuleIntervalAnalysis(mlir::Operation *op)
490 : ModuleAnalysis(op), smtSolver(llvm::CreateZ3Solver()), field(std::nullopt) {}
491 virtual ~ModuleIntervalAnalysis() = default;
492
493 void setField(const Field &f) { field = f; }
494 void setPropagateInputConstraints(bool prop) { propagateInputConstraints = prop; }
495
496protected:
497 void initializeSolver() override {
498 ensure(field.has_value(), "field not set, could not generate analysis context");
499 (void)solver.load<ConstrainRefAnalysis>();
500 auto smtSolverRef = smtSolver;
501 bool prop = propagateInputConstraints;
502 intervalDFA = solver.load<IntervalDataFlowAnalysis, llvm::SMTSolverRef, const Field &, bool>(
503 std::move(smtSolverRef), field.value(), std::move(prop)
504 );
505 }
506
508 ensure(field.has_value(), "field not set, could not generate analysis context");
509 return {
510 .intervalDFA = intervalDFA,
511 .smtSolver = smtSolver,
512 .field = field.value(),
513 .propagateInputConstraints = propagateInputConstraints,
514 };
515 }
516
517private:
518 llvm::SMTSolverRef smtSolver;
519 IntervalDataFlowAnalysis *intervalDFA;
520 std::optional<std::reference_wrapper<const Field>> field;
521 bool propagateInputConstraints;
522};
523
524} // namespace llzk
525
526namespace llvm {
527
528template <> struct DenseMapInfo<llzk::ExpressionValue> {
529
530 static SMTExprRef getEmptyExpr() {
531 static auto emptyPtr = reinterpret_cast<SMTExprRef>(1);
532 return emptyPtr;
533 }
534 static SMTExprRef getTombstoneExpr() {
535 static auto tombstonePtr = reinterpret_cast<SMTExprRef>(2);
536 return tombstonePtr;
537 }
538
545 static unsigned getHashValue(const llzk::ExpressionValue &e) {
546 return llzk::ExpressionValue::Hash {}(e);
547 }
548 static bool isEqual(const llzk::ExpressionValue &lhs, const llzk::ExpressionValue &rhs) {
549 if (lhs.getExpr() == getEmptyExpr() || lhs.getExpr() == getTombstoneExpr() ||
550 rhs.getExpr() == getEmptyExpr() || rhs.getExpr() == getTombstoneExpr()) {
551 return lhs.getExpr() == rhs.getExpr();
552 }
553 return lhs == rhs;
554 }
555};
556
557} // namespace llvm
This file defines helpers for manipulating APInts/APSInts for large numbers and operations over those...
Convenience classes for a frequent pattern of dataflow analysis used in LLZK, where an analysis is ru...
This file implements (LLZK-tailored) dense data-flow analysis using the data-flow analysis framework.
MlirStringRef name
The dataflow analysis that computes the set of references that LLZK operations use and produce.
Defines a reference to a llzk object within a constrain function call.
Tracks a solver expression and an interval range for that expression.
friend ExpressionValue neg(llvm::SMTSolverRef solver, const ExpressionValue &val)
friend ExpressionValue notOp(llvm::SMTSolverRef solver, const ExpressionValue &val)
const Interval & getInterval() const
friend ExpressionValue cmp(llvm::SMTSolverRef solver, boolean::CmpOp op, const ExpressionValue &lhs, const ExpressionValue &rhs)
ExpressionValue(const Field &f, llvm::SMTExprRef exprRef)
friend ExpressionValue sub(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue mul(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue fallbackUnaryOp(llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &val)
friend ExpressionValue boolOr(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue div(llvm::SMTSolverRef solver, felt::DivFeltOp op, const ExpressionValue &lhs, const ExpressionValue &rhs)
ExpressionValue withInterval(const Interval &newInterval) const
Return the current expression with a new interval.
void print(mlir::raw_ostream &os) const
bool operator==(const ExpressionValue &rhs) const
friend ExpressionValue add(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue shiftRight(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
llvm::SMTExprRef getExpr() const
friend ExpressionValue fallbackBinaryOp(llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &lhs, const ExpressionValue &rhs)
Computes a solver expression based on the operation, but computes a fallback interval (which is just ...
friend ExpressionValue bitAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
ExpressionValue & join(const ExpressionValue &rhs)
Fold two expressions together when overapproximating array elements.
ExpressionValue(llvm::SMTExprRef exprRef, Interval interval)
friend ExpressionValue boolXor(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
ExpressionValue(const Field &f, llvm::SMTExprRef exprRef, llvm::APSInt singleVal)
friend ExpressionValue join(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
Compute the union of the lhs and rhs intervals, and create a solver expression that constrains both s...
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const ExpressionValue &e)
friend ExpressionValue boolAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
const Field & getField() const
friend ExpressionValue mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue shiftLeft(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue intersection(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
Compute the intersection of the lhs and rhs intervals, and create a solver expression that constrains...
friend ExpressionValue boolNot(llvm::SMTSolverRef solver, const ExpressionValue &val)
Information about the prime finite field used for the interval analysis.
Definition Field.h:22
static const Field & getField(const char *fieldName)
Get a Field from a given field name string.
Definition Field.cpp:26
Maps mlir::Values to LatticeValues.
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const IntervalAnalysisLattice &l)
const ValueMap & getMap() const
mlir::DenseMap< mlir::Value, mlir::DenseMap< mlir::StringAttr, LatticeValue > > FieldMap
llvm::SetVector< ExpressionValue > ConstraintSet
mlir::ChangeResult setInterval(llvm::SMTExprRef expr, Interval i)
IntervalAnalysisLatticeValue LatticeValue
mlir::ChangeResult setValue(mlir::Value v, mlir::StringAttr f, ExpressionValue e)
mlir::DenseMap< mlir::Value, LatticeValue > ValueMap
mlir::ChangeResult addSolverConstraint(ExpressionValue e)
mlir::ChangeResult setValue(mlir::Value v, ExpressionValue e)
const ConstraintSet & getConstraints() const
void print(mlir::raw_ostream &os) const override
ValueMap::const_iterator end() const
mlir::DenseMap< llvm::SMTExprRef, Interval > ExpressionIntervals
mlir::ChangeResult join(const AbstractDenseLattice &other) override
mlir::FailureOr< LatticeValue > getValue(mlir::Value v) const
ValueMap::const_iterator begin() const
mlir::FailureOr< Interval > findInterval(llvm::SMTExprRef expr) const
mlir::ChangeResult meet(const AbstractDenseLattice &rhs) override
mlir::FailureOr< LatticeValue > getValue(mlir::Value v, mlir::StringAttr f) const
void visitOperation(mlir::Operation *op, const Lattice &before, Lattice *after) override
Visit an operation with the dense lattice before its execution.
void visitCallControlFlowTransfer(mlir::CallOpInterface call, dataflow::CallControlFlowAction action, const Lattice &before, Lattice *after) override
The interval analysis is intraprocedural only for now, so this control flow transfer function passes ...
llvm::SMTExprRef getOrCreateSymbol(const ConstrainRef &r)
Either return the existing SMT expression that corresponds to the ConstrainRef, or create one.
IntervalDataFlowAnalysis(mlir::DataFlowSolver &dataflowSolver, llvm::SMTSolverRef smt, const Field &f, bool propInputConstraints)
Intervals over a finite field.
Definition Intervals.h:214
ModuleIntervalAnalysis(mlir::Operation *op)
virtual ~ModuleIntervalAnalysis()=default
IntervalAnalysisContext getContext() override
Create and return a valid Context object.
void setPropagateInputConstraints(bool prop)
void initializeSolver() override
Initialize the shared dataflow solver with any common analyses required by the contained struct analy...
void setField(const Field &f)
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
mlir::LogicalResult runAnalysis(mlir::DataFlowSolver &solver, mlir::AnalysisManager &_, IntervalAnalysisContext &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 ~StructIntervalAnalysis()=default
const llvm::SetVector< ExpressionValue > getConstrainSolverConstraints() const
const llvm::SetVector< ExpressionValue > getComputeSolverConstraints() const
mlir::LogicalResult computeIntervals(mlir::DataFlowSolver &solver, IntervalAnalysisContext &ctx)
void print(mlir::raw_ostream &os, bool withConstraints=false, bool printCompute=false) const
const llvm::MapVector< ConstrainRef, Interval > & getConstrainIntervals() const
static mlir::FailureOr< StructIntervals > compute(mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver, IntervalAnalysisContext &ctx)
Compute the struct intervals.
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const StructIntervals &si)
const llvm::MapVector< ConstrainRef, Interval > & getComputeIntervals() const
LLZK: This class has been ported so that it can inherit from our port of the AbstractDenseForwardData...
mlir::dataflow::AbstractDenseLattice AbstractDenseLattice
mlir::dataflow::CallControlFlowAction CallControlFlowAction
void ensure(bool condition, llvm::Twine errMsg)
Definition ErrorHelper.h:35
ExpressionValue mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
static unsigned getHashValue(const llzk::ExpressionValue &e)
static bool isEqual(const llzk::ExpressionValue &lhs, const llzk::ExpressionValue &rhs)
static llzk::ExpressionValue getTombstoneKey()
static llzk::ExpressionValue getEmptyKey()
unsigned operator()(const ExpressionValue &e) const
Parameters and shared objects to pass to child analyses.
std::reference_wrapper< const Field > field
const Field & getField() const
IntervalDataFlowAnalysis * intervalDFA
llvm::SMTExprRef getSymbol(const ConstrainRef &r)