1515#include " llzk/Analysis/DenseAnalysis.h"
1616#include " llzk/Analysis/Field.h"
1717#include " llzk/Analysis/Intervals.h"
18+ #include " llzk/Analysis/SparseAnalysis.h"
1819#include " llzk/Dialect/Array/IR/Ops.h"
1920#include " llzk/Dialect/Bool/IR/Ops.h"
2021#include " llzk/Dialect/Cast/IR/Ops.h"
@@ -47,7 +48,9 @@ class ExpressionValue {
4748 /* Must be default initializable to be a ScalarLatticeValue. */
4849 ExpressionValue () : i(), expr(nullptr ) {}
4950
50- explicit ExpressionValue (const Field &f, llvm::SMTExprRef exprRef)
51+ explicit ExpressionValue (const Field &f) : i(Interval::Entire(f)), expr(nullptr ) {}
52+
53+ ExpressionValue (const Field &f, llvm::SMTExprRef exprRef)
5154 : i(Interval::Entire(f)), expr(exprRef) {}
5255
5356 ExpressionValue (const Field &f, llvm::SMTExprRef exprRef, const llvm::DynamicAPInt &singleVal)
@@ -199,9 +202,7 @@ class IntervalAnalysisLatticeValue
199202
200203class IntervalDataFlowAnalysis ;
201204
202- // / @brief Maps mlir::Values to LatticeValues.
203- // /
204- class IntervalAnalysisLattice : public dataflow ::AbstractDenseLattice {
205+ class IntervalAnalysisLattice : public dataflow ::AbstractSparseLattice {
205206public:
206207 using LatticeValue = IntervalAnalysisLatticeValue;
207208 // Map mlir::Values to LatticeValues
@@ -214,23 +215,18 @@ class IntervalAnalysisLattice : public dataflow::AbstractDenseLattice {
214215 // Tracks all constraints and assignments in insertion order
215216 using ConstraintSet = llvm::SetVector<ExpressionValue>;
216217
217- using AbstractDenseLattice::AbstractDenseLattice ;
218+ using AbstractSparseLattice::AbstractSparseLattice ;
218219
219- mlir::ChangeResult join (const AbstractDenseLattice &other) override ;
220+ mlir::ChangeResult join (const AbstractSparseLattice &other) override ;
220221
221- mlir::ChangeResult meet (const AbstractDenseLattice & /* rhs*/ ) override {
222- llvm::report_fatal_error (" IntervalDataFlowAnalysis::meet : unsupported" );
223- return mlir::ChangeResult::NoChange;
224- }
222+ mlir::ChangeResult meet (const AbstractSparseLattice &other) override ;
225223
226224 void print (mlir::raw_ostream &os) const override ;
227225
228- mlir::FailureOr<LatticeValue> getValue (mlir::Value v) const ;
229- mlir::FailureOr<LatticeValue> getValue (mlir::Value v, mlir::StringAttr f) const ;
226+ const LatticeValue &getValue () const { return val; }
230227
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);
228+ mlir::ChangeResult setValue (const LatticeValue &val);
229+ mlir::ChangeResult setValue (ExpressionValue e);
234230
235231 mlir::ChangeResult addSolverConstraint (ExpressionValue e);
236232
@@ -244,27 +240,16 @@ class IntervalAnalysisLattice : public dataflow::AbstractDenseLattice {
244240 mlir::FailureOr<Interval> findInterval (llvm::SMTExprRef expr) const ;
245241 mlir::ChangeResult setInterval (llvm::SMTExprRef expr, const Interval &i);
246242
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-
256243private:
257- ValueMap valMap;
258- FieldMap fieldMap;
244+ LatticeValue val;
259245 ConstraintSet constraints;
260- ExpressionIntervals intervals;
261246};
262247
263248/* IntervalDataFlowAnalysis */
264249
265250class IntervalDataFlowAnalysis
266- : public dataflow::DenseForwardDataFlowAnalysis <IntervalAnalysisLattice> {
267- using Base = dataflow::DenseForwardDataFlowAnalysis <IntervalAnalysisLattice>;
251+ : public dataflow::SparseForwardDataFlowAnalysis <IntervalAnalysisLattice> {
252+ using Base = dataflow::SparseForwardDataFlowAnalysis <IntervalAnalysisLattice>;
268253 using Lattice = IntervalAnalysisLattice;
269254 using LatticeValue = IntervalAnalysisLattice::LatticeValue;
270255
@@ -276,23 +261,28 @@ class IntervalDataFlowAnalysis
276261 mlir::DataFlowSolver &dataflowSolver, llvm::SMTSolverRef smt, const Field &f,
277262 bool propInputConstraints
278263 )
279- : Base::DenseForwardDataFlowAnalysis (dataflowSolver), _dataflowSolver(dataflowSolver),
264+ : Base::SparseForwardDataFlowAnalysis (dataflowSolver), _dataflowSolver(dataflowSolver),
280265 smtSolver(smt), field(f), propagateInputConstraints(propInputConstraints) {}
281266
282- void visitCallControlFlowTransfer (
283- mlir::CallOpInterface call, dataflow::CallControlFlowAction action, const Lattice &before ,
284- Lattice *after
267+ mlir::LogicalResult visitOperation (
268+ mlir::Operation *op, mlir::ArrayRef< const Lattice *> operands ,
269+ mlir::ArrayRef< Lattice *> results
285270 ) override ;
286271
287- mlir::LogicalResult
288- visitOperation (mlir::Operation *op, const Lattice &before, Lattice *after) override ;
289-
290272 // / @brief Either return the existing SMT expression that corresponds to the SourceRef,
291273 // / or create one.
292274 // / @param r
293275 // / @return
294276 llvm::SMTExprRef getOrCreateSymbol (const SourceRef &r);
295277
278+ const llvm::DenseMap<SourceRef, llvm::DenseSet<Lattice *>> &getFieldReadResults () const {
279+ return fieldReadResults;
280+ }
281+
282+ const llvm::DenseMap<SourceRef, ExpressionValue> &getFieldWriteResults () const {
283+ return fieldWriteResults;
284+ }
285+
296286private:
297287 mlir::DataFlowSolver &_dataflowSolver;
298288 llvm::SMTSolverRef smtSolver;
@@ -301,8 +291,14 @@ class IntervalDataFlowAnalysis
301291 bool propagateInputConstraints;
302292 mlir::SymbolTableCollection tables;
303293
294+ // Track field reads so that propagations to fields can be all updated efficiently.
295+ llvm::DenseMap<SourceRef, llvm::DenseSet<Lattice *>> fieldReadResults;
296+ // Track field writes values. For now, we'll overapproximate this.
297+ llvm::DenseMap<SourceRef, ExpressionValue> fieldWriteResults;
298+
304299 void setToEntryState (Lattice *lattice) override {
305- // initial state should be empty, so do nothing here
300+ // Initialize the value with an interval in our specified field.
301+ (void )lattice->setValue (ExpressionValue (field.get ()));
306302 }
307303
308304 llvm::SMTExprRef createFeltSymbol (const SourceRef &r) const ;
@@ -349,57 +345,22 @@ class IntervalDataFlowAnalysis
349345 // / @param after The current lattice state. Assumes that this has already been joined with the
350346 // / `before` lattice in `visitOperation`, so lookups and updates can be performed on the `after`
351347 // / lattice alone.
352- mlir::ChangeResult applyInterval (
353- mlir::Operation *originalOp, Lattice *originalLattice, Lattice *after, mlir::Value val,
354- Interval newInterval
355- );
348+ void applyInterval (mlir::Operation *originalOp, mlir::Value val, Interval newInterval);
356349
357350 // / @brief Special handling for generalized (s - c0) * (s - c1) * ... * (s - cN) = 0 patterns.
358351 mlir::FailureOr<std::pair<llvm::DenseSet<mlir::Value>, Interval>>
359352 getGeneralizedDecompInterval (mlir::Operation *baseOp, mlir::Value lhs, mlir::Value rhs);
360353
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-
375354 bool isReadOp (mlir::Operation *op) const {
376355 return llvm::isa<component::FieldReadOp, polymorphic::ConstReadOp, array::ReadArrayOp>(op);
377356 }
378357
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-
395358 bool isDefinitionOp (mlir::Operation *op) const {
396359 return llvm::isa<
397360 component::StructDefOp, function::FuncDefOp, component::FieldDefOp, global::GlobalDefOp,
398361 mlir::ModuleOp>(op);
399362 }
400363
401- bool isCallOp (mlir::Operation *op) const { return llvm::isa<function::CallOp>(op); }
402-
403364 bool isReturnOp (mlir::Operation *op) const { return llvm::isa<function::ReturnOp>(op); }
404365
405366 // / @brief Get the SourceRefLattice that defines `val`, or the SourceRefLattice after `baseOp`
0 commit comments