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