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