Skip to content

Commit 4425dfb

Browse files
[mlir][polynomial] Add and verify constraints of coefficientModulus for ringAttr (#111016)
Currently the semantic of coefficientModulus is unclear and a lowering of it faces uncertainty, for example, google/heir#995 (comment) Also, it lacks a verifier which should conform to the definition in the document. This PR tries to further define the semantic of coefficientModulus and adds a verifier for it. Cc @j2kun for review and suggestions.
1 parent 4e5f8a8 commit 4425dfb

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td

+12
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,25 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
161161

162162
The coefficient and polynomial modulus parameters are optional, and the
163163
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`.
164175
}];
165176

166177
let parameters = (ins
167178
"Type": $coefficientType,
168179
OptionalParameter<"::mlir::IntegerAttr">: $coefficientModulus,
169180
OptionalParameter<"::mlir::polynomial::IntPolynomialAttr">: $polynomialModulus
170181
);
182+
let genVerifyDecl = 1;
171183
let assemblyFormat = "`<` struct(params) `>`";
172184
let builders = [
173185
AttrBuilderWithInferredContext<

mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,34 @@ Attribute FloatPolynomialAttr::parse(AsmParser &parser, Type type) {
203203
return FloatPolynomialAttr::get(parser.getContext(), result.value());
204204
}
205205

206+
LogicalResult
207+
RingAttr::verify(function_ref<mlir::InFlightDiagnostic()> emitError,
208+
Type coefficientType, IntegerAttr coefficientModulus,
209+
IntPolynomialAttr polynomialModulus) {
210+
if (coefficientModulus) {
211+
auto coeffIntType = llvm::dyn_cast<IntegerType>(coefficientType);
212+
if (!coeffIntType) {
213+
return emitError() << "coefficientModulus specified but coefficientType "
214+
"is not integral";
215+
}
216+
APInt coeffModValue = coefficientModulus.getValue();
217+
if (coeffModValue == 0) {
218+
return emitError() << "coefficientModulus should not be 0";
219+
}
220+
if (coeffModValue.slt(0)) {
221+
return emitError() << "coefficientModulus should be positive";
222+
}
223+
auto coeffModWidth = (coeffModValue - 1).getActiveBits();
224+
auto coeffWidth = coeffIntType.getWidth();
225+
if (coeffModWidth > coeffWidth) {
226+
return emitError() << "coefficientModulus needs bit width of "
227+
<< coeffModWidth
228+
<< " but coefficientType can only contain "
229+
<< coeffWidth << " bits";
230+
}
231+
}
232+
return success();
233+
}
234+
206235
} // namespace polynomial
207236
} // namespace mlir

mlir/test/Dialect/Polynomial/attributes.mlir

+34
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,37 @@
3737
// expected-error@below {{failed to parse Polynomial_RingAttr parameter 'coefficientModulus' which is to be a `::mlir::IntegerAttr`}}
3838
// expected-error@below {{expected attribute value}}
3939
#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=x, polynomialModulus=#my_poly>
40+
41+
// -----
42+
43+
// expected-error@below {{coefficientModulus specified but coefficientType is not integral}}
44+
#ring1 = #polynomial.ring<coefficientType=f32, coefficientModulus=17>
45+
46+
// -----
47+
48+
// expected-error@below {{coefficientModulus should not be 0}}
49+
#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=0>
50+
51+
// -----
52+
53+
// expected-error@below {{coefficientModulus should be positive}}
54+
#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=-1>
55+
56+
// -----
57+
58+
// expected-error@below {{coefficientModulus needs bit width of 33 but coefficientType can only contain 32 bits}}
59+
#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=4294967297>
60+
61+
// -----
62+
63+
#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=4294967296>
64+
65+
// -----
66+
67+
// expected-error@below {{coefficientModulus should be positive}}
68+
#ring1 = #polynomial.ring<coefficientType=i64, coefficientModulus=18446744073709551615>
69+
70+
// -----
71+
72+
// unfortunately, coefficientModulus of 64bit should be contained in larger type
73+
#ring1 = #polynomial.ring<coefficientType=i64, coefficientModulus=18446744073709551615 : i128>

0 commit comments

Comments
 (0)