LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
LLZKInliningExtensions.cpp
Go to the documentation of this file.
1//===-- LLZKInliningExtensions.cpp ------------------------------*- 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//===----------------------------------------------------------------------===//
9
22
23#include <mlir/Dialect/ControlFlow/IR/ControlFlowOps.h>
24#include <mlir/Transforms/InliningUtils.h>
25
26using namespace mlir;
27using namespace llzk;
28
29namespace {
30
31template <typename InlinerImpl, typename DialectImpl, typename... RequiredDialects>
32struct BaseInlinerInterface : public DialectInlinerInterface {
33 using DialectInlinerInterface::DialectInlinerInterface;
34
35 static void registrationHook(MLIRContext *ctx, DialectImpl *dialect) {
36 dialect->template addInterfaces<InlinerImpl>();
37 if constexpr (sizeof...(RequiredDialects) != 0) {
38 ctx->loadDialect<RequiredDialects...>();
39 }
40 }
41};
42
43// Adapted from `mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp`
44struct FuncInlinerInterface
45 : public BaseInlinerInterface<
46 FuncInlinerInterface, function::FunctionDialect, cf::ControlFlowDialect> {
47 using BaseInlinerInterface::BaseInlinerInterface;
48
50 bool isLegalToInline(Operation *, Operation *, bool) const final { return true; }
51 bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final { return true; }
52 bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final { return true; }
53
54 void handleTerminator(Operation *op, Block *newDest) const final {
55 // Only return needs to be handled here. Replace the return with a branch to the dest.
56 // Note: This function is only called when there are multiple blocks in the region being
57 // inlined. In LLZK IR, that would only occur when the `cf` dialect is already used (since no
58 // LLZK dialect defines any kind of cross-block branching ops) so it's fine to add a
59 // `cf::BranchOp` here.
60 if (auto returnOp = llvm::dyn_cast<function::ReturnOp>(op)) {
61 OpBuilder builder(op);
62 builder.create<cf::BranchOp>(op->getLoc(), newDest, returnOp.getOperands());
63 op->erase();
64 }
65 }
66
67 void handleTerminator(Operation *op, ValueRange valuesToRepl) const final {
68 // ASSERT: when region contains a single block, terminator must be ReturnOp
69 assert(llvm::isa<function::ReturnOp>(op));
70
71 // Replace the values directly with the return operands.
72 auto returnOp = llvm::cast<function::ReturnOp>(op);
73 assert(returnOp.getNumOperands() == valuesToRepl.size());
74 for (const auto &it : llvm::enumerate(returnOp.getOperands())) {
75 valuesToRepl[it.index()].replaceAllUsesWith(it.value());
76 }
77 }
78};
79
80template <typename DialectImpl>
81struct FullyLegalForInlining
82 : public BaseInlinerInterface<FullyLegalForInlining<DialectImpl>, DialectImpl> {
83 using BaseInlinerInterface<FullyLegalForInlining<DialectImpl>, DialectImpl>::BaseInlinerInterface;
84
85 bool isLegalToInline(Operation *, Operation *, bool) const override { return true; }
86 bool isLegalToInline(Region *, Region *, bool, IRMapping &) const override { return true; }
87 bool isLegalToInline(Operation *op, Region *, bool, IRMapping &) const override { return true; }
88};
89
90} // namespace
91
92namespace llzk {
93
94void registerInliningExtensions(DialectRegistry &registry) {
95 registry.addExtension(FuncInlinerInterface::registrationHook);
96 registry.addExtension(FullyLegalForInlining<component::StructDialect>::registrationHook);
97 registry.addExtension(FullyLegalForInlining<constrain::ConstrainDialect>::registrationHook);
98 registry.addExtension(FullyLegalForInlining<undef::UndefDialect>::registrationHook);
99 registry.addExtension(FullyLegalForInlining<string::StringDialect>::registrationHook);
100 registry.addExtension(FullyLegalForInlining<polymorphic::PolymorphicDialect>::registrationHook);
101 registry.addExtension(FullyLegalForInlining<felt::FeltDialect>::registrationHook);
102 registry.addExtension(FullyLegalForInlining<global::GlobalDialect>::registrationHook);
103 registry.addExtension(FullyLegalForInlining<boolean::BoolDialect>::registrationHook);
104 registry.addExtension(FullyLegalForInlining<array::ArrayDialect>::registrationHook);
105}
106
107} // namespace llzk
void registerInliningExtensions(DialectRegistry &registry)