LLZK
3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Toggle main menu visibility
Loading...
Searching...
No Matches
MemberOverwriteAnalysis.cpp
Go to the documentation of this file.
1
//===-- MemberOverwriteAnalysis.cpp -----------------------------*- 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
#include "
llzk/Analysis/MemberOverwriteAnalysis.h
"
11
12
#include "
llzk/Analysis/AnalysisUtil.h
"
13
#include "
llzk/Dialect/Function/IR/Ops.h
"
14
#include "
llzk/Dialect/Struct/IR/Ops.h
"
15
16
#include <llvm/ADT/TypeSwitch.h>
17
#include <llvm/Support/Debug.h>
18
19
#define DEBUG_TYPE "member-overwrite-analysis"
20
21
using namespace
mlir
;
22
using namespace
mlir::dataflow;
23
24
namespace
llzk
{
25
using namespace
component;
26
27
llvm::raw_ostream &
operator<<
(llvm::raw_ostream &os,
const
MemberOverwriteLattice
&lat) {
28
os << lat.mustWrites;
29
return
os;
30
}
31
32
ChangeResult
MemberOverwriteLattice::record
(
MemberWriteOp
write) {
33
auto
name = write.
getMemberName
();
34
35
bool
changed =
false
;
36
37
if
(
auto
it = mayWrites.find(name); it != mayWrites.end() && it->second != write) {
38
// .insert(...) returns true if an insertion was performed (i.e., it wasn't present before),
39
// meaning there was a change
40
changed |= overwrites.insert({mayWrites.at(name), write});
41
}
else
{
42
mayWrites.insert({name, write});
43
changed =
true
;
44
}
45
46
changed |= mustWrites.insert(name);
47
return
ChangeResult {changed};
48
}
49
50
ChangeResult
MemberOverwriteLattice::join
(
const
AbstractDenseLattice &other) {
51
const
auto
*rhs =
dynamic_cast<
const
MemberOverwriteLattice
*
>
(&other);
52
ensure
(rhs,
"cannot join incomparable lattices"
);
53
54
LLVM_DEBUG(
55
llvm::dbgs() <<
"Joining "
<< *dyn_cast<ProgramPoint *>(getAnchor()) <<
'('
<< *
this
56
<<
") with "
<< *dyn_cast<ProgramPoint *>(rhs->getAnchor()) <<
'('
<< *rhs
57
<<
")\n"
58
);
59
bool
changed =
false
;
60
61
// Union the mayWrites
62
for
(
auto
[name, write] : rhs->mayWrites) {
63
auto
it = mayWrites.find(name);
64
changed |= it == mayWrites.end() || it->second != write;
65
mayWrites[name] = write;
66
}
67
changed |= overwrites.set_union(rhs->overwrites);
68
69
// "Intersect" the mustWrites
70
changed |= mustWrites.intersect(rhs->mustWrites);
71
72
return
ChangeResult {changed};
73
}
74
75
bool
MemberOverwriteLattice::hasOverwrites
()
const
{
return
!overwrites.empty(); }
76
77
llvm::SetVector<Overwrite>
MemberOverwriteLattice::getOverwrites
()
const
{
return
overwrites; }
78
79
bool
MemberOverwriteLattice::checkWritten
(
component::MemberDefOp
memberDef)
const
{
80
return
mustWrites.contains(memberDef.
getSymName
());
81
}
82
83
void
MemberOverwriteLattice::print
(llvm::raw_ostream &os)
const
{ os << *
this
<<
'\n'
; }
84
85
LogicalResult
MemberOverwriteAnalysis::visitOperation
(
86
Operation *op,
const
MemberOverwriteLattice
&before,
MemberOverwriteLattice
*after
87
) {
88
ChangeResult result = after->
join
(before);
89
90
LLVM_DEBUG(llvm::dbgs() <<
"Visiting operation: "
<< *op <<
": "
<< before <<
'\n'
);
91
92
if
(
auto
write = dyn_cast<MemberWriteOp>(op)) {
93
result |= after->
record
(write);
94
}
95
96
propagateIfChanged(after, result);
97
return
success();
98
}
99
100
llvm::FailureOr<std::pair<llvm::SetVector<Overwrite>,
FuzzySet
>>
101
analyzeStruct
(
component::StructDefOp
structDef) {
102
function::FuncDefOp
computeOrProductFunc = structDef.
getComputeFuncOp
();
103
if
(!computeOrProductFunc) {
104
computeOrProductFunc = structDef.
getProductFuncOp
();
105
}
106
107
DataFlowSolver solver {DataFlowConfig {}.setInterprocedural(
false
)};
108
llzk::dataflow::loadRequiredAnalyses
(solver);
109
solver.load<
MemberOverwriteAnalysis
>();
110
if
(failed(solver.initializeAndRun(computeOrProductFunc))) {
111
return
llvm::failure();
112
}
113
114
auto
&funcBody = computeOrProductFunc.
getBody
();
115
if
(funcBody.empty()) {
116
// If there's nothing, just build a default lattice element (no overwrites, everything is
117
// unwritten)
118
return
{{{}, {}}};
119
}
120
121
auto
*returnOp = funcBody.back().getTerminator();
122
const
auto
*lattice =
123
solver.lookupState<
MemberOverwriteLattice
>(solver.getProgramPointAfter(returnOp));
124
return
{{lattice->getOverwrites(), lattice->mustWrites}};
125
}
126
127
}
// namespace llzk
AnalysisUtil.h
Ops.h
MemberOverwriteAnalysis.h
Ops.h
llzk::FuzzySet
Represents a set where the membership predicate can take three values: true, false,...
Definition
MemberOverwriteAnalysis.h:24
llzk::MemberOverwriteAnalysis
Definition
MemberOverwriteAnalysis.h:142
llzk::MemberOverwriteAnalysis::visitOperation
mlir::LogicalResult visitOperation(mlir::Operation *op, const MemberOverwriteLattice &before, MemberOverwriteLattice *after) override
Definition
MemberOverwriteAnalysis.cpp:85
llzk::MemberOverwriteLattice
Definition
MemberOverwriteAnalysis.h:103
llzk::MemberOverwriteLattice::print
void print(llvm::raw_ostream &os) const override
Definition
MemberOverwriteAnalysis.cpp:83
llzk::MemberOverwriteLattice::getOverwrites
llvm::SetVector< Overwrite > getOverwrites() const
Definition
MemberOverwriteAnalysis.cpp:77
llzk::MemberOverwriteLattice::checkWritten
bool checkWritten(component::MemberDefOp) const
Definition
MemberOverwriteAnalysis.cpp:79
llzk::MemberOverwriteLattice::join
mlir::ChangeResult join(const mlir::dataflow::AbstractDenseLattice &other) override
Definition
MemberOverwriteAnalysis.cpp:50
llzk::MemberOverwriteLattice::hasOverwrites
bool hasOverwrites() const
Definition
MemberOverwriteAnalysis.cpp:75
llzk::MemberOverwriteLattice::record
mlir::ChangeResult record(component::MemberWriteOp write)
Definition
MemberOverwriteAnalysis.cpp:32
llzk::component::MemberDefOp
Definition
Ops.h.inc:307
llzk::component::MemberDefOp::getSymName
::llvm::StringRef getSymName()
Definition
Ops.cpp.inc:528
llzk::component::MemberWriteOp
Definition
Ops.h.inc:920
llzk::component::MemberWriteOp::getMemberName
::llvm::StringRef getMemberName()
Definition
Ops.cpp.inc:1319
llzk::component::StructDefOp
Definition
Ops.h.inc:1148
llzk::component::StructDefOp::getProductFuncOp
::llzk::function::FuncDefOp getProductFuncOp()
Gets the FuncDefOp that defines the product function in this structure, if present,...
Definition
Ops.cpp:472
llzk::component::StructDefOp::getComputeFuncOp
::llzk::function::FuncDefOp getComputeFuncOp()
Gets the FuncDefOp that defines the compute function in this structure, if present,...
Definition
Ops.cpp:464
llzk::function::FuncDefOp
Definition
Ops.h.inc:633
llzk::function::FuncDefOp::getBody
::mlir::Region & getBody()
Definition
Ops.h.inc:703
llzk::dataflow::loadRequiredAnalyses
void loadRequiredAnalyses(DataFlowSolver &solver)
Definition
AnalysisUtil.cpp:22
llzk
Definition
AnalysisPassEnums.cpp:19
llzk::ensure
void ensure(bool condition, const llvm::Twine &errMsg)
Definition
ErrorHelper.h:159
llzk::operator<<
Interval operator<<(const Interval &lhs, const Interval &rhs)
Definition
Intervals.cpp:679
llzk::analyzeStruct
llvm::FailureOr< std::pair< llvm::SetVector< Overwrite >, FuzzySet > > analyzeStruct(component::StructDefOp structDef)
Definition
MemberOverwriteAnalysis.cpp:101
mlir
Definition
ValueModel.h:30
lib
Analysis
MemberOverwriteAnalysis.cpp
Generated by
1.17.0
Copyright 2025 Veridise Inc. under the Apache License v2.0. Copyright 2026 Project LLZK under the Apache License v2.0.