LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
SharedImpl.h
Go to the documentation of this file.
1//===-- SharedImpl.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//===----------------------------------------------------------------------===//
13//===----------------------------------------------------------------------===//
14
15#pragma once
16
23
24#include <mlir/IR/BuiltinAttributes.h>
25#include <mlir/IR/MLIRContext.h>
26#include <mlir/IR/Operation.h>
27#include <mlir/IR/SymbolTable.h>
28#include <mlir/Transforms/DialectConversion.h>
29
30#include <llvm/ADT/ArrayRef.h>
31#include <llvm/ADT/DenseMap.h>
32#include <llvm/ADT/DenseSet.h>
33#include <llvm/ADT/STLExtras.h>
34#include <llvm/ADT/SmallVector.h>
35#include <llvm/ADT/StringRef.h>
36#include <llvm/Support/Debug.h>
37
38#include <string>
39#include <tuple>
40#include <utility>
41
42#define DEBUG_TYPE "poly-dialect-shared"
43
45
46namespace {
47
48// Default to true if the check is not for that particular operation type.
49template <typename Check> inline bool runCheck(mlir::Operation *op, Check check) {
50 if (auto specificOp =
51 llvm::dyn_cast_if_present<typename llvm::function_traits<Check>::template arg_t<0>>(op)) {
52 return check(specificOp);
53 }
54 return true;
55}
56
57} // namespace
58
60mlir::ConversionTarget newBaseTarget(mlir::MLIRContext *ctx);
61
64public:
65 mlir::SymbolTableCollection tables;
66
68 mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph
69 );
70
71protected:
72 mlir::ModuleOp rootMod;
75};
76
78bool isErasableDefinition(mlir::Operation *op);
79
82class FromEraseSet : public CleanupBase {
83public:
86 mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph,
87 llvm::DenseSet<mlir::SymbolRefAttr> &&tryToErasePaths
88 );
89
90 mlir::LogicalResult eraseUnusedDefinitions();
91
92 const llvm::DenseSet<mlir::SymbolOpInterface> &getTryToEraseSet() const { return tryToErase; }
93
94private:
96 llvm::DenseSet<mlir::SymbolOpInterface> tryToErase;
98 llvm::DenseMap<mlir::SymbolOpInterface, bool> visitedPlusSafetyResult;
100 llvm::DenseMap<const SymbolUseGraphNode *, mlir::SymbolOpInterface> lookupCache;
101
102 bool collectSafeToErase(mlir::SymbolOpInterface check);
103 bool collectSafeToErase(const SymbolDefTreeNode *check);
104 bool collectSafeToErase(const SymbolUseGraphNode *check);
105 mlir::SymbolOpInterface cachedLookup(const SymbolUseGraphNode *node);
106};
107
114
117getStructTypeWithParams(mlir::SymbolRefAttr nameRef, mlir::ArrayAttr params) {
118 return params && !params.empty() ? component::StructType::get(nameRef, params)
120}
121
124 mlir::SymbolRefAttr nameRef, mlir::MLIRContext *ctx, mlir::ArrayRef<mlir::Attribute> params
125) {
126 return params.empty() ? component::StructType::get(nameRef)
127 : component::StructType::get(nameRef, mlir::ArrayAttr::get(ctx, params));
128}
129
133 mlir::SmallVector<mlir::Attribute> remainingNames;
135 mlir::ArrayAttr concreteParamKey;
137 mlir::ArrayAttr rewrittenCallParams;
139 mlir::ArrayAttr namePattern;
140};
141
145mlir::FailureOr<InstantiationLayout> buildInstantiationLayout(
146 TemplateOp parentTemplate, mlir::ArrayAttr callParams,
147 const llvm::DenseMap<mlir::Attribute, mlir::Attribute> &paramNameToConcrete
148);
149
152void setInstantiationNamePattern(TemplateOp templateOp, mlir::ArrayAttr namePattern);
153
156 llvm::StringRef baseName, llvm::ArrayRef<mlir::Attribute> concreteAttrs
157);
158
160public:
161 virtual ~LegalityCheckCallback() = default;
162 virtual void checkStarted() = 0;
163 virtual void checkEnded(bool outcome) = 0;
164};
165
167public:
168 void checkStarted() override {}
169 void checkEnded(bool) override {}
170};
171
177template <typename... AdditionalOpClasses, typename... AdditionalChecks>
178mlir::ConversionTarget newConverterDefinedTarget(
179 mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, AdditionalChecks &&...checks
180) {
181 static EmptyLegalityCheckCallback empty;
182 return newConverterDefinedTargetWithCallback<AdditionalOpClasses...>(
183 tyConv, ctx, empty, (std::forward<AdditionalChecks>(checks))...
184 );
185}
186
192template <typename... AdditionalOpClasses, typename... AdditionalChecks>
194 mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, LegalityCheckCallback &cb,
195 AdditionalChecks &&...checks
196) {
197 mlir::ConversionTarget target = newBaseTarget(ctx);
198 auto inserter = [&](auto... opClasses) {
199 target.addDynamicallyLegalOp<decltype(opClasses)...>([&cb, &tyConv,
200 &checks...](mlir::Operation *op) {
201 LLVM_DEBUG(if (op) {
202 llvm::dbgs() << "[newConverterDefinedTarget] checking legality of ";
203 op->dump();
204 });
205 cb.checkStarted();
206 auto legality =
207 defaultLegalityCheck(tyConv, op) && (runCheck<AdditionalChecks>(op, checks) && ...);
208
209 cb.checkEnded(legality);
210 LLVM_DEBUG(if (legality) { llvm::dbgs() << "[newConverterDefinedTarget] is legal\n"; } else {
211 llvm::dbgs() << "[newConverterDefinedTarget] is not legal\n";
212 });
213 return legality;
214 });
215 };
216 std::apply(inserter, OpClassesWithStructTypes::NoGeneralBuilder {});
217 std::apply(inserter, OpClassesWithStructTypes::WithGeneralBuilder {});
218 applyToMoreTypes<decltype(inserter), AdditionalOpClasses...>(inserter);
219 return target;
220}
221
222} // namespace llzk::polymorphic::detail
223
224#undef DEBUG_TYPE
#define check(x)
Definition Ops.cpp:369
Reusable MLIR dialect conversion functions for LLZK StructType replacement.
Builds a tree structure representing the symbol table structure.
Builds a graph structure representing the relationships between symbols and their uses.
static StructType get(::mlir::SymbolRefAttr structName)
Definition Types.cpp.inc:81
const SymbolUseGraph & useGraph
Definition SharedImpl.h:74
mlir::SymbolTableCollection tables
Definition SharedImpl.h:65
CleanupBase(mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph)
mlir::LogicalResult eraseUnusedDefinitions()
const llvm::DenseSet< mlir::SymbolOpInterface > & getTryToEraseSet() const
Definition SharedImpl.h:92
FromEraseSet(mlir::ModuleOp root, const SymbolDefTree &symDefTree, const SymbolUseGraph &symUseGraph, llvm::DenseSet< mlir::SymbolRefAttr > &&tryToErasePaths)
Note: paths in tryToErase should be relative to root.
Common interface for constant parameter-like symbol operations that can be defined within a TemplateO...
component::StructType getStructTypeWithParams(mlir::SymbolRefAttr nameRef, mlir::ArrayAttr params)
Build a struct type while representing an empty parameter list as absent.
Definition SharedImpl.h:117
mlir::ConversionTarget newConverterDefinedTargetWithCallback(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, LegalityCheckCallback &cb, AdditionalChecks &&...checks)
Return a new ConversionTarget allowing all LLZK-required dialects and defining Op legality based on t...
Definition SharedImpl.h:193
mlir::ConversionTarget newConverterDefinedTarget(mlir::TypeConverter &tyConv, mlir::MLIRContext *ctx, AdditionalChecks &&...checks)
Return a new ConversionTarget allowing all LLZK-required dialects and defining Op legality based on t...
Definition SharedImpl.h:178
FailureOr< InstantiationLayout > buildInstantiationLayout(TemplateOp parentTemplate, ArrayAttr callParams, const DenseMap< Attribute, Attribute > &paramNameToConcrete)
array::ArrayType flattenInstantiatedArrayType(array::ArrayType inputTy, mlir::Type convertedElemTy)
Merge nested array dimensions produced by replacing an array element type.
void setInstantiationNamePattern(TemplateOp templateOp, ArrayAttr namePattern)
std::string buildOpaqueInstantiationName(StringRef baseName, ArrayRef< Attribute > concreteAttrs)
bool isErasableDefinition(mlir::Operation *op)
Return true iff op is a cleanup candidate.
mlir::ConversionTarget newBaseTarget(mlir::MLIRContext *ctx)
Return a new ConversionTarget allowing all LLZK-required dialects.
bool defaultLegalityCheck(const mlir::TypeConverter &tyConv, mlir::Operation *op)
Check whether an op is legal with respect to the given type converter, including TypeAttr attributes ...
std::tuple< function::CallOp, array::CreateArrayOp, pod::NewPodOp > NoGeneralBuilder
Ops in this subset do NOT define the general builder function (see above), so they cannot use General...
std::tuple< array::ArrayLengthOp, array::ReadArrayOp, array::WriteArrayOp, array::InsertArrayOp, array::ExtractArrayOp, constrain::EmitEqualityOp, constrain::EmitContainmentOp, component::MemberDefOp, component::MemberReadOp, component::MemberWriteOp, component::CreateStructOp, function::FuncDefOp, function::ReturnOp, global::GlobalDefOp, global::GlobalReadOp, global::GlobalWriteOp, llzk::NonDetOp, pod::ReadPodOp, pod::WritePodOp, polymorphic::UnifiableCastOp, polymorphic::ConstReadOp > WithGeneralBuilder
Ops in this subset define the general builder function: build(OpBuilder&, OperationState&,...
Groups the information needed after concrete parameters have been chosen to decide how to name a new ...
Definition SharedImpl.h:132
mlir::ArrayAttr namePattern
The refined literal chunks; fully concrete generated templates clear this state.
Definition SharedImpl.h:139
mlir::SmallVector< mlir::Attribute > remainingNames
Definition SharedImpl.h:133
mlir::ArrayAttr concreteParamKey
Ordered [parameter-name, concrete-value, ...] entries for exact partial-function reuse.
Definition SharedImpl.h:135