1//===-- Ops.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_BOOLEAN_OPS
11#define LLZK_BOOLEAN_OPS
13include "llzk/Dialect/Bool/IR/Dialect.td"
14include "llzk/Dialect/Bool/IR/Attrs.td"
15include "llzk/Dialect/Felt/IR/Types.td"
16include "llzk/Dialect/Array/IR/Types.td"
17include "llzk/Dialect/Function/IR/OpTraits.td"
18include "llzk/Dialect/Shared/OpsBase.td"
20include "mlir/IR/OpAsmInterface.td"
21include "mlir/IR/OpBase.td"
22include "mlir/IR/SymbolInterfaces.td"
23include "mlir/Interfaces/SideEffectInterfaces.td"
24include "mlir/Interfaces/ControlFlowInterfaces.td"
26//===------------------------------------------------------------------===//
28//===------------------------------------------------------------------===//
30class BoolDialectOp<string mnemonic, list<Trait> traits = []>
31 : Op<BoolDialect, mnemonic, traits>;
33class BoolBinaryOpBase<string mnemonic, Type resultType,
34 list<Trait> traits = []>
35 : BinaryOpBase<BoolDialect, mnemonic, resultType, traits> {
39class BoolUnaryOpBase<string mnemonic, Type resultType, list<Trait> traits = []>
40 : UnaryOpBase<BoolDialect, mnemonic, resultType, traits> {
44//===------------------------------------------------------------------===//
46//===------------------------------------------------------------------===//
49 : BoolBinaryOpBase<"and", I1, [NotFieldNative, Commutative]> {
50 let summary = "logical AND operator";
52 This operation computes the logical AND (i.e., conjunction) of two `i1` (i.e., boolean)
53 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
55 If used in a constraint expression, this operation can be converted to `a*b` on felt operands.
59def LLZK_OrBoolOp : BoolBinaryOpBase<"or", I1, [NotFieldNative, Commutative]> {
60 let summary = "logical OR operator";
62 This operation computes the logical OR (i.e., disjunction) of two `i1` (i.e., boolean)
63 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
65 If used in a constraint expression, this operation can be converted to `a+b - a*b` on felt operands.
70 : BoolBinaryOpBase<"xor", I1, [NotFieldNative, Commutative]> {
71 let summary = "logical XOR operator";
73 This operation computes the logical XOR (i.e., exclusive disjunction) of two `i1` (i.e., boolean)
74 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
76 If used in a constraint expression, this operation can be converted to `a+b - 2*a*b` on felt operands.
80def LLZK_NotBoolOp : BoolUnaryOpBase<"not", I1, [NotFieldNative]> {
81 let summary = "logical NOT operator";
83 This operation computes the logical NOT (i.e., negation) of an `i1` (i.e., boolean)
84 value as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
86 If used in a constraint expression, this operation can be converted to `1+a - 2*a` on felt operands.
90//===------------------------------------------------------------------===//
92//===------------------------------------------------------------------===//
96 "assert", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
97 let summary = "assertion operation";
99 This operation asserts that a given boolean value is true. Assertions are checked
100 statically when possible. If the condition evaluates to `true`, the assertion is
101 removed. If `false`, an error is reported. Otherwise, the assertion is preserved.
102 All assertions that appear in `constrain()` functions must evaluate statically
103 (i.e., they cannot depend on inputs to the circuit) else an error is reported.
105 Assertion without message:
107 %1 = bool.cmp lt(%a, %b)
111 Assertion with a message:
113 %1 = bool.cmp eq(%a, %b)
114 bool.assert %1, "expected equal values"
118 let arguments = (ins I1:$condition, OptionalAttr<StrAttr>:$msg);
120 let assemblyFormat = [{ $condition (`,` $msg^)? attr-dict }];
123// Match format of Index comparisons (for now)
125 : NaryOpBase<BoolDialect, "cmp",
126 LLZK_FeltType.builderCall, [Pure, TypesUnify<"lhs", "rhs">]> {
127 let summary = "compare field element values";
129 This operation takes two field element values and compares them according to the
130 comparison predicate and returns an `i1`. The following comparisons are supported:
135 - `le`: less than or equal
137 - `ge`: greater than or equal
139 The result is `1` if the comparison is true and `0` otherwise.
141 The inequality operators (lt, gt, le, ge) for the finite field elements
142 are defined by treating the field elements as integer values:
143 `f1 op f2` iff `int(f1) op int(f2)`
148 // Less than comparison.
149 %0 = bool.cmp lt(%a, %b)
151 // Greater than or equal comparison.
152 %1 = bool.cmp ge(%a, %b)
154 // Not equal comparison.
155 %2 = bool.cmp ne(%a, %b)
157 // Not equal comparison for felts in a specified field
158 %3 = bool.cmp ne(%c, %d) : !felt.type<"babybear">, !felt.type<"babybear">
162 let arguments = (ins LLZK_CmpPredicateAttr:$predicate, LLZK_FeltType:$lhs,
164 let results = (outs I1:$result);
165 let assemblyFormat = [{
166 `` $predicate `(` $lhs `,` $rhs `)`
167 `` custom<InferredOrParsedType>(type($lhs), "true")
168 `` custom<InferredOrParsedType>(type($rhs), "false") attr-dict
173class QuantifierOp<string mnemonic, string cond, list<Trait> traits = []>
174 : BoolDialectOp<mnemonic, traits#[NotFieldNative, Pure, SingleBlock]> {
175 let summary = mnemonic#" quantifier operation";
177 This operation applies a predicate to each element of the given sort.
178 Returns true iff the predicate is true for }]#cond#[{ of the sort.
180 Only LLZK arrays are supported as the sort type at the moment.
185 %0 = array.new %a, %b, %c : !array.type<3 x !felt.type>
186 %1 = bool.}]#mnemonic#[{ %e in %0 !array.type<3 x !felt.type> {
187 %2 = bool.cmp lt(%e, %c10)
193 let arguments = (ins LLZK_ArrayType:$sort);
194 let results = (outs I1:$result);
195 let regions = (region SizedRegion<1>:$region);
197 let hasCustomAssemblyFormat = 1;
201def ForAllOp : QuantifierOp<"forall", "all elements"> {}
203def ExistsOp : QuantifierOp<"exists", "at least one element"> {}
205def YieldOp : BoolDialectOp<"yield", [NotFieldNative, Terminator, ReturnLike,
206 ParentOneOf<["ForAllOp", "ExistsOp"]>]> {
207 let summary = "boolean yield operation";
209 This terminator operation yields the boolean value of the predicate inside the body of
210 `bool.forall` and `bool.exists` operations.
213 let arguments = (ins I1:$value);
214 let assemblyFormat = "$value attr-dict";
217#endif // LLZK_BOOLEAN_OPS