xref: /llvm-project/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td (revision 4425dfba6a1f394e958e94aa471a07bcf707136a)
1//===- PolynomialOps.td - Polynomial dialect ---------------*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef POLYNOMIAL_ATTRIBUTES
10#define POLYNOMIAL_ATTRIBUTES
11
12include "mlir/IR/BuiltinAttributes.td"
13include "mlir/Dialect/Polynomial/IR/PolynomialDialect.td"
14
15class Polynomial_Attr<string name, string attrMnemonic, list<Trait> traits = []>
16    : AttrDef<Polynomial_Dialect, name, traits> {
17  let mnemonic = attrMnemonic;
18}
19
20def Polynomial_IntPolynomialAttr : Polynomial_Attr<"IntPolynomial", "int_polynomial"> {
21  let summary = "an attribute containing a single-variable polynomial with integer coefficients";
22  let description = [{
23    A polynomial attribute represents a single-variable polynomial with integer
24    coefficients, which is used to define the modulus of a `RingAttr`, as well
25    as to define constants and perform constant folding for `polynomial` ops.
26
27    The polynomial must be expressed as a list of monomial terms, with addition
28    or subtraction between them. The choice of variable name is arbitrary, but
29    must be consistent across all the monomials used to define a single
30    attribute. The order of monomial terms is arbitrary, each monomial degree
31    must occur at most once.
32
33    Example:
34
35    ```mlir
36    #poly = #polynomial.int_polynomial<x**1024 + 1>
37    ```
38  }];
39  let parameters = (ins "::mlir::polynomial::IntPolynomial":$polynomial);
40  let hasCustomAssemblyFormat = 1;
41}
42
43def Polynomial_FloatPolynomialAttr : Polynomial_Attr<"FloatPolynomial", "float_polynomial"> {
44  let summary = "an attribute containing a single-variable polynomial with double precision floating point coefficients";
45  let description = [{
46    A polynomial attribute represents a single-variable polynomial with double
47    precision floating point coefficients.
48
49    The polynomial must be expressed as a list of monomial terms, with addition
50    or subtraction between them. The choice of variable name is arbitrary, but
51    must be consistent across all the monomials used to define a single
52    attribute. The order of monomial terms is arbitrary, each monomial degree
53    must occur at most once.
54
55    Example:
56
57    ```mlir
58    #poly = #polynomial.float_polynomial<0.5 x**7 + 1.5>
59    ```
60  }];
61  let parameters = (ins "FloatPolynomial":$polynomial);
62  let hasCustomAssemblyFormat = 1;
63}
64
65def Polynomial_TypedIntPolynomialAttr : Polynomial_Attr<
66    "TypedIntPolynomial", "typed_int_polynomial", [TypedAttrInterface]> {
67  let summary = "a typed int_polynomial";
68  let description = [{
69    Example:
70
71    ```mlir
72    !poly_ty = !polynomial.polynomial<ring=<coefficientType=i32>>
73    #poly = int<1 x**7 + 4> : !poly_ty
74    #poly_verbose = #polynomial.typed_int_polynomial<1 x**7 + 4> : !poly_ty
75    ```
76  }];
77  let parameters = (ins "::mlir::Type":$type, "::mlir::polynomial::IntPolynomialAttr":$value);
78  let assemblyFormat = "$value `:` $type";
79  let builders = [
80    AttrBuilderWithInferredContext<(ins "Type":$type,
81                                        "const IntPolynomial &":$value), [{
82      return $_get(
83        type.getContext(),
84        type,
85        IntPolynomialAttr::get(type.getContext(), value));
86    }]>,
87    AttrBuilderWithInferredContext<(ins "Type":$type,
88                                        "const Attribute &":$value), [{
89      return $_get(type.getContext(), type, ::llvm::cast<IntPolynomialAttr>(value));
90    }]>
91  ];
92  let extraClassDeclaration = [{
93    using ValueType = ::mlir::Attribute;
94  }];
95}
96
97def Polynomial_TypedFloatPolynomialAttr : Polynomial_Attr<
98    "TypedFloatPolynomial", "typed_float_polynomial", [TypedAttrInterface]> {
99  let summary = "a typed float_polynomial";
100  let description = [{
101    Example:
102
103    ```mlir
104    !poly_ty = !polynomial.polynomial<ring=<coefficientType=f32>>
105    #poly = float<1.4 x**7 + 4.5> : !poly_ty
106    #poly_verbose = #polynomial.typed_float_polynomial<1.4 x**7 + 4.5> : !poly_ty
107    ```
108  }];
109  let parameters = (ins "::mlir::Type":$type, "::mlir::polynomial::FloatPolynomialAttr":$value);
110  let assemblyFormat = "$value `:` $type";
111  let builders = [
112    AttrBuilderWithInferredContext<(ins "Type":$type,
113                                        "const FloatPolynomial &":$value), [{
114      return $_get(
115        type.getContext(),
116        type,
117        FloatPolynomialAttr::get(type.getContext(), value));
118    }]>,
119    AttrBuilderWithInferredContext<(ins "Type":$type,
120                                        "const Attribute &":$value), [{
121      return $_get(type.getContext(), type, ::llvm::cast<FloatPolynomialAttr>(value));
122    }]>
123  ];
124  let extraClassDeclaration = [{
125    using ValueType = ::mlir::Attribute;
126  }];
127}
128
129def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
130  let summary = "an attribute specifying a polynomial ring";
131  let description = [{
132    A ring describes the domain in which polynomial arithmetic occurs. The ring
133    attribute in `polynomial` represents the more specific case of polynomials
134    with a single indeterminate; whose coefficients can be represented by
135    another MLIR type (`coefficientType`); and, if the coefficient type is
136    integral, whose coefficients are taken modulo some statically known modulus
137    (`coefficientModulus`).
138
139    Additionally, a polynomial ring can specify a _polynomialModulus_, which converts
140    polynomial arithmetic to the analogue of modular integer arithmetic, where
141    each polynomial is represented as its remainder when dividing by the
142    modulus. For single-variable polynomials, an "polynomialModulus" is always specificed
143    via a single polynomial, which we call `polynomialModulus`.
144
145    An expressive example is polynomials with i32 coefficients, whose
146    coefficients are taken modulo `2**32 - 5`, with a polynomial modulus of
147    `x**1024 - 1`.
148
149    ```mlir
150    #poly_mod = #polynomial.int_polynomial<-1 + x**1024>
151    #ring = #polynomial.ring<coefficientType=i32,
152                             coefficientModulus=4294967291:i32,
153                             polynomialModulus=#poly_mod>
154
155    %0 = ... : polynomial.polynomial<#ring>
156    ```
157
158    In this case, the value of a polynomial is always "converted" to a
159    canonical form by applying repeated reductions by setting `x**1024 = 1`
160    and simplifying.
161
162    The coefficient and polynomial modulus parameters are optional, and the
163    coefficient modulus is only allowed if the coefficient type is integral.
164
165    The coefficient modulus, if specified, should be positive and not larger
166    than `2 ** width(coefficientType)`.
167
168    If the coefficient modulus is not specified, the handling of coefficients
169    overflows is determined by subsequent lowering passes, which may choose to
170    wrap around or widen the overflow at their discretion.
171
172    Note that coefficient modulus is contained in `i64` by default, which is signed.
173    To specify a 64 bit number without intepreting it as a negative number, its container
174    type should be manually specified like `coefficientModulus=18446744073709551615:i128`.
175  }];
176
177  let parameters = (ins
178    "Type": $coefficientType,
179    OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus,
180    OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus
181  );
182  let genVerifyDecl = 1;
183  let assemblyFormat = "`<` struct(params) `>`";
184  let builders = [
185    AttrBuilderWithInferredContext<
186        (ins "::mlir::Type":$coefficientTy,
187              CArg<"::mlir::IntegerAttr", "nullptr"> :$coefficientModulusAttr,
188              CArg<"::mlir::polynomial::IntPolynomialAttr", "nullptr"> :$polynomialModulusAttr), [{
189      return $_get(
190        coefficientTy.getContext(),
191        coefficientTy,
192        coefficientModulusAttr,
193        polynomialModulusAttr);
194    }]>,
195  ];
196}
197
198def Polynomial_PrimitiveRootAttr: Polynomial_Attr<"PrimitiveRoot", "primitive_root"> {
199  let summary = "an attribute containing an integer and its degree as a root of unity";
200  let description = [{
201    A primitive root attribute stores an integer root `value` and an integer
202    `degree`, corresponding to a primitive root of unity of the given degree in
203    an unspecified ring.
204
205    This is used as an attribute on `polynomial.ntt` and `polynomial.intt` ops
206    to specify the root of unity used in lowering the transform.
207
208    Example:
209
210    ```mlir
211    #poly = #polynomial.primitive_root<value=123 : i32, degree : 7 index>
212    ```
213  }];
214  let parameters = (ins
215    "::mlir::IntegerAttr":$value,
216    "::mlir::IntegerAttr":$degree
217  );
218  let assemblyFormat = "`<` struct(params) `>`";
219}
220
221
222#endif // POLYNOMIAL_ATTRIBUTES
223