1//===-- LLZKTransformationPasses.td ------------------------*- tablegen -*-===//
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
8//===----------------------------------------------------------------------===//
10#ifndef LLZK_TRANSFORMATION_PASSES_TD
11#define LLZK_TRANSFORMATION_PASSES_TD
13include "llzk/Pass/PassBase.td"
15def RedundantReadAndWriteEliminationPass
16 : LLZKPass<"llzk-duplicate-read-write-elim"> {
17 let summary = "Remove redundant reads and writes";
19 Remove read and write operations to struct members and arrays that are redundant or unnecessary.
23def RedundantOperationEliminationPass : LLZKPass<"llzk-duplicate-op-elim"> {
24 let summary = "Remove redundant operations";
26 Remove llzk and arith dialect operations that produce the same results
27 as previously executed operations.
29 Pass should be run after `llzk-duplicate-read-write-elim` for maximum effect.
33def UnusedDeclarationEliminationPass
34 : LLZKPass<"llzk-unused-declaration-elim"> {
35 let summary = "Remove unused member and struct declarations";
37 Remove member and struct declarations that are unused within the current compilation
38 unit. Note that this pass may cause linking issues with external modules that
39 depend on any unused member and struct declarations from this compilation unit.
41 Pass should be run after `llzk-duplicate-read-write-elim`
42 and `llzk-duplicate-op-elim` for maximum effect.
44 let options = [Option<"removeStructs", "remove-structs", "bool",
45 /* default */ "false",
46 "Whether to remove unused struct definitions as well. "
47 "Requires module to declare a Main component, "
48 "otherwise all components will appear unused.">,
52def RemoveUnusedDiscardableAllocationsPass
53 : LLZKPass<"llzk-remove-unused-discardable-allocations"> {
54 let summary = "Remove unread discardable allocations and their dead stores";
56 Remove ops with the selected allocator operation name when they are marked with
57 `MemAlloc<DiscardableAllocationResource>`, the allocation has no reads, and every direct user is
58 a discardable allocation accessor that can be erased as a dead store.
60 let options = [Option<
61 "allocatorOpName", "allocator-op", "std::string",
63 "Operation name of the discardable allocator to remove">];
66def PolyLoweringPass : LLZKPass<"llzk-poly-lowering-pass"> {
68 "Lower the degree of all polynomial equations to a specified maximum";
70 Rewrites constraint expressions into an (observationally) equivalent system where the degree of
71 every polynomial is less than or equal to the specified maximum.
73 High-degree subexpressions are factored into auxiliary struct members. The pass also recurses
74 through degree-neutral roots such as `felt.add`, `felt.sub`, and `felt.neg`, so composite
75 equality operands and struct constrain call arguments satisfy their degree bounds.
77 This pass is best used as part of the `-llzk-full-poly-lowering` pipeline, which includes
78 additional cleanup passes to ensure correctness and optimal performance.
80 let options = [Option<"maxDegree", "max-degree", "unsigned",
82 "Maximum degree of constraint polynomials "
83 "(default 2, minimum 2)">,
87def InlineStructsPass : LLZKPass<"llzk-inline-structs"> {
88 let summary = "Inlines nested structs (i.e., subcomponents).";
90 This pass inlines nested structs (i.e., subcomponents) at struct-type members and at calls to the
91 subcomponent compute/constrain functions. Inlining decisions are guided by the call graph of
92 "constrain" functions.
94 The `max-merge-complexity` parameter can be used to limit the complexity of the resulting structs such
95 that a potential inlining will not take place if doing so would push the sum of constraint and
96 multiplications in the combined struct over the limit. The default value `0` indicates no limits
97 which means all structs will be inlined into the Main struct.
99 This pass should be run after `llzk-flatten` to ensure structs do not have template parameters
100 because structs with template parameters cannot (currently) be inlined. Inlining is also not
101 (currently) supported for subcomponent structs stored in an array-type member.
103 This pass also assumes that all subcomponents that are created by calling a struct "@compute"
104 function are ultimately written to exactly one member within the current struct.
106 let options = [Option<"maxComplexity", "max-merge-complexity", "uint64_t",
108 "Maximum allowed constraint+multiplications in merged "
109 "@constrain functions">,
113def ComputeConstrainToProductPass
114 : LLZKPass<"llzk-compute-constrain-to-product"> {
115 let summary = "Replace separate @compute and @constrain functions in a "
116 "struct with a single @product function";
117 let description = summary;
118 let options = [Option<"rootStruct", "root-struct", "std::string",
119 /* default */ "\"@Main\"",
120 "Root struct at which to start alignment "
121 "(default to `@Main`)">];
124def FuseProductLoopsPass : LLZKPass<"llzk-fuse-product-loops"> {
125 let summary = "Fuse matching witness/constraint loops in a @product function";
126 let description = summary;
129def EnforceNoMemberOverwritePass : LLZKPass<"llzk-enforce-no-overwrite"> {
130 let summary = "Checks that every struct member is written exactly once";
132 This pass currently reports an error if any struct member may not be written
133 exactly once (i.e. overwritten or left uninitialized), and does not
134 attempt to perform any repairs (e.g. SSA-ifying overwritten struct
135 members, or default-initializing unwritten members). This pass
136 overapproximates conditionals, and can result in false positives.
140def WhileToForPass : LLZKPass<"llzk-while-to-for"> {
142 "Converts scf.while loops to equivalent scf.for loops when possible";
144 "This pass identifies scf.while loops that have an "
145 "induction variable and a uniform step, and converts them "
146 "to equivalent scf.for loops, which are preferred by some "
147 "analyses. This pass may introduce some spurious felt/index casts which "
148 "should be cleaned up by --canonicalize.";
151#endif // LLZK_TRANSFORMATION_PASSES_TD