LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
llzk-opt.cpp
Go to the documentation of this file.
1//===-- llzk-opt.cpp - LLZK opt tool ----------------------------*- 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//===----------------------------------------------------------------------===//
14//===----------------------------------------------------------------------===//
15
16#include "r1cs/Dialect/IR/Dialect.h"
17#include "r1cs/DialectRegistration.h"
18#include "r1cs/Transforms/TransformationPasses.h"
19#include "smt/Conversions/ConversionPasses.h"
20#include "tools/config.h"
21#include "zklean/Conversions/Passes.h"
22#include "zklean/DialectRegistration.h"
23#include "zklean/Transforms/ZKLeanPasses.h"
24
26#include "llzk/Config/Config.h"
34
35#include <mlir/Dialect/Func/Extensions/InlinerExtension.h>
36#include <mlir/Dialect/Func/IR/FuncOps.h>
37#include <mlir/Dialect/SCF/IR/SCF.h>
38#include <mlir/IR/DialectRegistry.h>
39#include <mlir/Pass/PassManager.h>
40#include <mlir/Pass/PassRegistry.h>
41#include <mlir/Tools/mlir-opt/MlirOptMain.h>
42#include <mlir/Transforms/Passes.h>
43
44#include <llvm/ADT/StringRef.h>
45#include <llvm/Support/CommandLine.h>
46#include <llvm/Support/PrettyStackTrace.h>
47#include <llvm/Support/Signals.h>
48
49#if LLZK_WITH_PCL
50#include "pcl-conv/Transforms/TransformationPasses.h"
51
52#include <pcl/Dialect/IR/Dialect.h>
53#include <pcl/InitAllDialects.h>
54#include <pcl/Transforms/PCLTransformationPasses.h>
55#endif // LLZK_WITH_PCL
56
57static llvm::cl::list<std::string> IncludeDirs(
58 "I", llvm::cl::desc("Directory of include files"), llvm::cl::value_desc("directory"),
59 llvm::cl::Prefix
60);
61
62static llvm::cl::opt<bool>
63 PrintAllOps("print-llzk-ops", llvm::cl::desc("Print a list of all ops registered in LLZK"));
64
68namespace mlir_hotfix {
69
71 : public mlir::PassWrapper<RemoveDeadValuesWorkaroundPass, mlir::OperationPass<>> {
72public:
73 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(RemoveDeadValuesWorkaroundPass)
74
75 llvm::StringRef getArgument() const override { return "remove-dead-values"; }
76 llvm::StringRef getDescription() const override { return "Remove dead values"; }
77
78 void runOnOperation() final {
79 // pre-pass: add trivial block to empty "else" regions of scf.if ops
80 getOperation()->walk([](mlir::scf::IfOp ifOp) {
81 if (ifOp.getElseRegion().empty()) {
82 mlir::Block &elseBlock = ifOp.getElseRegion().emplaceBlock();
83 mlir::OpBuilder builder(ifOp.getContext());
84 builder.setInsertionPointToEnd(&elseBlock);
85 builder.create<mlir::scf::YieldOp>(ifOp.getLoc());
86 }
87 });
88
89 mlir::OpPassManager pm(getOperation()->getName().getStringRef());
90 pm.addPass(mlir::createRemoveDeadValuesPass());
91 if (mlir::failed(runPipeline(pm, getOperation()))) {
92 signalPassFailure();
93 }
94
95 // post-pass: cleanup trival "else" blocks that remain after the pass
96 getOperation()->walk([](mlir::scf::IfOp ifOp) {
97 if (ifOp.getResults().empty()) {
98 mlir::Region &elseRegion = ifOp.getElseRegion();
99 if (!llvm::hasSingleElement(elseRegion)) {
100 return;
101 }
102 mlir::Block &elseBlock = elseRegion.front();
103 if (!llvm::hasSingleElement(elseBlock)) {
104 return;
105 }
106 if (!llvm::isa<mlir::scf::YieldOp>(elseBlock.front())) {
107 return;
108 }
109 elseRegion.dropAllReferences();
110 elseBlock.clear();
111 elseRegion.getBlocks().clear();
112 }
113 });
114 }
115};
116
117inline static void registerTransformsPasses() {
118 mlir::registerCSE();
119 mlir::registerCanonicalizer();
120 mlir::registerCompositeFixedPointPass();
121 mlir::registerControlFlowSink();
122 mlir::registerGenerateRuntimeVerification();
123 mlir::registerInliner();
124 mlir::registerLocationSnapshot();
125 mlir::registerLoopInvariantCodeMotion();
126 mlir::registerLoopInvariantSubsetHoisting();
127 mlir::registerMem2Reg();
128 mlir::registerPrintIRPass();
129 mlir::registerPrintOpStats();
130 mlir::registerPass([]() -> std::unique_ptr<mlir::Pass> {
131 return std::make_unique<RemoveDeadValuesWorkaroundPass>();
132 });
133 mlir::registerSCCP();
134 mlir::registerSROA();
135 mlir::registerStripDebugInfo();
136 mlir::registerSymbolDCE();
137 mlir::registerSymbolPrivatize();
138 mlir::registerTopologicalSort();
139 mlir::registerViewOpGraph();
140}
141
142} // namespace mlir_hotfix
143
144int main(int argc, char **argv) {
145 llvm::sys::PrintStackTraceOnErrorSignal(llvm::StringRef());
146 llvm::setBugReportMsg(
147 "PLEASE submit a bug report to " BUG_REPORT_URL
148 " and include the crash backtrace, relevant LLZK files,"
149 " and associated run script(s).\n"
150 );
151 llvm::cl::AddExtraVersionPrinter([](llvm::raw_ostream &os) {
152 os << "\nLLZK (" LLZK_URL "):\n LLZK version " LLZK_VERSION_STRING "\n";
153 });
154
155 // MLIR initialization
156 mlir::DialectRegistry registry;
157 // registers CSE, etc
158 mlir_hotfix::registerTransformsPasses();
160 r1cs::registerAllDialects(registry);
161 zklean::registerAllDialects(registry);
162 mlir::func::registerInlinerExtension(registry);
163#if LLZK_WITH_PCL
164 pcl::registerAllDialects(registry);
165#endif // LLZK_WITH_PCL
166
173 r1cs::registerTransformationPasses();
174 zklean::registerConversionPasses();
175 zklean::registerZKLeanPasses();
176#if LLZK_WITH_PCL
177 pcl::registerTransformationPasses();
178 pcl::conversion::registerPCLTransformationPasses();
179#endif // LLZK_WITH_PCL
180
182 r1cs::registerTransformationPassPipelines();
183 llzk::smt::registerConversionPasses();
184
185 // Register and parse command line options.
186 std::string inputFilename, outputFilename;
187 std::tie(inputFilename, outputFilename) =
188 registerAndParseCLIOptions(argc, argv, "llzk-opt", registry);
189
190 if (PrintAllOps) {
191 mlir::MLIRContext context;
192 context.appendDialectRegistry(registry);
193 context.loadAllAvailableDialects();
194 llvm::outs() << "All ops registered in LLZK IR: {\n";
195 for (const auto &opName : context.getRegisteredOperations()) {
196 llvm::outs().indent(2) << opName.getStringRef() << '\n';
197 }
198 llvm::outs() << "}\n";
199 return EXIT_SUCCESS;
200 }
201
202 // Set the include directories from CL option
203 if (mlir::failed(llzk::GlobalSourceMgr::get().setup(IncludeDirs))) {
204 return EXIT_FAILURE;
205 }
206
207 // Run 'mlir-opt'
208 auto result = mlir::MlirOptMain(argc, argv, inputFilename, outputFilename, registry);
209 return mlir::asMainReturnCode(result);
210}
#define LLZK_VERSION_STRING
Definition Config.h:12
#define LLZK_URL
Definition Config.h:17
static GlobalSourceMgr & get()
llvm::StringRef getArgument() const override
Definition llzk-opt.cpp:75
llvm::StringRef getDescription() const override
Definition llzk-opt.cpp:76
#define BUG_REPORT_URL
Definition config.h:15
int main(int argc, char **argv)
Definition llzk-opt.cpp:144
This file defines llzk::registerAllDialects.
void registerTransformationPasses()
void registerTransformationPasses()
void registerTransformationPassPipelines()
void registerValidationPasses()
void registerAllDialects(mlir::DialectRegistry &registry)
void registerAnalysisPasses()
Replace mlir::registerTransformsPasses() to register a custom remove-dead-values pass because MLIR ve...
Definition llzk-opt.cpp:68