LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
MemberOverwriteAnalysis.h
Go to the documentation of this file.
1//===-- MemberOverwriteAnalysis.h -------------------------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2026 Project LLZK
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
10#pragma once
11
13
14#include <mlir/Analysis/DataFlow/DenseAnalysis.h>
15
16#include <llvm/Support/Debug.h>
17
18namespace llzk {
19
24class FuzzySet {
25
26 using Present = bool;
27
28 llvm::DenseMap<llvm::StringRef, Present> isPresent;
29 bool _value_is(llvm::StringRef key, Present present) const {
30 return isPresent.contains(key) && isPresent.at(key) == present;
31 }
32 bool _set_to(llvm::StringRef key, Present present) {
33 bool changed = !_value_is(key, present);
34 isPresent[key] = present;
35 return changed;
36 }
37
38 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const FuzzySet &set);
39
40public:
43 bool contains(llvm::StringRef key) const { return _value_is(key, true); }
44
47 bool doesNotContain(llvm::StringRef key) const { return _value_is(key, false); }
48
51 bool insert(llvm::StringRef key) { return _set_to(key, true); }
52
55 bool remove(llvm::StringRef key) { return _set_to(key, false); }
56
61 bool intersect(const FuzzySet &other) {
62 bool changed = false;
63
64 llvm::DenseSet<llvm::StringRef> allKeys;
65
66 for (auto [key, _] : isPresent) {
67 allKeys.insert(key);
68 }
69 for (auto [key, _] : other.isPresent) {
70 allKeys.insert(key);
71 }
72
73 for (auto key : allKeys) {
74 if (isPresent.contains(key) && other.isPresent.contains(key)) {
75 changed |= _set_to(key, isPresent.at(key) && other.isPresent.at(key));
76 } else if (other.isPresent.contains(key)) {
77 changed |= _set_to(key, other.isPresent.at(key));
78 }
79 }
80
81 return changed;
82 }
83
84 bool operator==(const FuzzySet &other) const = default;
85};
86
87inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const FuzzySet &set) {
88 os << "[ ";
89 for (auto [key, c] : set.isPresent) {
90 os << (c ? "" : "x") << key << ' ';
91 }
92 os << ']';
93 return os;
94}
95
97
98using Overwrite = std::pair<component::MemberWriteOp, component::MemberWriteOp>;
99
100llvm::FailureOr<std::pair<llvm::SetVector<Overwrite>, FuzzySet>>
102
103class MemberOverwriteLattice : public mlir::dataflow::AbstractDenseLattice {
104 llvm::DenseMap<llvm::StringRef, component::MemberWriteOp> mayWrites;
105 llvm::SetVector<Overwrite> overwrites;
106
107 FuzzySet mustWrites;
108
109 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const MemberOverwriteLattice &lat);
110 friend llvm::FailureOr<std::pair<llvm::SetVector<Overwrite>, FuzzySet>>
112
113public:
114 using AbstractDenseLattice::AbstractDenseLattice;
115 mlir::ChangeResult join(const mlir::dataflow::AbstractDenseLattice &other) override;
116
117 bool operator==(const MemberOverwriteLattice &other) const {
118 return std::tie(mayWrites, overwrites, mustWrites) ==
119 std::tie(other.mayWrites, other.overwrites, mustWrites);
120 }
121
122 void print(llvm::raw_ostream &os) const override;
123
124 void entry() {
125 auto structDef = dyn_cast<mlir::ProgramPoint *>(getAnchor())
126 ->getBlock()
127 ->getParentOp()
128 ->getParentOfType<component::StructDefOp>();
129 for (auto memberDef : structDef.getMemberDefs()) {
130 mustWrites.remove(memberDef.getSymName());
131 }
132 }
133
134 mlir::ChangeResult record(component::MemberWriteOp write);
135
136 bool hasOverwrites() const;
137 llvm::SetVector<Overwrite> getOverwrites() const;
139};
140
142 : public mlir::dataflow::DenseForwardDataFlowAnalysis<MemberOverwriteLattice> {
143public:
144 using DenseForwardDataFlowAnalysis::DenseForwardDataFlowAnalysis;
145 mlir::LogicalResult visitOperation(
146 mlir::Operation *op, const MemberOverwriteLattice &before, MemberOverwriteLattice *after
147 ) override;
148
149 void setToEntryState(MemberOverwriteLattice *lattice) override { lattice->entry(); }
150};
151
152}; // namespace llzk
Represents a set where the membership predicate can take three values: true, false,...
bool contains(llvm::StringRef key) const
key \in *this == true (key is definitely present)
bool remove(llvm::StringRef key)
Mark key as definitely not present.
bool intersect(const FuzzySet &other)
Perform an intersection in-place.
bool doesNotContain(llvm::StringRef key) const
key \in *this == false (key is definitely not present)
bool insert(llvm::StringRef key)
Mark key as definitely present.
bool operator==(const FuzzySet &other) const =default
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const FuzzySet &set)
mlir::LogicalResult visitOperation(mlir::Operation *op, const MemberOverwriteLattice &before, MemberOverwriteLattice *after) override
void setToEntryState(MemberOverwriteLattice *lattice) override
void print(llvm::raw_ostream &os) const override
llvm::SetVector< Overwrite > getOverwrites() const
bool checkWritten(component::MemberDefOp) const
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const MemberOverwriteLattice &lat)
mlir::ChangeResult join(const mlir::dataflow::AbstractDenseLattice &other) override
friend llvm::FailureOr< std::pair< llvm::SetVector< Overwrite >, FuzzySet > > analyzeStruct(component::StructDefOp)
bool operator==(const MemberOverwriteLattice &other) const
mlir::ChangeResult record(component::MemberWriteOp write)
std::pair< component::MemberWriteOp, component::MemberWriteOp > Overwrite
Interval operator<<(const Interval &lhs, const Interval &rhs)
llvm::FailureOr< std::pair< llvm::SetVector< Overwrite >, FuzzySet > > analyzeStruct(component::StructDefOp structDef)