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"
26#include "llzk/Util/Compare.h"
27
28#include <mlir/IR/BuiltinOps.h>
29#include <mlir/Pass/AnalysisManager.h>
30#include <mlir/Support/LLVM.h>
31
32#include <llvm/ADT/DynamicAPInt.h>
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, const llvm::DynamicAPInt &singleVal)
54 : i(Interval::Degenerate(f, singleVal)), expr(exprRef) {}
55
56 ExpressionValue(llvm::SMTExprRef exprRef, const Interval &interval)
57 : i(interval), expr(exprRef) {}
58
59 llvm::SMTExprRef getExpr() const { return expr; }
60
61 const Interval &getInterval() const { return i; }
62
63 const Field &getField() const { return i.getField(); }
64
68 ExpressionValue withInterval(const Interval &newInterval) const {
69 return ExpressionValue(expr, newInterval);
70 }
71
73 ExpressionValue withExpression(const llvm::SMTExprRef &newExpr) const {
74 return ExpressionValue(newExpr, i);
75 }
76
77 /* Required to be a ScalarLatticeValue. */
81 return *this;
82 }
83
84 bool operator==(const ExpressionValue &rhs) const;
85
86 bool isBoolSort(llvm::SMTSolverRef solver) const {
87 return solver->getBoolSort() == solver->getSort(expr);
88 }
89
96 friend ExpressionValue
97 intersection(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
98
105 friend ExpressionValue
106 join(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
107
108 // arithmetic ops
109
110 friend ExpressionValue
111 add(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
112
113 friend ExpressionValue
114 sub(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
115
116 friend ExpressionValue
117 mul(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
118
119 friend ExpressionValue
120 div(llvm::SMTSolverRef solver, felt::DivFeltOp op, const ExpressionValue &lhs,
121 const ExpressionValue &rhs);
122
123 friend ExpressionValue
124 mod(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
125
126 friend ExpressionValue
127 bitAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
128
129 friend ExpressionValue
130 shiftLeft(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
131
132 friend ExpressionValue
133 shiftRight(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
134
135 friend ExpressionValue
136 cmp(llvm::SMTSolverRef solver, boolean::CmpOp op, const ExpressionValue &lhs,
137 const ExpressionValue &rhs);
138
139 friend ExpressionValue
140 boolAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
141
142 friend ExpressionValue
143 boolOr(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
144
145 friend ExpressionValue
146 boolXor(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs);
147
157 llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &lhs,
158 const ExpressionValue &rhs
159 );
160
161 friend ExpressionValue neg(llvm::SMTSolverRef solver, const ExpressionValue &val);
162
163 friend ExpressionValue notOp(llvm::SMTSolverRef solver, const ExpressionValue &val);
164
165 friend ExpressionValue boolNot(llvm::SMTSolverRef solver, const ExpressionValue &val);
166
167 friend ExpressionValue
168 fallbackUnaryOp(llvm::SMTSolverRef solver, mlir::Operation *op, const ExpressionValue &val);
169
170 /* Utility */
171
172 void print(mlir::raw_ostream &os) const;
173
174 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const ExpressionValue &e) {
175 e.print(os);
176 return os;
177 }
178
179 struct Hash {
180 unsigned operator()(const ExpressionValue &e) const {
181 return Interval::Hash {}(e.i) ^ llvm::hash_value(e.expr);
182 }
183 };
184
185private:
186 Interval i;
187 llvm::SMTExprRef expr;
188};
189
190/* IntervalAnalysisLatticeValue */
191
193 : public dataflow::AbstractLatticeValue<IntervalAnalysisLatticeValue, ExpressionValue> {
194public:
195 using AbstractLatticeValue::AbstractLatticeValue;
196};
197
198/* IntervalAnalysisLattice */
199
201
205public:
207 // Map mlir::Values to LatticeValues
208 using ValueMap = mlir::DenseMap<mlir::Value, LatticeValue>;
209 // Map field references to LatticeValues. Used for field reads and writes.
210 // Structure is component value -> field attribute -> latticeValue
211 using FieldMap = mlir::DenseMap<mlir::Value, mlir::DenseMap<mlir::StringAttr, LatticeValue>>;
212 // Expression to interval map for convenience.
213 using ExpressionIntervals = mlir::DenseMap<llvm::SMTExprRef, Interval>;
214 // Tracks all constraints and assignments in insertion order
215 using ConstraintSet = llvm::SetVector<ExpressionValue>;
216
217 using AbstractDenseLattice::AbstractDenseLattice;
218
219 mlir::ChangeResult join(const AbstractDenseLattice &other) override;
220
221 mlir::ChangeResult meet(const AbstractDenseLattice & /*rhs*/) override {
222 llvm::report_fatal_error("IntervalDataFlowAnalysis::meet : unsupported");
223 return mlir::ChangeResult::NoChange;
224 }
225
226 void print(mlir::raw_ostream &os) const override;
227
228 mlir::FailureOr<LatticeValue> getValue(mlir::Value v) const;
229 mlir::FailureOr<LatticeValue> getValue(mlir::Value v, mlir::StringAttr f) const;
230
231 mlir::ChangeResult setValue(mlir::Value v, const LatticeValue &val);
232 mlir::ChangeResult setValue(mlir::Value v, ExpressionValue e);
233 mlir::ChangeResult setValue(mlir::Value v, mlir::StringAttr f, ExpressionValue e);
234
235 mlir::ChangeResult addSolverConstraint(ExpressionValue e);
236
237 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const IntervalAnalysisLattice &l) {
238 l.print(os);
239 return os;
240 }
241
242 const ConstraintSet &getConstraints() const { return constraints; }
243
244 mlir::FailureOr<Interval> findInterval(llvm::SMTExprRef expr) const;
245 mlir::ChangeResult setInterval(llvm::SMTExprRef expr, const Interval &i);
246
247 size_t size() const { return valMap.size(); }
248
249 const ValueMap &getMap() const { return valMap; }
250
251 ValueMap::iterator begin() { return valMap.begin(); }
252 ValueMap::iterator end() { return valMap.end(); }
253 ValueMap::const_iterator begin() const { return valMap.begin(); }
254 ValueMap::const_iterator end() const { return valMap.end(); }
255
256private:
257 ValueMap valMap;
258 FieldMap fieldMap;
259 ConstraintSet constraints;
260 ExpressionIntervals intervals;
261};
262
263/* IntervalDataFlowAnalysis */
264
266 : public dataflow::DenseForwardDataFlowAnalysis<IntervalAnalysisLattice> {
268 using Lattice = IntervalAnalysisLattice;
269 using LatticeValue = IntervalAnalysisLattice::LatticeValue;
270
271 // Map fields to their symbols
272 using SymbolMap = mlir::DenseMap<SourceRef, llvm::SMTExprRef>;
273
274public:
276 mlir::DataFlowSolver &dataflowSolver, llvm::SMTSolverRef smt, const Field &f,
277 bool propInputConstraints
278 )
279 : Base::DenseForwardDataFlowAnalysis(dataflowSolver), _dataflowSolver(dataflowSolver),
280 smtSolver(smt), field(f), propagateInputConstraints(propInputConstraints) {}
281
283 mlir::CallOpInterface call, dataflow::CallControlFlowAction action, const Lattice &before,
284 Lattice *after
285 ) override;
286
287 mlir::LogicalResult
288 visitOperation(mlir::Operation *op, const Lattice &before, Lattice *after) override;
289
294 llvm::SMTExprRef getOrCreateSymbol(const SourceRef &r);
295
296private:
297 mlir::DataFlowSolver &_dataflowSolver;
298 llvm::SMTSolverRef smtSolver;
299 SymbolMap refSymbols;
300 std::reference_wrapper<const Field> field;
301 bool propagateInputConstraints;
302 mlir::SymbolTableCollection tables;
303
304 void setToEntryState(Lattice *lattice) override {
305 // initial state should be empty, so do nothing here
306 }
307
308 llvm::SMTExprRef createFeltSymbol(const SourceRef &r) const;
309
310 llvm::SMTExprRef createFeltSymbol(mlir::Value val) const;
311
312 llvm::SMTExprRef createFeltSymbol(const char *name) const;
313
314 bool isConstOp(mlir::Operation *op) const {
315 return llvm::isa<
316 felt::FeltConstantOp, mlir::arith::ConstantIndexOp, mlir::arith::ConstantIntOp>(op);
317 }
318
319 llvm::DynamicAPInt getConst(mlir::Operation *op) const;
320
321 inline llvm::SMTExprRef createConstBitvectorExpr(const llvm::DynamicAPInt &v) const {
322 return createConstBitvectorExpr(toAPSInt(v));
323 }
324
325 inline llvm::SMTExprRef createConstBitvectorExpr(const llvm::APSInt &v) const {
326 return smtSolver->mkBitvector(v, field.get().bitWidth());
327 }
328
329 llvm::SMTExprRef createConstBoolExpr(bool v) const {
330 return smtSolver->mkBitvector(mlir::APSInt((int)v), field.get().bitWidth());
331 }
332
333 bool isArithmeticOp(mlir::Operation *op) const {
334 return llvm::isa<
335 felt::AddFeltOp, felt::SubFeltOp, felt::MulFeltOp, felt::DivFeltOp, felt::ModFeltOp,
336 felt::NegFeltOp, felt::InvFeltOp, felt::AndFeltOp, felt::OrFeltOp, felt::XorFeltOp,
337 felt::NotFeltOp, felt::ShlFeltOp, felt::ShrFeltOp, boolean::CmpOp, boolean::AndBoolOp,
338 boolean::OrBoolOp, boolean::XorBoolOp, boolean::NotBoolOp>(op);
339 }
340
341 ExpressionValue
342 performBinaryArithmetic(mlir::Operation *op, const LatticeValue &a, const LatticeValue &b);
343
344 ExpressionValue performUnaryArithmetic(mlir::Operation *op, const LatticeValue &a);
345
352 mlir::ChangeResult applyInterval(
353 mlir::Operation *originalOp, Lattice *originalLattice, Lattice *after, mlir::Value val,
354 Interval newInterval
355 );
356
358 mlir::FailureOr<std::pair<llvm::DenseSet<mlir::Value>, Interval>>
359 getGeneralizedDecompInterval(mlir::Operation *baseOp, mlir::Value lhs, mlir::Value rhs);
360
361 bool isBoolOp(mlir::Operation *op) const {
362 return llvm::isa<boolean::AndBoolOp, boolean::OrBoolOp, boolean::XorBoolOp, boolean::NotBoolOp>(
363 op
364 );
365 }
366
367 bool isConversionOp(mlir::Operation *op) const {
368 return llvm::isa<cast::IntToFeltOp, cast::FeltToIndexOp>(op);
369 }
370
371 bool isApplyMapOp(mlir::Operation *op) const { return llvm::isa<polymorphic::ApplyMapOp>(op); }
372
373 bool isAssertOp(mlir::Operation *op) const { return llvm::isa<boolean::AssertOp>(op); }
374
375 bool isReadOp(mlir::Operation *op) const {
376 return llvm::isa<component::FieldReadOp, polymorphic::ConstReadOp, array::ReadArrayOp>(op);
377 }
378
379 bool isWriteOp(mlir::Operation *op) const {
380 return llvm::isa<component::FieldWriteOp, array::WriteArrayOp, array::InsertArrayOp>(op);
381 }
382
383 bool isArrayLengthOp(mlir::Operation *op) const { return llvm::isa<array::ArrayLengthOp>(op); }
384
385 bool isEmitOp(mlir::Operation *op) const {
386 return llvm::isa<constrain::EmitEqualityOp, constrain::EmitContainmentOp>(op);
387 }
388
389 bool isCreateOp(mlir::Operation *op) const {
390 return llvm::isa<component::CreateStructOp, array::CreateArrayOp>(op);
391 }
392
393 bool isExtractArrayOp(mlir::Operation *op) const { return llvm::isa<array::ExtractArrayOp>(op); }
394
395 bool isDefinitionOp(mlir::Operation *op) const {
396 return llvm::isa<
397 component::StructDefOp, function::FuncDefOp, component::FieldDefOp, global::GlobalDefOp,
398 mlir::ModuleOp>(op);
399 }
400
401 bool isCallOp(mlir::Operation *op) const { return llvm::isa<function::CallOp>(op); }
402
403 bool isReturnOp(mlir::Operation *op) const { return llvm::isa<function::ReturnOp>(op); }
404
407 const SourceRefLattice *getSourceRefLattice(mlir::Operation *baseOp, mlir::Value val);
408};
409
410/* StructIntervals */
411
415 llvm::SMTSolverRef smtSolver;
416 std::optional<std::reference_wrapper<const Field>> field;
418
419 llvm::SMTExprRef getSymbol(const SourceRef &r) const { return intervalDFA->getOrCreateSymbol(r); }
420 bool hasField() const { return field.has_value(); }
421 const Field &getField() const {
422 ensure(field.has_value(), "field not set within context");
423 return field->get();
424 }
426
427 friend bool
429};
430
431} // namespace llzk
432
433template <> struct std::hash<llzk::IntervalAnalysisContext> {
435 return llvm::hash_combine(
436 std::hash<const llzk::IntervalDataFlowAnalysis *> {}(c.intervalDFA),
437 std::hash<const llvm::SMTSolver *> {}(c.smtSolver.get()),
438 std::hash<const llzk::Field *> {}(&c.getField()),
439 std::hash<bool> {}(c.propagateInputConstraints)
440 );
441 }
442};
443
444namespace llzk {
445
446class StructIntervals {
447public:
457 static mlir::FailureOr<StructIntervals> compute(
458 mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver,
459 const IntervalAnalysisContext &ctx
460 ) {
461 StructIntervals si(mod, s);
462 if (si.computeIntervals(solver, ctx).failed()) {
463 return mlir::failure();
464 }
465 return si;
466 }
467
468 mlir::LogicalResult
469 computeIntervals(mlir::DataFlowSolver &solver, const IntervalAnalysisContext &ctx);
470
471 void print(mlir::raw_ostream &os, bool withConstraints = false, bool printCompute = false) const;
472
473 const llvm::MapVector<SourceRef, Interval> &getConstrainIntervals() const {
474 return constrainFieldRanges;
475 }
476
477 const llvm::SetVector<ExpressionValue> getConstrainSolverConstraints() const {
478 return constrainSolverConstraints;
479 }
480
481 const llvm::MapVector<SourceRef, Interval> &getComputeIntervals() const {
482 return computeFieldRanges;
483 }
484
485 const llvm::SetVector<ExpressionValue> getComputeSolverConstraints() const {
486 return computeSolverConstraints;
487 }
488
489 friend mlir::raw_ostream &operator<<(mlir::raw_ostream &os, const StructIntervals &si) {
490 si.print(os);
491 return os;
492 }
493
494private:
495 mlir::ModuleOp mod;
496 component::StructDefOp structDef;
497 llvm::SMTSolverRef smtSolver;
498 // llvm::MapVector keeps insertion order for consistent iteration
499 llvm::MapVector<SourceRef, Interval> constrainFieldRanges, computeFieldRanges;
500 // llvm::SetVector for the same reasons as above
501 llvm::SetVector<ExpressionValue> constrainSolverConstraints, computeSolverConstraints;
502
503 StructIntervals(mlir::ModuleOp m, component::StructDefOp s) : mod(m), structDef(s) {}
504};
505
506/* StructIntervalAnalysis */
507
509
510class StructIntervalAnalysis : public StructAnalysis<StructIntervals, IntervalAnalysisContext> {
511public:
513 virtual ~StructIntervalAnalysis() = default;
514
515 mlir::LogicalResult runAnalysis(
516 mlir::DataFlowSolver &solver, mlir::AnalysisManager &, const IntervalAnalysisContext &ctx
517 ) override {
518 auto computeRes = StructIntervals::compute(getModule(), getStruct(), solver, ctx);
519 if (mlir::failed(computeRes)) {
520 return mlir::failure();
521 }
522 setResult(ctx, std::move(*computeRes));
523 return mlir::success();
524 }
525};
526
527/* ModuleIntervalAnalysis */
528
530 : public ModuleAnalysis<StructIntervals, IntervalAnalysisContext, StructIntervalAnalysis> {
531
532public:
533 ModuleIntervalAnalysis(mlir::Operation *op) : ModuleAnalysis(op), ctx {} {
534 ctx.smtSolver = llvm::CreateZ3Solver();
535 }
536 virtual ~ModuleIntervalAnalysis() = default;
537
538 void setField(const Field &f) { ctx.field = f; }
539 void setPropagateInputConstraints(bool prop) { ctx.propagateInputConstraints = prop; }
540
541protected:
542 void initializeSolver() override {
543 ensure(ctx.hasField(), "field not set, could not generate analysis context");
544 (void)solver.load<SourceRefAnalysis>();
545 auto smtSolverRef = ctx.smtSolver;
546 bool prop = ctx.propagateInputConstraints;
547 ctx.intervalDFA =
548 solver.load<IntervalDataFlowAnalysis, llvm::SMTSolverRef, const Field &, bool>(
549 std::move(smtSolverRef), ctx.getField(), std::move(prop)
550 );
551 }
552
553 const IntervalAnalysisContext &getContext() const override {
554 ensure(ctx.field.has_value(), "field not set, could not generate analysis context");
555 return ctx;
556 }
557
558private:
560};
561
562} // namespace llzk
563
564namespace llvm {
565
566template <> struct DenseMapInfo<llzk::ExpressionValue> {
567
568 static SMTExprRef getEmptyExpr() {
569 static auto emptyPtr = reinterpret_cast<SMTExprRef>(1);
570 return emptyPtr;
571 }
572 static SMTExprRef getTombstoneExpr() {
573 static auto tombstonePtr = reinterpret_cast<SMTExprRef>(2);
574 return tombstonePtr;
575 }
576
583 static unsigned getHashValue(const llzk::ExpressionValue &e) {
584 return llzk::ExpressionValue::Hash {}(e);
585 }
586 static bool isEqual(const llzk::ExpressionValue &lhs, const llzk::ExpressionValue &rhs) {
587 if (lhs.getExpr() == getEmptyExpr() || lhs.getExpr() == getTombstoneExpr() ||
588 rhs.getExpr() == getEmptyExpr() || rhs.getExpr() == getTombstoneExpr()) {
589 return lhs.getExpr() == rhs.getExpr();
590 }
591 return lhs == rhs;
592 }
593};
594
595} // namespace llvm
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
Definition Poly.cpp:48
Tracks a solver expression and an interval range for that expression.
ExpressionValue(llvm::SMTExprRef exprRef, const Interval &interval)
ExpressionValue withExpression(const llvm::SMTExprRef &newExpr) const
Return the current expression with a new SMT 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)
bool isBoolSort(llvm::SMTSolverRef solver) const
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 ...
ExpressionValue(const Field &f, llvm::SMTExprRef exprRef, const llvm::DynamicAPInt &singleVal)
friend ExpressionValue bitAnd(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
friend ExpressionValue boolXor(llvm::SMTSolverRef solver, const ExpressionValue &lhs, const ExpressionValue &rhs)
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)
ExpressionValue & join(const ExpressionValue &)
Fold two expressions together when overapproximating array elements.
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:25
static const Field & getField(const char *fieldName)
Get a Field from a given field name string.
Definition Field.cpp:31
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
IntervalAnalysisLatticeValue LatticeValue
mlir::ChangeResult meet(const AbstractDenseLattice &) override
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::ChangeResult setValue(mlir::Value v, const LatticeValue &val)
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 setInterval(llvm::SMTExprRef expr, const Interval &i)
mlir::FailureOr< LatticeValue > getValue(mlir::Value v, mlir::StringAttr f) const
mlir::LogicalResult 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 SourceRef &r)
Either return the existing SMT expression that corresponds to the SourceRef, or create one.
IntervalDataFlowAnalysis(mlir::DataFlowSolver &dataflowSolver, llvm::SMTSolverRef smt, const Field &f, bool propInputConstraints)
Intervals over a finite field.
Definition Intervals.h:200
ModuleIntervalAnalysis(mlir::Operation *op)
virtual ~ModuleIntervalAnalysis()=default
void setPropagateInputConstraints(bool prop)
void initializeSolver() override
Initialize the shared dataflow solver with any common analyses required by the contained struct analy...
const IntervalAnalysisContext & getContext() const override
Return the current Context object.
void setField(const Field &f)
The dataflow analysis that computes the set of references that LLZK operations use and produce.
A reference to a "source", which is the base value from which other SSA values are derived.
Definition SourceRef.h:127
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
void setResult(const IntervalAnalysisContext &ctx, StructIntervals &&r)
StructAnalysis(mlir::Operation *op)
Assert that this analysis is being run on a StructDefOp and initializes the analysis with the current...
virtual ~StructIntervalAnalysis()=default
mlir::LogicalResult runAnalysis(mlir::DataFlowSolver &solver, mlir::AnalysisManager &, const IntervalAnalysisContext &ctx) override
Perform the analysis and construct the Result output.
const llvm::MapVector< SourceRef, Interval > & getConstrainIntervals() const
const llvm::SetVector< ExpressionValue > getConstrainSolverConstraints() const
const llvm::SetVector< ExpressionValue > getComputeSolverConstraints() const
const llvm::MapVector< SourceRef, Interval > & getComputeIntervals() const
void print(mlir::raw_ostream &os, bool withConstraints=false, bool printCompute=false) const
static mlir::FailureOr< StructIntervals > compute(mlir::ModuleOp mod, component::StructDefOp s, mlir::DataFlowSolver &solver, const IntervalAnalysisContext &ctx)
Compute the struct intervals.
friend mlir::raw_ostream & operator<<(mlir::raw_ostream &os, const StructIntervals &si)
mlir::LogicalResult computeIntervals(mlir::DataFlowSolver &solver, const IntervalAnalysisContext &ctx)
mlir::SymbolTableCollection tables
LLZK: Added for use of symbol helper caching.
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, const llvm::Twine &errMsg)
APSInt toAPSInt(const DynamicAPInt &i)
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.
const Field & getField() const
friend bool operator==(const IntervalAnalysisContext &a, const IntervalAnalysisContext &b)=default
std::optional< std::reference_wrapper< const Field > > field
IntervalDataFlowAnalysis * intervalDFA
llvm::SMTExprRef getSymbol(const SourceRef &r) const
size_t operator()(const llzk::IntervalAnalysisContext &c) const