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/Function/IR/OpTraits.td"
17include "llzk/Dialect/Shared/OpsBase.td"
19include "mlir/IR/OpAsmInterface.td"
20include "mlir/IR/OpBase.td"
21include "mlir/IR/SymbolInterfaces.td"
22include "mlir/Interfaces/SideEffectInterfaces.td"
24//===------------------------------------------------------------------===//
26//===------------------------------------------------------------------===//
28class BoolDialectOp<string mnemonic, list<Trait> traits = []>
29 : Op<BoolDialect, mnemonic, traits>;
31class BoolBinaryOpBase<string mnemonic, Type resultType,
32 list<Trait> traits = []>
33 : BinaryOpBase<BoolDialect, mnemonic, resultType, traits> {
37class BoolUnaryOpBase<string mnemonic, Type resultType, list<Trait> traits = []>
38 : UnaryOpBase<BoolDialect, mnemonic, resultType, traits> {
42//===------------------------------------------------------------------===//
44//===------------------------------------------------------------------===//
47 : BoolBinaryOpBase<"and", I1, [NotFieldNative, Commutative]> {
48 let summary = "logical AND operator";
50 This operation computes the logical AND (i.e., conjunction) of two `i1` (i.e., boolean)
51 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
53 If used in a constraint expression, this operation can be converted to `a*b` on felt operands.
57def LLZK_OrBoolOp : BoolBinaryOpBase<"or", I1, [NotFieldNative, Commutative]> {
58 let summary = "logical OR operator";
60 This operation computes the logical OR (i.e., disjunction) of two `i1` (i.e., boolean)
61 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
63 If used in a constraint expression, this operation can be converted to `a+b - a*b` on felt operands.
68 : BoolBinaryOpBase<"xor", I1, [NotFieldNative, Commutative]> {
69 let summary = "logical XOR operator";
71 This operation computes the logical XOR (i.e., exclusive disjunction) of two `i1` (i.e., boolean)
72 values as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
74 If used in a constraint expression, this operation can be converted to `a+b - 2*a*b` on felt operands.
78def LLZK_NotBoolOp : BoolUnaryOpBase<"not", I1, [NotFieldNative]> {
79 let summary = "logical NOT operator";
81 This operation computes the logical NOT (i.e., negation) of an `i1` (i.e., boolean)
82 value as an `i1` value. The result is `1` if the operation is true and `0` otherwise.
84 If used in a constraint expression, this operation can be converted to `1+a - 2*a` on felt operands.
88//===------------------------------------------------------------------===//
90//===------------------------------------------------------------------===//
94 "assert", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
95 let summary = "assertion operation";
97 This operation asserts that a given boolean value is true. Assertions are checked
98 statically when possible. If the condition evaluates to `true`, the assertion is
99 removed. If `false`, an error is reported. Otherwise, the assertion is preserved.
100 All assertions that appear in `constrain()` functions must evaluate statically
101 (i.e., they cannot depend on inputs to the circuit) else an error is reported.
103 Assertion without message:
105 %1 = bool.cmp lt(%a, %b)
109 Assertion with a message:
111 %1 = bool.cmp eq(%a, %b)
112 bool.assert %1, "expected equal values"
116 let arguments = (ins I1:$condition, OptionalAttr<StrAttr>:$msg);
118 let assemblyFormat = [{ $condition (`,` $msg^)? attr-dict }];
121// Match format of Index comparisons (for now)
123 : NaryOpBase<BoolDialect, "cmp",
124 LLZK_FeltType.builderCall, [Pure, TypesUnify<"lhs", "rhs">]> {
125 let summary = "compare field element values";
127 This operation takes two field element values and compares them according to the
128 comparison predicate and returns an `i1`. The following comparisons are supported:
133 - `le`: less than or equal
135 - `ge`: greater than or equal
137 The result is `1` if the comparison is true and `0` otherwise.
139 The inequality operators (lt, gt, le, ge) for the finite field elements
140 are defined by treating the field elements as integer values:
141 `f1 op f2` iff `int(f1) op int(f2)`
146 // Less than comparison.
147 %0 = bool.cmp lt(%a, %b)
149 // Greater than or equal comparison.
150 %1 = bool.cmp ge(%a, %b)
152 // Not equal comparison.
153 %2 = bool.cmp ne(%a, %b)
155 // Not equal comparison for felts in a specified field
156 %3 = bool.cmp ne(%c, %d) : !felt.type<"babybear">, !felt.type<"babybear">
160 let arguments = (ins LLZK_CmpPredicateAttr:$predicate, LLZK_FeltType:$lhs,
162 let results = (outs I1:$result);
163 let assemblyFormat = [{
164 `` $predicate `(` $lhs `,` $rhs `)`
165 `` custom<InferredOrParsedType>(type($lhs), "true")
166 `` custom<InferredOrParsedType>(type($rhs), "false") attr-dict
171#endif // LLZK_BOOLEAN_OPS