LLZK 2.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Ops.td
Go to the documentation of this file.
1//===-- Ops.td ---------------------------------------------*- tablegen -*-===//
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
10#ifndef LLZK_OPS
11#define LLZK_OPS
12
13include "llzk/Dialect/LLZK/IR/Dialect.td"
14include "llzk/Dialect/LLZK/IR/Attrs.td" // must be included to generate docs
15include "llzk/Dialect/Shared/Types.td"
16
17include "mlir/IR/OpAsmInterface.td"
18include "mlir/IR/OpBase.td"
19include "mlir/Interfaces/SideEffectInterfaces.td"
20
21//===------------------------------------------------------------------===//
22// Op Classes
23//===------------------------------------------------------------------===//
24
25class LLZKDialectOp<string mnemonic, list<Trait> traits = []>
26 : Op<LLZKDialect, mnemonic, traits>;
27
28def LLZK_NonDetOp
29 : LLZKDialectOp<"nondet", [AlwaysSpeculatable,
30 DeclareOpInterfaceMethods<
31 OpAsmOpInterface, ["getAsmResultNames"]>]> {
32 let summary = "uninitialized variable";
33 let description = [{
34 This operation produces an SSA variable of the specified type but with
35 nondeterministic value.
36
37 This op can be used in `@constrain()` functions in place of expressions that
38 cannot be included in constraints. It may also be generated for a frontend
39 language that supports uninitialized variables and can also be introduced by
40 the `llzk-array-to-scalar` pass if there is a read from an array index
41 that was not dominated by an earlier write to that same index.
42
43 Example:
44
45 ```llzk
46 %0 = llzk.nondet : !felt.type
47 ```
48
49 Note that `llzk.nondet` does not have the `ConstantLike` or `NoMemoryEffect`
50 traits because different SSA variables initialized with `llzk.nondet` may be
51 constrained in different ways so they cannot be treated as identical values.
52 However, it does have the `AlwaysSpeculatable` trait to denote that it is
53 free to move, hoist, and sick without changing the semantics.
54
55 Example:
56
57 ```llzk
58 %0 = llzk.nondet : !felt.type
59 %1 = llzk.nondet : !felt.type
60 %c1 = felt.const 1
61 constrain.eq %0, %c1 : !felt.type
62
63 %m = struct.readm %self[@m] : !struct.type<@S>, !felt.type
64 constrain.eq %m, %1 : !felt.type
65 ```
66
67 In the above example, `%m` is effectively unconstrained, as it is only constrained
68 to the nondet value `%1`. However, if `%0` and `%1` were treated as pure constants,
69 `%0` and `%1` could be combined, resulting in:
70
71 ```llzk
72 %0 = llzk.nondet : !felt.type
73 %c1 = felt.const 1
74 constrain.eq %0, %c1 : !felt.type
75
76 %m = struct.readm %self[@m] : !struct.type<@S>, !felt.type
77 constrain.eq %m, %0 : !felt.type
78 ```
79
80 This transformation would constrain `%m` to be exactly equal to 1, thus changing
81 the semantics of the circuit.
82 }];
83
84 let results = (outs AnyLLZKType:$res);
85 let assemblyFormat = [{ `:` type($res) attr-dict }];
86 let hasCanonicalizer = 1;
87}
88
89#endif // LLZK_OPS