[Mlir-commits] [mlir] Add a polynomial dialect shell, attributes, and types (PR #72081)

Jeremy Kun llvmlistbot at llvm.org
Fri Apr 12 14:53:57 PDT 2024


https://github.com/j2kun updated https://github.com/llvm/llvm-project/pull/72081

>From e877dbf4981123c494bb20079cbc5685e185df08 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Sat, 4 Nov 2023 10:05:33 -0700
Subject: [PATCH 01/44] polynomial: add dialect shell, attrs, and types

---
 mlir/include/mlir/Dialect/CMakeLists.txt      |   1 +
 .../mlir/Dialect/Polynomial/CMakeLists.txt    |   1 +
 .../mlir/Dialect/Polynomial/IR/CMakeLists.txt |  19 ++
 .../mlir/Dialect/Polynomial/IR/Polynomial.h   | 157 +++++++++++++
 .../Polynomial/IR/PolynomialAttributes.h      |  18 ++
 .../Polynomial/IR/PolynomialAttributes.td     |  81 +++++++
 .../Dialect/Polynomial/IR/PolynomialDialect.h |  19 ++
 .../Polynomial/IR/PolynomialDialect.td        |  54 +++++
 .../Dialect/Polynomial/IR/PolynomialOps.h     |  21 ++
 .../Dialect/Polynomial/IR/PolynomialOps.td    |  40 ++++
 .../Dialect/Polynomial/IR/PolynomialTypes.h   |  17 ++
 .../Dialect/Polynomial/IR/PolynomialTypes.td  |  32 +++
 mlir/include/mlir/InitAllDialects.h           |   2 +
 mlir/lib/Dialect/CMakeLists.txt               |   1 +
 mlir/lib/Dialect/Polynomial/CMakeLists.txt    |   1 +
 mlir/lib/Dialect/Polynomial/IR/CMakeLists.txt |  21 ++
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp |  97 ++++++++
 .../Polynomial/IR/PolynomialAttributes.cpp    | 217 ++++++++++++++++++
 .../Dialect/Polynomial/IR/PolynomialDetail.h  |  65 ++++++
 .../Polynomial/IR/PolynomialDialect.cpp       |  47 ++++
 .../Dialect/Polynomial/IR/PolynomialOps.cpp   |  16 ++
 mlir/test/Dialect/Polynomial/types.td         |  19 ++
 22 files changed, 946 insertions(+)
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/CMakeLists.txt
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
 create mode 100644 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
 create mode 100644 mlir/lib/Dialect/Polynomial/CMakeLists.txt
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/CMakeLists.txt
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
 create mode 100644 mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
 create mode 100644 mlir/test/Dialect/Polynomial/types.td

diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index 2da79011fa26a3..4bd7f12fabf7ba 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -28,6 +28,7 @@ add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
 add_subdirectory(PDL)
 add_subdirectory(PDLInterp)
+add_subdirectory(Polynomial)
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/include/mlir/Dialect/Polynomial/CMakeLists.txt b/mlir/include/mlir/Dialect/Polynomial/CMakeLists.txt
new file mode 100644
index 00000000000000..f33061b2d87cff
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
new file mode 100644
index 00000000000000..3719fda2aec6d4
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_TARGET_DEFINITIONS PolynomialOps.td)
+mlir_tablegen(PolynomialDialect.cpp.inc -gen-dialect-defs -dialect=polynomial)
+mlir_tablegen(PolynomialDialect.h.inc -gen-dialect-decls -dialect=polynomial)
+add_public_tablegen_target(MLIRPolynomialDialectIncGen)
+
+mlir_tablegen(PolynomialAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=polynomial)
+mlir_tablegen(PolynomialAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=polynomial)
+mlir_tablegen(PolynomialOps.cpp.inc -gen-op-defs)
+mlir_tablegen(PolynomialOps.h.inc -gen-op-decls)
+mlir_tablegen(PolynomialTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=polynomial)
+mlir_tablegen(PolynomialTypes.h.inc -gen-typedef-decls -typedefs-dialect=polynomial)
+add_public_tablegen_target(MLIRPolynomialAttributesIncGen)
+add_public_tablegen_target(MLIRPolynomialOpsIncGen)
+add_public_tablegen_target(MLIRPolynomialTypesIncGen)
+add_dependencies(mlir-headers MLIRPolynomialOpsIncGen)
+
+add_mlir_doc(PolynoialOps PolynoialOps Dialects/ -gen-dialect-doc -dialect polynomial)
+add_mlir_doc(PolynomialAttributes PolynomialAttributes Dialects/ -gen-attrdef-doc)
+add_mlir_doc(PolynomialTypes PolynomialTypes Dialects/ -gen-typedef-doc)
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
new file mode 100644
index 00000000000000..757ee61ec8c7a2
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -0,0 +1,157 @@
+//===- Polynomial.h - A storage class for polynomial types --------*- C++-*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+
+#include <utility>
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/Hashing.h"
+
+namespace mlir {
+
+class MLIRContext;
+
+namespace polynomial {
+
+// This restricts statically defined polynomials to have at most 64-bit
+// coefficients. This may be relaxed in the future, but it seems unlikely one
+// would want to specify 128-bit polynomials statically in the source code.
+constexpr unsigned apintBitWidth = 64;
+
+namespace detail {
+struct PolynomialStorage;
+} // namespace detail
+
+class Monomial {
+public:
+  Monomial(int64_t coeff, uint64_t expo)
+      : coefficient(apintBitWidth, coeff), exponent(apintBitWidth, expo) {}
+
+  Monomial(APInt coeff, APInt expo)
+      : coefficient(std::move(coeff)), exponent(std::move(expo)) {}
+
+  Monomial() : coefficient(apintBitWidth, 0), exponent(apintBitWidth, 0) {}
+
+  bool operator==(const Monomial &other) const {
+    return other.coefficient == coefficient && other.exponent == exponent;
+  }
+  bool operator!=(const Monomial &other) const {
+    return other.coefficient != coefficient || other.exponent != exponent;
+  }
+
+  /// Monomials are ordered by exponent.
+  bool operator<(const Monomial &other) const {
+    return (exponent.ult(other.exponent));
+  }
+
+  // Prints polynomial to 'os'.
+  void print(raw_ostream &os) const;
+
+  friend ::llvm::hash_code hash_value(Monomial arg);
+
+public:
+  APInt coefficient;
+
+  // Always unsigned
+  APInt exponent;
+};
+
+/// A single-variable polynomial with integer coefficients. Polynomials are
+/// immutable and uniqued.
+///
+/// Eg: x^1024 + x + 1
+///
+/// The symbols used as the polynomial's indeterminate don't matter, so long as
+/// it is used consistently throughout the polynomial.
+class Polynomial {
+public:
+  using ImplType = detail::PolynomialStorage;
+
+  constexpr Polynomial() = default;
+  explicit Polynomial(ImplType *terms) : terms(terms) {}
+
+  static Polynomial fromMonomials(ArrayRef<Monomial> monomials,
+                                  MLIRContext *context);
+  /// Returns a polynomial with coefficients given by `coeffs`
+  static Polynomial fromCoefficients(ArrayRef<int64_t> coeffs,
+                                     MLIRContext *context);
+
+  MLIRContext *getContext() const;
+
+  explicit operator bool() const { return terms != nullptr; }
+  bool operator==(Polynomial other) const { return other.terms == terms; }
+  bool operator!=(Polynomial other) const { return !(other.terms == terms); }
+
+  // Prints polynomial to 'os'.
+  void print(raw_ostream &os) const;
+  void print(raw_ostream &os, const std::string &separator,
+             const std::string &exponentiation) const;
+  void dump() const;
+
+  // Prints polynomial so that it can be used as a valid identifier
+  std::string toIdentifier() const;
+
+  // A polynomial's terms are canonically stored in order of increasing degree.
+  ArrayRef<Monomial> getTerms() const;
+
+  unsigned getDegree() const;
+
+  friend ::llvm::hash_code hash_value(Polynomial arg);
+
+private:
+  ImplType *terms{nullptr};
+};
+
+// Make Polynomial hashable.
+inline ::llvm::hash_code hash_value(Polynomial arg) {
+  return ::llvm::hash_value(arg.terms);
+}
+
+inline ::llvm::hash_code hash_value(Monomial arg) {
+  return ::llvm::hash_value(arg.coefficient) ^ ::llvm::hash_value(arg.exponent);
+}
+
+inline raw_ostream &operator<<(raw_ostream &os, Polynomial polynomial) {
+  polynomial.print(os);
+  return os;
+}
+
+} // namespace polynomial
+} // namespace mlir
+
+namespace llvm {
+
+// Polynomials hash just like pointers
+template <>
+struct DenseMapInfo<mlir::polynomial::Polynomial> {
+  static mlir::polynomial::Polynomial getEmptyKey() {
+    auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
+    return mlir::polynomial::Polynomial(
+        static_cast<mlir::polynomial::Polynomial::ImplType *>(pointer));
+  }
+  static mlir::polynomial::Polynomial getTombstoneKey() {
+    auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
+    return mlir::polynomial::Polynomial(
+        static_cast<mlir::polynomial::Polynomial::ImplType *>(pointer));
+  }
+  static unsigned getHashValue(mlir::polynomial::Polynomial val) {
+    return mlir::polynomial::hash_value(val);
+  }
+  static bool isEqual(mlir::polynomial::Polynomial lhs,
+                      mlir::polynomial::Polynomial rhs) {
+    return lhs == rhs;
+  }
+};
+
+} // namespace llvm
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
new file mode 100644
index 00000000000000..6d6941cf6bdcc6
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
@@ -0,0 +1,18 @@
+//===- PolynomialAttributes.h - Attributes for the Polynomial dialect -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
+
+#include "Polynomial.h"
+#include "PolynomialDialect.h"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h.inc"
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
new file mode 100644
index 00000000000000..0e4f2f182ede1f
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -0,0 +1,81 @@
+//===- PolynomialAttributes.td - Attribute definitions for the polynomial dialect ------*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLYNOMIAL_ATTRIBUTES
+#define POLYNOMIAL_ATTRIBUTES
+
+include "PolynomialDialect.td"
+include "mlir/IR/BuiltinAttributes.td"
+include "mlir/IR/OpBase.td"
+
+class Polynomial_Attr<string name, string attrMnemonic, list<Trait> traits = []>
+    : AttrDef<Polynomial_Dialect, name, traits> {
+  let mnemonic = attrMnemonic;
+}
+
+def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> {
+  let summary = "An attribute containing a single-variable polynomial.";
+  let description = [{
+     #poly = #polynomial.poly<x**1024 + 1>
+  }];
+
+  let parameters = (ins "Polynomial":$polynomial);
+
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "Polynomial":$polynomial), [{
+      return $_get(polynomial.getContext(), polynomial);
+    }]>
+  ];
+
+  let skipDefaultBuilders = 1;
+  let hasCustomAssemblyFormat = 1;
+}
+
+def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
+  let summary = "An attribute specifying a polynomial ring.";
+  let description = [{
+    A ring describes the domain in which polynomial arithmetic occurs. The ring
+    attribute in `polynomial` represents the more specific case of polynomials
+    with a single indeterminate; whose coefficients can be represented by
+    another MLIR type (`ctype`); and, if the coefficient type is integral,
+    whose coefficients are taken modulo some statically known modulus (`cmod`).
+
+    Additionally, a polynomial ring can specify an _ideal_, which converts
+    polynomial arithmetic to the analogue of modular integer arithmetic, where
+    each polynomial is represented as its remainder when dividing by the
+    modulus. For single-variable polynomials, an "ideal" is always specificed
+    via a single polynomial, which we call `polynomialModulus`.
+
+    An expressive example is polynomials with i32 coefficients, whose
+    coefficients are taken modulo `2**32 - 5`, with a polynomial modulus of
+    `x**1024 - 1`.
+
+    ```
+    #poly_mod = #polynomial.polynomial<-1 + x**1024>
+    #ring = #polynomial.ring<ctype=i32, cmod=4294967291, ideal=#poly_mod>
+
+    %0 = ... : polynomial.polynomial<#ring>
+    ```
+
+    In this case, the value of a polynomial is always ``converted'' to a
+    canonical form by applying repeated reductions by setting `x**1024 = 1`
+    and simplifying.
+
+    The coefficient and polynomial modulus parameters are optional, and the
+    coefficient modulus is only allowed if the coefficient type is integral.
+  }];
+
+  let parameters = (ins
+    Builtin_TypeAttr: $coefficientType,
+    OptionalParameter<"std::optional<IntegerAttr>">: $coefficientModulus,
+    OptionalParameter<"std::optional<PolynomialAttr>">: $polynomialModulus
+  );
+
+  let hasCustomAssemblyFormat = 1;
+}
+
+#endif // POLYNOMIAL_ATTRIBUTES
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
new file mode 100644
index 00000000000000..50538126c0372f
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
@@ -0,0 +1,19 @@
+//===- PolynomialDialect.h - The Polynomial dialect -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
+
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/DialectImplementation.h"
+
+// Generated headers (block clang-format from messing up order)
+#include "mlir/Dialect/Polynomial/IR/PolynomialDialect.h.inc"
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
new file mode 100644
index 00000000000000..d664a7c6159fdc
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
@@ -0,0 +1,54 @@
+//===- PolynomialDialect.td - Dialect definition for the polynomial dialect ------*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLYNOMIAL_DIALECT
+#define POLYNOMIAL_DIALECT
+
+include "mlir/IR/OpBase.td"
+
+def Polynomial_Dialect : Dialect {
+  let name = "polynomial";
+  let cppNamespace = "::mlir::polynomial";
+  let description = [{
+    The Polynomial dialect defines single-variable polynomial types and
+    operations.
+
+    The simplest use of `polynomial` is to represent mathematical operations in
+    a polynomial ring `R[x]`, where `R` is another MLIR type like `i32`.
+
+    More generally, this dialect supports representing polynomial operations in a
+    quotient ring `R[X]/(f(x))` for some statically fixed polynomial `f(x)`.
+    Two polyomials `p(x), q(x)` are considered equal in this ring if they have the
+    same remainder when dividing by `f(x)`. When a modulus is given, ring operations
+    are performed with reductions modulo `f(x)` and relative to the coefficient ring
+    `R`.
+
+    Examples:
+
+    ```mlir
+    // A constant polynomial in a ring with i32 coefficients and no polynomial modulus
+    #ring = #polynomial.ring<ctype=i32>
+    %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
+
+    // A constant polynomial in a ring with i32 coefficients, modulo (x^1024 + 1)
+    #modulus = #polynomial.polynomial<1 + x**1024>
+    #ring = #polynomial.ring<ctype=i32, ideal=#modulus>
+    %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
+
+    // A constant polynomial in a ring with i32 coefficients, with a polynomial
+    // modulus of (x^1024 + 1) and a coefficient modulus of 17.
+    #modulus = #polynomial.polynomial<1 + x**1024>
+    #ring = #polynomial.ring<ctype=i32, cmod=17, ideal=#modulus>
+    %a = polynomial.constant <1 + x**2 - 3x**3> : polynomial.polynomial<#ring>
+    ```
+  }];
+
+  let useDefaultTypePrinterParser = 1;
+  let useDefaultAttributePrinterParser = 1;
+}
+
+#endif // POLYNOMIAL_DIALECT
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
new file mode 100644
index 00000000000000..49491c9bdc8ad3
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
@@ -0,0 +1,21 @@
+//===- PolynomialOps.h - Ops for the Polynomial dialect -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
+
+#include "PolynomialDialect.h"
+#include "PolynomialTypes.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/Interfaces/InferTypeOpInterface.h"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialOps.h.inc"
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
new file mode 100644
index 00000000000000..6ead46c953faf7
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
@@ -0,0 +1,40 @@
+//===- PolynomialOps.td - Polynomial op definitions --------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLYNOMIAL_OPS
+#define POLYNOMIAL_OPS
+
+include "PolynomialDialect.td"
+include "PolynomialTypes.td"
+include "mlir/Interfaces/InferTypeOpInterface.td"
+include "mlir/Interfaces/SideEffectInterfaces.td"
+
+// Base class for polynomial dialect ops. Ops in this dialect have no side
+// effects.
+class Polynomial_Op<string mnemonic, list<Trait> traits = []> :
+    Op<Polynomial_Dialect, mnemonic, traits # [Pure]>;
+
+// Base class for unary polynomial operations.
+class Polynomial_UnaryOp<string mnemonic, list<Trait> traits = []> :
+    Polynomial_Op<mnemonic, traits # [SameOperandsAndResultType]> {
+  let arguments = (ins Polynomial_PolynomialType:$operand);
+  let results = (outs Polynomial_PolynomialType:$result);
+
+  let assemblyFormat = "$operand attr-dict `:` qualified(type($result))";
+}
+
+// Base class for binary polynomial operations.
+class Polynomial_BinaryOp<string mnemonic, list<Trait> traits = []> :
+    Polynomial_Op<mnemonic, traits # [SameOperandsAndResultType]> {
+  let arguments = (ins Polynomial_PolynomialType:$lhs, Polynomial_PolynomialType:$rhs);
+  let results = (outs Polynomial_PolynomialType:$result);
+
+  let assemblyFormat = "$lhs `,` $rhs attr-dict `:` qualified(type($result))";
+}
+
+#endif // POLYNOMIAL_OPS
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
new file mode 100644
index 00000000000000..c030de2d6c77fb
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
@@ -0,0 +1,17 @@
+//===- PolynomialTypes.h - Types for the Polynomial dialect -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
+
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
+#include "mlir/Dialect/Polynomial/IR/PolynomialDialect.h"
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialTypes.h.inc"
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
new file mode 100644
index 00000000000000..b480c9ea714471
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
@@ -0,0 +1,32 @@
+//===- PolynomialTypes.td - Type definitions for polynomial dialect ------*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef POLYNOMIAL_TYPES
+#define POLYNOMIAL_TYPES
+
+include "PolynomialAttributes.td"
+include "PolynomialDialect.td"
+include "mlir/IR/BuiltinAttributes.td"
+include "mlir/IR/OpBase.td"
+
+class Polynomial_Type<string name, string typeMnemonic>
+    : TypeDef<Polynomial_Dialect, name> {
+  let mnemonic = typeMnemonic;
+}
+
+def Polynomial_PolynomialType : Polynomial_Type<"Polynomial", "polynomial"> {
+  let summary = "An element of a polynomial ring.";
+
+  let description = [{
+    A type for polynomials in a polynomial quotient ring.
+  }];
+
+  let parameters = (ins Polynomial_RingAttr:$ring);
+  let assemblyFormat = "`<` $ring `>`";
+}
+
+#endif // POLYNOMIAL_TYPES
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index c558dc53cc7fac..c4d788cf8ed316 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -61,6 +61,7 @@
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "mlir/Dialect/PDL/IR/PDL.h"
 #include "mlir/Dialect/PDLInterp/IR/PDLInterp.h"
+#include "mlir/Dialect/Polynomial/IR/PolynomialDialect.h"
 #include "mlir/Dialect/Quant/QuantOps.h"
 #include "mlir/Dialect/SCF/IR/SCF.h"
 #include "mlir/Dialect/SCF/IR/ValueBoundsOpInterfaceImpl.h"
@@ -131,6 +132,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
                   omp::OpenMPDialect,
                   pdl::PDLDialect,
                   pdl_interp::PDLInterpDialect,
+                  polynomial::PolynomialDialect,
                   quant::QuantizationDialect,
                   ROCDL::ROCDLDialect,
                   scf::SCFDialect,
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index b1ba5a3bc8817d..a324ce7f9b19f7 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -28,6 +28,7 @@ add_subdirectory(OpenACCMPCommon)
 add_subdirectory(OpenMP)
 add_subdirectory(PDL)
 add_subdirectory(PDLInterp)
+add_subdirectory(Polynomial)
 add_subdirectory(Quant)
 add_subdirectory(SCF)
 add_subdirectory(Shape)
diff --git a/mlir/lib/Dialect/Polynomial/CMakeLists.txt b/mlir/lib/Dialect/Polynomial/CMakeLists.txt
new file mode 100644
index 00000000000000..f33061b2d87cff
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/lib/Dialect/Polynomial/IR/CMakeLists.txt b/mlir/lib/Dialect/Polynomial/IR/CMakeLists.txt
new file mode 100644
index 00000000000000..695c37f7a368b3
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_mlir_dialect_library(MLIRPolynomialDialect
+  Polynomial.cpp
+  PolynomialAttributes.cpp
+  PolynomialDialect.cpp
+  PolynomialOps.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/Polynomial
+
+  DEPENDS
+  MLIRPolynomialOpsIncGen
+  MLIRPolynomialTypesIncGen
+  MLIRPolynomialDialectIncGen
+  MLIRPolynomialAttributesIncGen
+  MLIRBuiltinAttributesIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRSupport
+  MLIRDialect
+  MLIRIR
+  )
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
new file mode 100644
index 00000000000000..6e04691502275c
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -0,0 +1,97 @@
+//===- Polynomial.cpp - MLIR storage type for static Polynomial
+//--------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
+
+#include "PolynomialDetail.h"
+#include "mlir/IR/MLIRContext.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace mlir {
+namespace polynomial {
+
+MLIRContext *Polynomial::getContext() const { return terms->context; }
+
+ArrayRef<Monomial> Polynomial::getTerms() const { return terms->terms(); }
+
+Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials,
+                                     MLIRContext *context) {
+  auto assignCtx = [context](detail::PolynomialStorage *storage) {
+    storage->context = context;
+  };
+
+  // A polynomial's terms are canonically stored in order of increasing degree.
+  llvm::OwningArrayRef<Monomial> monomialsCopy =
+      llvm::OwningArrayRef<Monomial>(monomials);
+  std::sort(monomialsCopy.begin(), monomialsCopy.end());
+
+  StorageUniquer &uniquer = context->getAttributeUniquer();
+  return Polynomial(uniquer.get<detail::PolynomialStorage>(
+      assignCtx, monomials.size(), monomialsCopy));
+}
+
+Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs,
+                                        MLIRContext *context) {
+  std::vector<Monomial> monomials;
+  for (size_t i = 0; i < coeffs.size(); i++) {
+    monomials.emplace_back(coeffs[i], i);
+  }
+  return Polynomial::fromMonomials(monomials, context);
+}
+
+void Polynomial::print(raw_ostream &os, const std::string &separator,
+                       const std::string &exponentiation) const {
+  bool first = true;
+  for (const auto &term : terms->terms()) {
+    if (first) {
+      first = false;
+    } else {
+      os << separator;
+    }
+    std::string coeffToPrint;
+    if (term.coefficient == 1 && term.exponent.uge(1)) {
+      coeffToPrint = "";
+    } else {
+      llvm::SmallString<512> coeffString;
+      term.coefficient.toStringSigned(coeffString);
+      coeffToPrint = coeffString.str();
+    }
+
+    if (term.exponent == 0) {
+      os << coeffToPrint;
+    } else if (term.exponent == 1) {
+      os << coeffToPrint << "x";
+    } else {
+      llvm::SmallString<512> expString;
+      term.exponent.toStringSigned(expString);
+      os << coeffToPrint << "x" << exponentiation << expString;
+    }
+  }
+}
+
+void Polynomial::print(raw_ostream &os) const { print(os, " + ", "**"); }
+
+std::string Polynomial::toIdentifier() const {
+  std::string result;
+  llvm::raw_string_ostream os(result);
+  print(os, "_", "");
+  return os.str();
+}
+
+unsigned Polynomial::getDegree() const {
+  return terms->terms().back().exponent.getZExtValue();
+}
+
+} // namespace polynomial
+} // namespace mlir
+
+MLIR_DEFINE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage);
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
new file mode 100644
index 00000000000000..d3ce95e161dee1
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -0,0 +1,217 @@
+//===- PolynomialAttributes.cpp - Polynomial dialect attributes --*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
+
+#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
+#include "mlir/Support/LLVM.h"
+#include "mlir/Support/LogicalResult.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace mlir {
+namespace polynomial {
+
+void PolynomialAttr::print(AsmPrinter &p) const {
+  p << '<';
+  p << getPolynomial();
+  p << '>';
+}
+
+/// Try to parse a monomial. If successful, populate the fields of the outparam
+/// `monomial` with the results, and the `variable` outparam with the parsed
+/// variable name.
+ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
+                          llvm::StringRef *variable, bool *isConstantTerm) {
+  APInt parsedCoeff(apintBitWidth, 1);
+  auto result = parser.parseOptionalInteger(parsedCoeff);
+  if (result.has_value()) {
+    if (failed(*result)) {
+      parser.emitError(parser.getCurrentLocation(),
+                       "Invalid integer coefficient.");
+      return failure();
+    }
+  }
+
+  // Variable name
+  result = parser.parseOptionalKeyword(variable);
+  if (!result.has_value() || failed(*result)) {
+    // we allow "failed" because it triggers when the next token is a +,
+    // which is allowed when the input is the constant term.
+    monomial.coefficient = parsedCoeff;
+    monomial.exponent = APInt(apintBitWidth, 0);
+    *isConstantTerm = true;
+    return success();
+  }
+
+  // Parse exponentiation symbol as **
+  // We can't use caret because it's reserved for basic block identifiers
+  // If no star is present, it's treated as a polynomial with exponent 1
+  if (failed(parser.parseOptionalStar())) {
+    monomial.coefficient = parsedCoeff;
+    monomial.exponent = APInt(apintBitWidth, 1);
+    return success();
+  }
+
+  // If there's one * there must be two
+  if (failed(parser.parseStar())) {
+    parser.emitError(parser.getCurrentLocation(),
+                     "Exponents must be specified as a double-asterisk `**`.");
+    return failure();
+  }
+
+  // If there's a **, then the integer exponent is required.
+  APInt parsedExponent(apintBitWidth, 0);
+  if (failed(parser.parseInteger(parsedExponent))) {
+    parser.emitError(parser.getCurrentLocation(),
+                     "Found invalid integer exponent.");
+    return failure();
+  }
+
+  monomial.coefficient = parsedCoeff;
+  monomial.exponent = parsedExponent;
+  return success();
+}
+
+mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
+                                                        Type type) {
+  if (failed(parser.parseLess()))
+    return {};
+
+  std::vector<Monomial> monomials;
+  llvm::SmallSet<std::string, 2> variables;
+  llvm::DenseSet<APInt> exponents;
+
+  while (true) {
+    Monomial parsedMonomial;
+    llvm::StringRef parsedVariableRef;
+    bool isConstantTerm = false;
+    if (failed(parseMonomial(parser, parsedMonomial, &parsedVariableRef,
+                             &isConstantTerm))) {
+      return {};
+    }
+
+    if (!isConstantTerm) {
+      std::string parsedVariable = parsedVariableRef.str();
+      variables.insert(parsedVariable);
+    }
+    monomials.push_back(parsedMonomial);
+
+    if (exponents.count(parsedMonomial.exponent) > 0) {
+      llvm::SmallString<512> coeff_string;
+      parsedMonomial.exponent.toStringSigned(coeff_string);
+      parser.emitError(parser.getCurrentLocation(),
+                       "At most one monomial may have exponent " +
+                           coeff_string + ", but found multiple.");
+      return {};
+    }
+    exponents.insert(parsedMonomial.exponent);
+
+    // Parse optional +. If a + is absent, require > and break, otherwise forbid
+    // > and continue with the next monomial.
+    // ParseOptional{Plus, Greater} does not return an OptionalParseResult, so
+    // failed means that the token was not found.
+    if (failed(parser.parseOptionalPlus())) {
+      if (succeeded(parser.parseGreater())) {
+        break;
+      } else {
+        parser.emitError(
+            parser.getCurrentLocation(),
+            "Expected + and more monomials, or > to end polynomial attribute.");
+        return {};
+      }
+    } else if (succeeded(parser.parseOptionalGreater())) {
+      parser.emitError(
+          parser.getCurrentLocation(),
+          "Expected another monomial after +, but found > ending attribute.");
+      return {};
+    }
+  }
+
+  // insert necessary constant ops to give as input to extract_slice.
+  if (variables.size() > 1) {
+    std::string vars = llvm::join(variables.begin(), variables.end(), ", ");
+    parser.emitError(
+        parser.getCurrentLocation(),
+        "Polynomials must have one indeterminate, but there were multiple: " +
+            vars);
+  }
+
+  Polynomial poly = Polynomial::fromMonomials(monomials, parser.getContext());
+  return PolynomialAttr::get(poly);
+}
+
+void RingAttr::print(AsmPrinter &p) const {
+  p << "#polynomial.ring<ctype=" << getCoefficientType()
+    << ", cmod=" << getCoefficientModulus()
+    << ", ideal=" << getPolynomialModulus() << '>';
+}
+
+mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
+                                                  Type type) {
+  if (failed(parser.parseLess()))
+    return {};
+
+  if (failed(parser.parseKeyword("ctype")))
+    return {};
+
+  if (failed(parser.parseEqual()))
+    return {};
+
+  TypeAttr typeAttr;
+  if (failed(parser.parseAttribute<TypeAttr>(typeAttr)))
+    return {};
+
+  if (failed(parser.parseComma()))
+    return {};
+
+  std::optional<IntegerAttr> cmodAttr = std::nullopt;
+  if (succeeded(parser.parseKeyword("cmod"))) {
+    if (failed(parser.parseEqual()))
+      return {};
+
+    IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
+    if (!iType) {
+      parser.emitError(
+          parser.getCurrentLocation(),
+          "Invalid coefficient modulus, ctype must specify an integer type.");
+      return {};
+    }
+    APInt cmod(iType.getWidth(), 0);
+    auto result = parser.parseInteger(cmod);
+    if (failed(result)) {
+      parser.emitError(parser.getCurrentLocation(),
+                       "Invalid coefficient modulus.");
+      return {};
+    }
+    cmodAttr = IntegerAttr::get(iType, cmod);
+
+    if (failed(parser.parseComma()))
+      return {};
+  }
+
+  std::optional<PolynomialAttr> polyAttr = std::nullopt;
+  if (succeeded(parser.parseKeyword("ideal"))) {
+    if (failed(parser.parseEqual()))
+      return {};
+
+    PolynomialAttr attr;
+    if (failed(parser.parseAttribute<PolynomialAttr>(attr)))
+      return {};
+    polyAttr = attr;
+  }
+
+  if (failed(parser.parseGreater()))
+    return {};
+
+  return RingAttr::get(parser.getContext(), typeAttr, cmodAttr, polyAttr);
+}
+
+} // namespace polynomial
+} // namespace mlir
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h b/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
new file mode 100644
index 00000000000000..19ee6b7ec25d10
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
@@ -0,0 +1,65 @@
+//===- Polynomial.h - Storage class details for polynomial types --------*-
+// C++-*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
+#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
+
+#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
+#include "mlir/Support/StorageUniquer.h"
+#include "mlir/Support/TypeID.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/TrailingObjects.h"
+
+namespace mlir {
+namespace polynomial {
+namespace detail {
+
+// A Polynomial is stored as an ordered list of monomial terms, each of which
+// is a tuple of coefficient and exponent.
+struct PolynomialStorage final
+    : public StorageUniquer::BaseStorage,
+      public llvm::TrailingObjects<PolynomialStorage, Monomial> {
+  /// The hash key used for uniquing.
+  using KeyTy = std::tuple<unsigned, ArrayRef<Monomial>>;
+
+  unsigned numTerms;
+
+  MLIRContext *context;
+
+  /// The monomial terms for this polynomial.
+  ArrayRef<Monomial> terms() const {
+    return {getTrailingObjects<Monomial>(), numTerms};
+  }
+
+  bool operator==(const KeyTy &key) const {
+    return std::get<0>(key) == numTerms && std::get<1>(key) == terms();
+  }
+
+  // Constructs a PolynomialStorage from a key. The context must be set by the
+  // caller.
+  static PolynomialStorage *
+  construct(StorageUniquer::StorageAllocator &allocator, const KeyTy &key) {
+    auto terms = std::get<1>(key);
+    auto byteSize = PolynomialStorage::totalSizeToAlloc<Monomial>(terms.size());
+    auto *rawMem = allocator.allocate(byteSize, alignof(PolynomialStorage));
+    auto *res = new (rawMem) PolynomialStorage();
+    res->numTerms = std::get<0>(key);
+    std::uninitialized_copy(terms.begin(), terms.end(),
+                            res->getTrailingObjects<Monomial>());
+    return res;
+  }
+};
+
+} // namespace detail
+} // namespace polynomial
+} // namespace mlir
+
+MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage)
+
+#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
new file mode 100644
index 00000000000000..b618495b2cdcd0
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
@@ -0,0 +1,47 @@
+//===- PolynomialDialect.cpp - MLIR dialect for Polynomial implementation
+//-------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
+
+#include "PolynomialDetail.h"
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
+#include "mlir/Dialect/Polynomial/IR/PolynomialOps.h"
+#include "mlir/Dialect/Polynomial/IR/PolynomialTypes.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace mlir;
+using namespace mlir::polynomial;
+
+#include "mlir/Dialect/Polynomial/IR/PolynomialDialect.cpp.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.cpp.inc"
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialTypes.cpp.inc"
+#define GET_OP_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialOps.cpp.inc"
+
+void PolynomialDialect::initialize() {
+  addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.cpp.inc"
+      >();
+  addTypes<
+#define GET_TYPEDEF_LIST
+#include "mlir/Dialect/Polynomial/IR/PolynomialTypes.cpp.inc"
+      >();
+  addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/Polynomial/IR/PolynomialOps.cpp.inc"
+      >();
+
+  getContext()
+      ->getAttributeUniquer()
+      .registerParametricStorageType<detail::PolynomialStorage>();
+}
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
new file mode 100644
index 00000000000000..644a669205213e
--- /dev/null
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
@@ -0,0 +1,16 @@
+//===- PolynomialOps.cpp - MLIR operations for polynomial implementation
+//--------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
+
+using namespace mlir;
+using namespace mlir::polynomial;
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/Polynomial/IR/PolynomialOps.cpp.inc"
diff --git a/mlir/test/Dialect/Polynomial/types.td b/mlir/test/Dialect/Polynomial/types.td
new file mode 100644
index 00000000000000..7328318002203e
--- /dev/null
+++ b/mlir/test/Dialect/Polynomial/types.td
@@ -0,0 +1,19 @@
+// RUN: mlir-opt %s | FileCheck %s
+
+#my_poly = #polynomial.polynomial<1 + x**1024>
+#my_poly_2 = #polynomial.polynomial<2>
+#my_poly_3 = #polynomial.polynomial<3x>
+#my_poly_4 = #polynomial.polynomial<t**3 + 4t + 2>
+#ring1 = #polynomial.ring<ctype=i32, cmod=2837465, ideal=#my_poly>
+
+!ty = !polynomial.polynomial<#ring1>
+
+// CHECK-LABEL: func @test_types
+// CHECK-SAME:  !polynomial.polynomial<
+// CHECK-SAME:    #polynomial.ring<
+// CHECK-SAME:       ctype=i32,
+// CHECK-SAME:       cmod=2837465 : i32,
+// CHECK-SAME:       ideal=#polynomial.polynomial<1 + x**1024>>>
+func.func @test_types(%0: !ty) -> !ty {
+  return %0 : !ty
+}

>From 021fcd6203e0a3363cb23800d4af47d330fa193b Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:01:12 -0800
Subject: [PATCH 02/44] fix include guards

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h        | 6 +++---
 .../mlir/Dialect/Polynomial/IR/PolynomialAttributes.h       | 6 +++---
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h | 6 +++---
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h     | 6 +++---
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h   | 6 +++---
 5 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 757ee61ec8c7a2..1ca04cf92e1edc 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
 
 #include <utility>
 
@@ -154,4 +154,4 @@ struct DenseMapInfo<mlir::polynomial::Polynomial> {
 
 } // namespace llvm
 
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
index 6d6941cf6bdcc6..3b0223e6da27a0 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
@@ -6,8 +6,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
+#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
+#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
 
 #include "Polynomial.h"
 #include "PolynomialDialect.h"
@@ -15,4 +15,4 @@
 #define GET_ATTRDEF_CLASSES
 #include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h.inc"
 
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
+#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALATTRIBUTES_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
index 50538126c0372f..b1971c020b3547 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
@@ -5,8 +5,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
+#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
+#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -16,4 +16,4 @@
 // Generated headers (block clang-format from messing up order)
 #include "mlir/Dialect/Polynomial/IR/PolynomialDialect.h.inc"
 
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
+#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDIALECT_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
index 49491c9bdc8ad3..8897949a182cae 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
@@ -5,8 +5,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
+#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
+#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
 
 #include "PolynomialDialect.h"
 #include "PolynomialTypes.h"
@@ -18,4 +18,4 @@
 #define GET_OP_CLASSES
 #include "mlir/Dialect/Polynomial/IR/PolynomialOps.h.inc"
 
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
+#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALOPS_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
index c030de2d6c77fb..286b0d96539528 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
@@ -5,8 +5,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
+#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
+#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
 
 #include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
 #include "mlir/Dialect/Polynomial/IR/PolynomialDialect.h"
@@ -14,4 +14,4 @@
 #define GET_TYPEDEF_CLASSES
 #include "mlir/Dialect/Polynomial/IR/PolynomialTypes.h.inc"
 
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_
+#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALTYPES_H_

>From 73e0e78e4ef755bcfe9415a2ca4cd3196529cedd Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:06:37 -0800
Subject: [PATCH 03/44] add top level docs to Monomial

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 1ca04cf92e1edc..945b0789733afa 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -31,6 +31,8 @@ namespace detail {
 struct PolynomialStorage;
 } // namespace detail
 
+/// A class representing a monomial of a single-variable polynomial with integer
+/// coefficients.
 class Monomial {
 public:
   Monomial(int64_t coeff, uint64_t expo)

>From dde8eb36b64acc42d45cf854ab1fece87a8670bf Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:08:04 -0800
Subject: [PATCH 04/44] use /// for top level comment

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 945b0789733afa..b7c1fcad732aa3 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -22,9 +22,9 @@ class MLIRContext;
 
 namespace polynomial {
 
-// This restricts statically defined polynomials to have at most 64-bit
-// coefficients. This may be relaxed in the future, but it seems unlikely one
-// would want to specify 128-bit polynomials statically in the source code.
+/// This restricts statically defined polynomials to have at most 64-bit
+/// coefficients. This may be relaxed in the future, but it seems unlikely one
+/// would want to specify 128-bit polynomials statically in the source code.
 constexpr unsigned apintBitWidth = 64;
 
 namespace detail {

>From 6dd45b5c31fab17efaae6d4a25ff1ec82ba26df2 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:08:48 -0800
Subject: [PATCH 05/44] make hash_value arg const

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index b7c1fcad732aa3..503f187be13022 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -58,7 +58,7 @@ class Monomial {
   // Prints polynomial to 'os'.
   void print(raw_ostream &os) const;
 
-  friend ::llvm::hash_code hash_value(Monomial arg);
+  friend ::llvm::hash_code hash_value(const Monomial& arg);
 
 public:
   APInt coefficient;
@@ -118,7 +118,7 @@ inline ::llvm::hash_code hash_value(Polynomial arg) {
   return ::llvm::hash_value(arg.terms);
 }
 
-inline ::llvm::hash_code hash_value(Monomial arg) {
+inline ::llvm::hash_code hash_value(const Monomial& arg) {
   return ::llvm::hash_value(arg.coefficient) ^ ::llvm::hash_value(arg.exponent);
 }
 

>From 9f382931a24e9c617d5a70ca0b1a8c5b82937cda Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:13:52 -0800
Subject: [PATCH 06/44] std::string -> StringRef

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 ++--
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp        | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 503f187be13022..063e620a1d8b3c 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -95,8 +95,8 @@ class Polynomial {
 
   // Prints polynomial to 'os'.
   void print(raw_ostream &os) const;
-  void print(raw_ostream &os, const std::string &separator,
-             const std::string &exponentiation) const;
+  void print(raw_ostream &os, ::llvm::StringRef separator,
+             ::llvm::StringRef exponentiation) const;
   void dump() const;
 
   // Prints polynomial so that it can be used as a valid identifier
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 6e04691502275c..740d1abdaa67d5 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -48,8 +48,8 @@ Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs,
   return Polynomial::fromMonomials(monomials, context);
 }
 
-void Polynomial::print(raw_ostream &os, const std::string &separator,
-                       const std::string &exponentiation) const {
+void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
+                       ::llvm::StringRef exponentiation) const {
   bool first = true;
   for (const auto &term : terms->terms()) {
     if (first) {

>From 7cd8313a5f1c7ebc94926fb5b2a6b08214773b90 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 07:18:48 -0800
Subject: [PATCH 07/44] update/align header comments

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h           | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h | 3 +--
 .../include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h    | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td   | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h        | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td       | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h      | 2 +-
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td     | 2 +-
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp                  | 3 +--
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp        | 3 +--
 mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h              | 3 +--
 mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp           | 3 +--
 mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp               | 3 +--
 14 files changed, 14 insertions(+), 20 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 063e620a1d8b3c..7422251bd9eb47 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -1,4 +1,4 @@
-//===- Polynomial.h - A storage class for polynomial types --------*- C++-*-==//
+//===- Polynomial.h - A storage class for polynomial types ------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
index 3b0223e6da27a0..b37d17bb89fb2c 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.h
@@ -1,5 +1,4 @@
-//===- PolynomialAttributes.h - Attributes for the Polynomial dialect -*- C++
-//-*-===//
+//===- PolynomialAttributes.h - polynomial dialect attributes ---*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
index 0e4f2f182ede1f..53c26e99103f1d 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -1,4 +1,4 @@
-//===- PolynomialAttributes.td - Attribute definitions for the polynomial dialect ------*- tablegen -*-==//
+//===- PolynomialAttributes.td - polynomial dialect attrs --*- tablegen -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
index b1971c020b3547..7b7acebe7a93bb 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.h
@@ -1,4 +1,4 @@
-//===- PolynomialDialect.h - The Polynomial dialect -*- C++ -*-===//
+//===- PolynomialDialect.h - The Polynomial dialect -------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
index d664a7c6159fdc..95baafc281492c 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialDialect.td
@@ -1,4 +1,4 @@
-//===- PolynomialDialect.td - Dialect definition for the polynomial dialect ------*- tablegen -*-==//
+//===- PolynomialDialect.td - polynomial dialect -----------*- tablegen -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
index 8897949a182cae..a3ec062ac93fed 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.h
@@ -1,4 +1,4 @@
-//===- PolynomialOps.h - Ops for the Polynomial dialect -*- C++ -*-===//
+//===- PolynomialOps.h - Ops for the Polynomial dialect ---------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
index 6ead46c953faf7..06b97cdd059f85 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialOps.td
@@ -1,4 +1,4 @@
-//===- PolynomialOps.td - Polynomial op definitions --------------------*- tablegen -*-===//
+//===- PolynomialOps.td - Polynomial op definitions --------*- tablegen -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
index 286b0d96539528..2fc68774525476 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.h
@@ -1,4 +1,4 @@
-//===- PolynomialTypes.h - Types for the Polynomial dialect -*- C++ -*-===//
+//===- PolynomialTypes.h - Types for the Polynomial dialect -----*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
index b480c9ea714471..0a9be5f3f88464 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialTypes.td
@@ -1,4 +1,4 @@
-//===- PolynomialTypes.td - Type definitions for polynomial dialect ------*- tablegen -*-==//
+//===- PolynomialTypes.td - Types for polynomial dialect ---*- tablegen -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 740d1abdaa67d5..add132f3fcde0b 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -1,5 +1,4 @@
-//===- Polynomial.cpp - MLIR storage type for static Polynomial
-//--------------===//
+//===- Polynomial.cpp - MLIR storage type for static Polynomial -*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index d3ce95e161dee1..d932362f76f3ac 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -1,5 +1,4 @@
-//===- PolynomialAttributes.cpp - Polynomial dialect attributes --*- C++
-//-*-===//
+//===- PolynomialAttributes.cpp - Polynomial dialect attrs ------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h b/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
index 19ee6b7ec25d10..f57dc50e309cde 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
@@ -1,5 +1,4 @@
-//===- Polynomial.h - Storage class details for polynomial types --------*-
-// C++-*-==//
+//===- Polynomial.h - Storage class details for polynomial ------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
index b618495b2cdcd0..6b4e26e5fb03c9 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
@@ -1,5 +1,4 @@
-//===- PolynomialDialect.cpp - MLIR dialect for Polynomial implementation
-//-------------===//
+//===- PolynomialDialect.cpp - Polynomial dialect ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
index 644a669205213e..a33a15ca9dfe5c 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialOps.cpp
@@ -1,5 +1,4 @@
-//===- PolynomialOps.cpp - MLIR operations for polynomial implementation
-//--------------===//
+//===- PolynomialOps.cpp - Polynomial dialect ops ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

>From fc3b6ea00ac03ef731b38d179cc1d5d71088d500 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:33:39 -0800
Subject: [PATCH 08/44] remove tex quotes

---
 mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
index 53c26e99103f1d..d061ae26f5b800 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -61,7 +61,7 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
     %0 = ... : polynomial.polynomial<#ring>
     ```
 
-    In this case, the value of a polynomial is always ``converted'' to a
+    In this case, the value of a polynomial is always "converted" to a
     canonical form by applying repeated reductions by setting `x**1024 = 1`
     and simplifying.
 

>From 3962aa9ef8169a694a2a46eebd81d51163d46a3a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:35:09 -0800
Subject: [PATCH 09/44] use auto over OwningArrayRef

---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index add132f3fcde0b..fb3d535abb6fe8 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -29,8 +29,7 @@ Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials,
   };
 
   // A polynomial's terms are canonically stored in order of increasing degree.
-  llvm::OwningArrayRef<Monomial> monomialsCopy =
-      llvm::OwningArrayRef<Monomial>(monomials);
+  auto monomialsCopy = llvm::OwningArrayRef<Monomial>(monomials);
   std::sort(monomialsCopy.begin(), monomialsCopy.end());
 
   StorageUniquer &uniquer = context->getAttributeUniquer();

>From 99c75d9f00fbf2a87868aba72b8a17ce928eed96 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:42:55 -0800
Subject: [PATCH 10/44] use SmallVector instead of std::vector, clarify
 docstring

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 +++-
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp        | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 7422251bd9eb47..2914334fae47e2 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -83,7 +83,9 @@ class Polynomial {
 
   static Polynomial fromMonomials(ArrayRef<Monomial> monomials,
                                   MLIRContext *context);
-  /// Returns a polynomial with coefficients given by `coeffs`
+
+  /// Returns a polynomial with coefficients given by `coeffs`. The value
+  /// coeffs[i] is converted to a monomial with exponent i.
   static Polynomial fromCoefficients(ArrayRef<int64_t> coeffs,
                                      MLIRContext *context);
 
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index fb3d535abb6fe8..4bc0393bcd4176 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -12,6 +12,7 @@
 #include "mlir/IR/MLIRContext.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -39,7 +40,8 @@ Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials,
 
 Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs,
                                         MLIRContext *context) {
-  std::vector<Monomial> monomials;
+  llvm::SmallVector<Monomial> monomials;
+  monomials.reserve(coeffs.size());
   for (size_t i = 0; i < coeffs.size(); i++) {
     monomials.emplace_back(coeffs[i], i);
   }

>From 64c5274b291d14209bb96457ccaad957c8257e0e Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:45:52 -0800
Subject: [PATCH 11/44] Fix parser error string style

---
 .../Polynomial/IR/PolynomialAttributes.cpp    | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index d932362f76f3ac..8a4e75cd6cbcc5 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -33,7 +33,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   if (result.has_value()) {
     if (failed(*result)) {
       parser.emitError(parser.getCurrentLocation(),
-                       "Invalid integer coefficient.");
+                       "invalid integer coefficient");
       return failure();
     }
   }
@@ -61,7 +61,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   // If there's one * there must be two
   if (failed(parser.parseStar())) {
     parser.emitError(parser.getCurrentLocation(),
-                     "Exponents must be specified as a double-asterisk `**`.");
+                     "exponents must be specified as a double-asterisk `**`");
     return failure();
   }
 
@@ -69,7 +69,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   APInt parsedExponent(apintBitWidth, 0);
   if (failed(parser.parseInteger(parsedExponent))) {
     parser.emitError(parser.getCurrentLocation(),
-                     "Found invalid integer exponent.");
+                     "found invalid integer exponent");
     return failure();
   }
 
@@ -106,8 +106,8 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
       llvm::SmallString<512> coeff_string;
       parsedMonomial.exponent.toStringSigned(coeff_string);
       parser.emitError(parser.getCurrentLocation(),
-                       "At most one monomial may have exponent " +
-                           coeff_string + ", but found multiple.");
+                       "at most one monomial may have exponent " +
+                           coeff_string + ", but found multiple");
       return {};
     }
     exponents.insert(parsedMonomial.exponent);
@@ -122,13 +122,13 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
       } else {
         parser.emitError(
             parser.getCurrentLocation(),
-            "Expected + and more monomials, or > to end polynomial attribute.");
+            "expected + and more monomials, or > to end polynomial attribute");
         return {};
       }
     } else if (succeeded(parser.parseOptionalGreater())) {
       parser.emitError(
           parser.getCurrentLocation(),
-          "Expected another monomial after +, but found > ending attribute.");
+          "expected another monomial after +, but found > ending attribute");
       return {};
     }
   }
@@ -138,7 +138,7 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     std::string vars = llvm::join(variables.begin(), variables.end(), ", ");
     parser.emitError(
         parser.getCurrentLocation(),
-        "Polynomials must have one indeterminate, but there were multiple: " +
+        "polynomials must have one indeterminate, but there were multiple: " +
             vars);
   }
 
@@ -179,14 +179,14 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
     if (!iType) {
       parser.emitError(
           parser.getCurrentLocation(),
-          "Invalid coefficient modulus, ctype must specify an integer type.");
+          "invalid coefficient modulus, ctype must specify an integer type");
       return {};
     }
     APInt cmod(iType.getWidth(), 0);
     auto result = parser.parseInteger(cmod);
     if (failed(result)) {
       parser.emitError(parser.getCurrentLocation(),
-                       "Invalid coefficient modulus.");
+                       "invalid coefficient modulus");
       return {};
     }
     cmodAttr = IntegerAttr::get(iType, cmod);

>From 9cfb7f40ae3b51fb10bf31cbcc7dc6a532849be5 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:47:02 -0800
Subject: [PATCH 12/44] small string size 512 -> 16, and snake_case to
 camelCase

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 8a4e75cd6cbcc5..2751cd258e34f6 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -103,11 +103,11 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     monomials.push_back(parsedMonomial);
 
     if (exponents.count(parsedMonomial.exponent) > 0) {
-      llvm::SmallString<512> coeff_string;
-      parsedMonomial.exponent.toStringSigned(coeff_string);
+      llvm::SmallString<16> coeffString;
+      parsedMonomial.exponent.toStringSigned(coeffString);
       parser.emitError(parser.getCurrentLocation(),
                        "at most one monomial may have exponent " +
-                           coeff_string + ", but found multiple");
+                           coeffString + ", but found multiple");
       return {};
     }
     exponents.insert(parsedMonomial.exponent);

>From 4570beed6eca9388915aeeab72404579ab6c2c5a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 08:48:14 -0800
Subject: [PATCH 13/44] comment capitalization style

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 2751cd258e34f6..470d6e8d57d7a9 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -41,7 +41,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   // Variable name
   result = parser.parseOptionalKeyword(variable);
   if (!result.has_value() || failed(*result)) {
-    // we allow "failed" because it triggers when the next token is a +,
+    // We allow "failed" because it triggers when the next token is a +,
     // which is allowed when the input is the constant term.
     monomial.coefficient = parsedCoeff;
     monomial.exponent = APInt(apintBitWidth, 0);
@@ -133,7 +133,7 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     }
   }
 
-  // insert necessary constant ops to give as input to extract_slice.
+  // Insert necessary constant ops to give as input to extract_slice.
   if (variables.size() > 1) {
     std::string vars = llvm::join(variables.begin(), variables.end(), ", ");
     parser.emitError(

>From 9929633f43906c114d992ab6e28857a589e2511e Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 09:47:25 -0800
Subject: [PATCH 14/44] use consistent verbose attribute property names

---
 .../Polynomial/IR/PolynomialAttributes.td     | 11 ++++---
 .../Polynomial/IR/PolynomialAttributes.cpp    | 33 ++++++++++---------
 mlir/test/Dialect/Polynomial/types.td         |  8 ++---
 3 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
index d061ae26f5b800..626350813d0dd9 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -41,8 +41,9 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
     A ring describes the domain in which polynomial arithmetic occurs. The ring
     attribute in `polynomial` represents the more specific case of polynomials
     with a single indeterminate; whose coefficients can be represented by
-    another MLIR type (`ctype`); and, if the coefficient type is integral,
-    whose coefficients are taken modulo some statically known modulus (`cmod`).
+    another MLIR type (`coefficientType`); and, if the coefficient type is
+    integral, whose coefficients are taken modulo some statically known modulus
+    (`coefficientModulus`).
 
     Additionally, a polynomial ring can specify an _ideal_, which converts
     polynomial arithmetic to the analogue of modular integer arithmetic, where
@@ -54,9 +55,11 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
     coefficients are taken modulo `2**32 - 5`, with a polynomial modulus of
     `x**1024 - 1`.
 
-    ```
+    ```mlir
     #poly_mod = #polynomial.polynomial<-1 + x**1024>
-    #ring = #polynomial.ring<ctype=i32, cmod=4294967291, ideal=#poly_mod>
+    #ring = #polynomial.ring<coefficientType=i32,
+                             coefficientModulus=4294967291,
+                             polynomialModulus=#poly_mod>
 
     %0 = ... : polynomial.polynomial<#ring>
     ```
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 470d6e8d57d7a9..80678d8890ae79 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -106,8 +106,8 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
       llvm::SmallString<16> coeffString;
       parsedMonomial.exponent.toStringSigned(coeffString);
       parser.emitError(parser.getCurrentLocation(),
-                       "at most one monomial may have exponent " +
-                           coeffString + ", but found multiple");
+                       "at most one monomial may have exponent " + coeffString +
+                           ", but found multiple");
       return {};
     }
     exponents.insert(parsedMonomial.exponent);
@@ -147,9 +147,9 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
 }
 
 void RingAttr::print(AsmPrinter &p) const {
-  p << "#polynomial.ring<ctype=" << getCoefficientType()
-    << ", cmod=" << getCoefficientModulus()
-    << ", ideal=" << getPolynomialModulus() << '>';
+  p << "#polynomial.ring<coefficientType=" << getCoefficientType()
+    << ", coefficientModulus=" << getCoefficientModulus()
+    << ", polynomialModulus=" << getPolynomialModulus() << '>';
 }
 
 mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
@@ -157,7 +157,7 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
   if (failed(parser.parseLess()))
     return {};
 
-  if (failed(parser.parseKeyword("ctype")))
+  if (failed(parser.parseKeyword("coefficientType")))
     return {};
 
   if (failed(parser.parseEqual()))
@@ -170,33 +170,33 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
   if (failed(parser.parseComma()))
     return {};
 
-  std::optional<IntegerAttr> cmodAttr = std::nullopt;
-  if (succeeded(parser.parseKeyword("cmod"))) {
+  std::optional<IntegerAttr> coefficientModulusAttr = std::nullopt;
+  if (succeeded(parser.parseKeyword("coefficientModulus"))) {
     if (failed(parser.parseEqual()))
       return {};
 
     IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
     if (!iType) {
-      parser.emitError(
-          parser.getCurrentLocation(),
-          "invalid coefficient modulus, ctype must specify an integer type");
+      parser.emitError(parser.getCurrentLocation(),
+                       "invalid coefficient modulus, coefficientType must "
+                       "specify an integer type");
       return {};
     }
-    APInt cmod(iType.getWidth(), 0);
-    auto result = parser.parseInteger(cmod);
+    APInt coefficientModulus(iType.getWidth(), 0);
+    auto result = parser.parseInteger(coefficientModulus);
     if (failed(result)) {
       parser.emitError(parser.getCurrentLocation(),
                        "invalid coefficient modulus");
       return {};
     }
-    cmodAttr = IntegerAttr::get(iType, cmod);
+    coefficientModulusAttr = IntegerAttr::get(iType, coefficientModulus);
 
     if (failed(parser.parseComma()))
       return {};
   }
 
   std::optional<PolynomialAttr> polyAttr = std::nullopt;
-  if (succeeded(parser.parseKeyword("ideal"))) {
+  if (succeeded(parser.parseKeyword("polynomialModulus"))) {
     if (failed(parser.parseEqual()))
       return {};
 
@@ -209,7 +209,8 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
   if (failed(parser.parseGreater()))
     return {};
 
-  return RingAttr::get(parser.getContext(), typeAttr, cmodAttr, polyAttr);
+  return RingAttr::get(parser.getContext(), typeAttr, coefficientModulusAttr,
+                       polyAttr);
 }
 
 } // namespace polynomial
diff --git a/mlir/test/Dialect/Polynomial/types.td b/mlir/test/Dialect/Polynomial/types.td
index 7328318002203e..558c714e4400af 100644
--- a/mlir/test/Dialect/Polynomial/types.td
+++ b/mlir/test/Dialect/Polynomial/types.td
@@ -4,16 +4,16 @@
 #my_poly_2 = #polynomial.polynomial<2>
 #my_poly_3 = #polynomial.polynomial<3x>
 #my_poly_4 = #polynomial.polynomial<t**3 + 4t + 2>
-#ring1 = #polynomial.ring<ctype=i32, cmod=2837465, ideal=#my_poly>
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
 
 !ty = !polynomial.polynomial<#ring1>
 
 // CHECK-LABEL: func @test_types
 // CHECK-SAME:  !polynomial.polynomial<
 // CHECK-SAME:    #polynomial.ring<
-// CHECK-SAME:       ctype=i32,
-// CHECK-SAME:       cmod=2837465 : i32,
-// CHECK-SAME:       ideal=#polynomial.polynomial<1 + x**1024>>>
+// CHECK-SAME:       coefficientType=i32,
+// CHECK-SAME:       coefficientModulus=2837465 : i32,
+// CHECK-SAME:       polynomialModulus=#polynomial.polynomial<1 + x**1024>>>
 func.func @test_types(%0: !ty) -> !ty {
   return %0 : !ty
 }

>From a856641c9673b02a43e9880babc2e3d6e668c319 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 09:51:06 -0800
Subject: [PATCH 15/44] std::vector -> SmallVector

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 80678d8890ae79..7e10b6deab18cb 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -83,7 +83,7 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
   if (failed(parser.parseLess()))
     return {};
 
-  std::vector<Monomial> monomials;
+  llvm::SmallVector<Monomial> monomials;
   llvm::SmallSet<std::string, 2> variables;
   llvm::DenseSet<APInt> exponents;
 

>From a8b4888abc53d224ad5eabaa51dc6e140716e80b Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:14:06 -0800
Subject: [PATCH 16/44] pass variable stringref by reference

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 7e10b6deab18cb..2847bb95ffd011 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -27,7 +27,7 @@ void PolynomialAttr::print(AsmPrinter &p) const {
 /// `monomial` with the results, and the `variable` outparam with the parsed
 /// variable name.
 ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
-                          llvm::StringRef *variable, bool *isConstantTerm) {
+                          llvm::StringRef &variable, bool *isConstantTerm) {
   APInt parsedCoeff(apintBitWidth, 1);
   auto result = parser.parseOptionalInteger(parsedCoeff);
   if (result.has_value()) {
@@ -39,7 +39,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   }
 
   // Variable name
-  result = parser.parseOptionalKeyword(variable);
+  result = parser.parseOptionalKeyword(&variable);
   if (!result.has_value() || failed(*result)) {
     // We allow "failed" because it triggers when the next token is a +,
     // which is allowed when the input is the constant term.
@@ -91,7 +91,7 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     Monomial parsedMonomial;
     llvm::StringRef parsedVariableRef;
     bool isConstantTerm = false;
-    if (failed(parseMonomial(parser, parsedMonomial, &parsedVariableRef,
+    if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef,
                              &isConstantTerm))) {
       return {};
     }

>From 34f5ab8c99b6ee57f9a926e6f3dcfa87a56bb004 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:15:32 -0800
Subject: [PATCH 17/44] use llvm::is_contained

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 2847bb95ffd011..fc9abd5ab20662 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -102,7 +102,7 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     }
     monomials.push_back(parsedMonomial);
 
-    if (exponents.count(parsedMonomial.exponent) > 0) {
+    if (llvm::is_contained(exponents, parsedMonomial.exponent)) {
       llvm::SmallString<16> coeffString;
       parsedMonomial.exponent.toStringSigned(coeffString);
       parser.emitError(parser.getCurrentLocation(),

>From a2a1e5846a700fbd0934c67c4910f4f83244b4e2 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:16:24 -0800
Subject: [PATCH 18/44] fix emitError string concatenation

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index fc9abd5ab20662..20fc5871c9c326 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -105,9 +105,9 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     if (llvm::is_contained(exponents, parsedMonomial.exponent)) {
       llvm::SmallString<16> coeffString;
       parsedMonomial.exponent.toStringSigned(coeffString);
-      parser.emitError(parser.getCurrentLocation(),
-                       "at most one monomial may have exponent " + coeffString +
-                           ", but found multiple");
+      parser.emitError(parser.getCurrentLocation())
+          << "at most one monomial may have exponent " << coeffString
+          << ", but found multiple";
       return {};
     }
     exponents.insert(parsedMonomial.exponent);

>From c826c7683fb313811f23f8fffaa7a078b258b944 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:17:05 -0800
Subject: [PATCH 19/44] remove stray comment

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 20fc5871c9c326..a1da473af750a2 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -133,7 +133,6 @@ mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
     }
   }
 
-  // Insert necessary constant ops to give as input to extract_slice.
   if (variables.size() > 1) {
     std::string vars = llvm::join(variables.begin(), variables.end(), ", ");
     parser.emitError(

>From 16d019c3f2fb496a461a652552d7af8b8976d195 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:17:50 -0800
Subject: [PATCH 20/44] remove unnecessary llvm:: prefix

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index a1da473af750a2..a4a66e15232155 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -174,7 +174,7 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
     if (failed(parser.parseEqual()))
       return {};
 
-    IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
+    IntegerType iType = dyn_cast<IntegerType>(typeAttr.getValue());
     if (!iType) {
       parser.emitError(parser.getCurrentLocation(),
                        "invalid coefficient modulus, coefficientType must "

>From c90d16c88d9d2be17a3a4ebd6ae3418d36c5283c Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:26:45 -0800
Subject: [PATCH 21/44] fiddle with namespaces a bit more

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index a4a66e15232155..51d761b4b8ac06 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -78,8 +78,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   return success();
 }
 
-mlir::Attribute mlir::polynomial::PolynomialAttr::parse(AsmParser &parser,
-                                                        Type type) {
+Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
   if (failed(parser.parseLess()))
     return {};
 
@@ -151,8 +150,7 @@ void RingAttr::print(AsmPrinter &p) const {
     << ", polynomialModulus=" << getPolynomialModulus() << '>';
 }
 
-mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
-                                                  Type type) {
+Attribute RingAttr::parse(AsmParser &parser, Type type) {
   if (failed(parser.parseLess()))
     return {};
 
@@ -174,7 +172,7 @@ mlir::Attribute mlir::polynomial::RingAttr::parse(AsmParser &parser,
     if (failed(parser.parseEqual()))
       return {};
 
-    IntegerType iType = dyn_cast<IntegerType>(typeAttr.getValue());
+    IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
     if (!iType) {
       parser.emitError(parser.getCurrentLocation(),
                        "invalid coefficient modulus, coefficientType must "

>From f5555e330e2f3407558013a7497f67e233797286 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 10:29:04 -0800
Subject: [PATCH 22/44] = nullptr

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 2914334fae47e2..ea61e7d68e9dd1 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -112,7 +112,7 @@ class Polynomial {
   friend ::llvm::hash_code hash_value(Polynomial arg);
 
 private:
-  ImplType *terms{nullptr};
+  ImplType *terms = nullptr;
 };
 
 // Make Polynomial hashable.

>From 6b0538324b2d7eefa306f521eb6454d6537fe775 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Mon, 13 Nov 2023 11:03:09 -0800
Subject: [PATCH 23/44] use hash_combine

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index ea61e7d68e9dd1..587070866a9633 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -58,7 +58,7 @@ class Monomial {
   // Prints polynomial to 'os'.
   void print(raw_ostream &os) const;
 
-  friend ::llvm::hash_code hash_value(const Monomial& arg);
+  friend ::llvm::hash_code hash_value(const Monomial &arg);
 
 public:
   APInt coefficient;
@@ -120,8 +120,9 @@ inline ::llvm::hash_code hash_value(Polynomial arg) {
   return ::llvm::hash_value(arg.terms);
 }
 
-inline ::llvm::hash_code hash_value(const Monomial& arg) {
-  return ::llvm::hash_value(arg.coefficient) ^ ::llvm::hash_value(arg.exponent);
+inline ::llvm::hash_code hash_value(const Monomial &arg) {
+  return llvm::hash_combine(::llvm::hash_value(arg.coefficient),
+                            ::llvm::hash_value(arg.exponent));
 }
 
 inline raw_ostream &operator<<(raw_ostream &os, Polynomial polynomial) {

>From da5d8a9c51c580e25164bfd5f2546c943644dcd1 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 11:15:53 -0800
Subject: [PATCH 24/44] add diagnostic tests

---
 mlir/test/Dialect/Polynomial/attributes.mlir  | 44 +++++++++++++++++++
 .../Polynomial/{types.td => types.mlir}       |  0
 2 files changed, 44 insertions(+)
 create mode 100644 mlir/test/Dialect/Polynomial/attributes.mlir
 rename mlir/test/Dialect/Polynomial/{types.td => types.mlir} (100%)

diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir
new file mode 100644
index 00000000000000..6cb39b75e0791d
--- /dev/null
+++ b/mlir/test/Dialect/Polynomial/attributes.mlir
@@ -0,0 +1,44 @@
+// RUN: mlir-opt %s --split-input-file --verify-diagnostics
+
+#my_poly = #polynomial.polynomial<y + x**1024>
+// expected-error at below {{polynomials must have one indeterminate, but there were multiple: y, x}}
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+// expected-error at below {{expected integer value}}
+// expected-error at below {{found invalid integer exponent}}
+#my_poly = #polynomial.polynomial<5 + x**f>
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+// expected-error at below {{at most one monomial may have exponent 2, but found multiple}}
+#my_poly = #polynomial.polynomial<5 + x**2 + 3x**2>
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+// expected-error at below {{expected '>'}}
+// expected-error at below {{expected + and more monomials, or > to end polynomial attribute}}
+#my_poly = #polynomial.polynomial<5 + x**2 7>
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+#my_poly = #polynomial.polynomial<5 + x**2 +>
+// expected-error at below {{expected another monomial after +, but found > ending attribute}}
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+#my_poly = #polynomial.polynomial<5 + x**2>
+// expected-error at below {{coefficientType must specify an integer type}}
+#ring1 = #polynomial.ring<coefficientType=f64, coefficientModulus=2837465, polynomialModulus=#my_poly>
+
+// -----
+
+#my_poly = #polynomial.polynomial<5 + x**2>
+// expected-error at below {{expected integer value}}
+// expected-error at below {{invalid coefficient modulus}}
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=x, polynomialModulus=#my_poly>
diff --git a/mlir/test/Dialect/Polynomial/types.td b/mlir/test/Dialect/Polynomial/types.mlir
similarity index 100%
rename from mlir/test/Dialect/Polynomial/types.td
rename to mlir/test/Dialect/Polynomial/types.mlir

>From 06effd622f8e42d4b25499edcfc54e7d000dc6c5 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 11:16:16 -0800
Subject: [PATCH 25/44] cleanup minor attribute suggestions

---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp |  2 +-
 .../Polynomial/IR/PolynomialAttributes.cpp    | 23 +++++++------------
 2 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 4bc0393bcd4176..db9752e2e3c3bd 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -94,4 +94,4 @@ unsigned Polynomial::getDegree() const {
 } // namespace polynomial
 } // namespace mlir
 
-MLIR_DEFINE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage);
+MLIR_DEFINE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage)
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 51d761b4b8ac06..a4cd0a3b726dba 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -30,13 +30,6 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
                           llvm::StringRef &variable, bool *isConstantTerm) {
   APInt parsedCoeff(apintBitWidth, 1);
   auto result = parser.parseOptionalInteger(parsedCoeff);
-  if (result.has_value()) {
-    if (failed(*result)) {
-      parser.emitError(parser.getCurrentLocation(),
-                       "invalid integer coefficient");
-      return failure();
-    }
-  }
 
   // Variable name
   result = parser.parseOptionalKeyword(&variable);
@@ -118,13 +111,14 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
     if (failed(parser.parseOptionalPlus())) {
       if (succeeded(parser.parseGreater())) {
         break;
-      } else {
-        parser.emitError(
-            parser.getCurrentLocation(),
-            "expected + and more monomials, or > to end polynomial attribute");
-        return {};
       }
-    } else if (succeeded(parser.parseOptionalGreater())) {
+      parser.emitError(
+          parser.getCurrentLocation(),
+          "expected + and more monomials, or > to end polynomial attribute");
+      return {};
+    }
+
+    if (succeeded(parser.parseOptionalGreater())) {
       parser.emitError(
           parser.getCurrentLocation(),
           "expected another monomial after +, but found > ending attribute");
@@ -175,8 +169,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
     IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
     if (!iType) {
       parser.emitError(parser.getCurrentLocation(),
-                       "invalid coefficient modulus, coefficientType must "
-                       "specify an integer type");
+                       "coefficientType must specify an integer type");
       return {};
     }
     APInt coefficientModulus(iType.getWidth(), 0);

>From 25892918e95c7db47e9f88bfb3ae6bdd1a53617f Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 11:46:39 -0800
Subject: [PATCH 26/44] add more positive tests

---
 mlir/test/Dialect/Polynomial/types.mlir | 39 ++++++++++++++++++++-----
 1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/mlir/test/Dialect/Polynomial/types.mlir b/mlir/test/Dialect/Polynomial/types.mlir
index 558c714e4400af..64b74d9d36bb1c 100644
--- a/mlir/test/Dialect/Polynomial/types.mlir
+++ b/mlir/test/Dialect/Polynomial/types.mlir
@@ -1,19 +1,42 @@
 // RUN: mlir-opt %s | FileCheck %s
 
-#my_poly = #polynomial.polynomial<1 + x**1024>
-#my_poly_2 = #polynomial.polynomial<2>
-#my_poly_3 = #polynomial.polynomial<3x>
-#my_poly_4 = #polynomial.polynomial<t**3 + 4t + 2>
-#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
-
-!ty = !polynomial.polynomial<#ring1>
-
 // CHECK-LABEL: func @test_types
 // CHECK-SAME:  !polynomial.polynomial<
 // CHECK-SAME:    #polynomial.ring<
 // CHECK-SAME:       coefficientType=i32,
 // CHECK-SAME:       coefficientModulus=2837465 : i32,
 // CHECK-SAME:       polynomialModulus=#polynomial.polynomial<1 + x**1024>>>
+#my_poly = #polynomial.polynomial<1 + x**1024>
+#ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
+!ty = !polynomial.polynomial<#ring1>
 func.func @test_types(%0: !ty) -> !ty {
   return %0 : !ty
 }
+
+
+// CHECK-LABEL: func @test_non_x_variable_64_bit
+// CHECK-SAME:  !polynomial.polynomial<
+// CHECK-SAME:    #polynomial.ring<
+// CHECK-SAME:       coefficientType=i64,
+// CHECK-SAME:       coefficientModulus=2837465 : i64,
+// CHECK-SAME:       polynomialModulus=#polynomial.polynomial<2 + 4x + x**3>>>
+#my_poly_2 = #polynomial.polynomial<t**3 + 4t + 2>
+#ring2 = #polynomial.ring<coefficientType=i64, coefficientModulus=2837465, polynomialModulus=#my_poly_2>
+!ty2 = !polynomial.polynomial<#ring2>
+func.func @test_non_x_variable_64_bit(%0: !ty2) -> !ty2 {
+  return %0 : !ty2
+}
+
+
+// CHECK-LABEL: func @test_linear_poly
+// CHECK-SAME:  !polynomial.polynomial<
+// CHECK-SAME:    #polynomial.ring<
+// CHECK-SAME:       coefficientType=i32,
+// CHECK-SAME:       coefficientModulus=12 : i32,
+// CHECK-SAME:       polynomialModulus=#polynomial.polynomial<4x>>
+#my_poly_3 = #polynomial.polynomial<4x>
+#ring3 = #polynomial.ring<coefficientType=i32, coefficientModulus=12, polynomialModulus=#my_poly_3>
+!ty3 = !polynomial.polynomial<#ring3>
+func.func @test_linear_poly(%0: !ty3) -> !ty3 {
+  return %0 : !ty3
+}

>From a5254d9b8c633707e83e2fea0a965bae399881b6 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 11:58:02 -0800
Subject: [PATCH 27/44] use StringSet

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 5 +++--
 mlir/test/Dialect/Polynomial/attributes.mlir            | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index a4cd0a3b726dba..2c1459e1bc3564 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -13,6 +13,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 
 namespace mlir {
 namespace polynomial {
@@ -76,7 +77,7 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
     return {};
 
   llvm::SmallVector<Monomial> monomials;
-  llvm::SmallSet<std::string, 2> variables;
+  llvm::StringSet<> variables;
   llvm::DenseSet<APInt> exponents;
 
   while (true) {
@@ -127,7 +128,7 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
   }
 
   if (variables.size() > 1) {
-    std::string vars = llvm::join(variables.begin(), variables.end(), ", ");
+    std::string vars = llvm::join(variables.keys(), ", ");
     parser.emitError(
         parser.getCurrentLocation(),
         "polynomials must have one indeterminate, but there were multiple: " +
diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir
index 6cb39b75e0791d..9eeec09cbba6be 100644
--- a/mlir/test/Dialect/Polynomial/attributes.mlir
+++ b/mlir/test/Dialect/Polynomial/attributes.mlir
@@ -1,7 +1,7 @@
 // RUN: mlir-opt %s --split-input-file --verify-diagnostics
 
 #my_poly = #polynomial.polynomial<y + x**1024>
-// expected-error at below {{polynomials must have one indeterminate, but there were multiple: y, x}}
+// expected-error at below {{polynomials must have one indeterminate, but there were multiple: x, y}}
 #ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
 
 // -----

>From ea96bf4b79b01d740fa0423dcb4624523947c477 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 12:01:17 -0800
Subject: [PATCH 28/44] use dyn_cast member function

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 2c1459e1bc3564..906c8dd3a9f355 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -167,7 +167,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
     if (failed(parser.parseEqual()))
       return {};
 
-    IntegerType iType = llvm::dyn_cast<IntegerType>(typeAttr.getValue());
+    IntegerType iType = typeAttr.getValue().dyn_cast<IntegerType>();
     if (!iType) {
       parser.emitError(parser.getCurrentLocation(),
                        "coefficientType must specify an integer type");

>From f00a0d3143cf5536309dea31783b84e764ff297a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <jkun at google.com>
Date: Wed, 15 Nov 2023 13:07:42 -0800
Subject: [PATCH 29/44] try refactoring monomial parser somewhat

---
 .../Polynomial/IR/PolynomialAttributes.cpp    | 110 ++++++++++--------
 mlir/test/Dialect/Polynomial/attributes.mlir  |   5 +-
 2 files changed, 65 insertions(+), 50 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 906c8dd3a9f355..e6f7ac47699c65 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -26,18 +26,39 @@ void PolynomialAttr::print(AsmPrinter &p) const {
 
 /// Try to parse a monomial. If successful, populate the fields of the outparam
 /// `monomial` with the results, and the `variable` outparam with the parsed
-/// variable name.
+/// variable name. Sets shouldParseMore to true if the monomial is followed by
+/// a '+'.
 ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
-                          llvm::StringRef &variable, bool *isConstantTerm) {
+                          llvm::StringRef &variable, bool *isConstantTerm,
+                          bool *shouldParseMore) {
   APInt parsedCoeff(apintBitWidth, 1);
-  auto result = parser.parseOptionalInteger(parsedCoeff);
-
-  // Variable name
-  result = parser.parseOptionalKeyword(&variable);
-  if (!result.has_value() || failed(*result)) {
-    // We allow "failed" because it triggers when the next token is a +,
-    // which is allowed when the input is the constant term.
-    monomial.coefficient = parsedCoeff;
+  auto parsedCoeffResult = parser.parseOptionalInteger(parsedCoeff);
+  monomial.coefficient = parsedCoeff;
+
+  *isConstantTerm = false;
+  *shouldParseMore = false;
+
+  // A + indicates it's a constant term with more to go, as in `1 + x`.
+  if (succeeded(parser.parseOptionalPlus())) {
+    // If no coefficient was parsed, and there's a +, then it's effectively
+    // parsing an empty string.
+    if (!parsedCoeffResult.has_value()) {
+      return failure();
+    }
+    monomial.exponent = APInt(apintBitWidth, 0);
+    *isConstantTerm = true;
+    *shouldParseMore = true;
+    return success();
+  }
+
+  // A monomial can be a trailing constant term, as in `x + 1`
+  if (failed(parser.parseOptionalKeyword(&variable))) {
+    // If neither a coefficient nor a variable was found, then it's effectively
+    // parsing an empty string.
+    if (!parsedCoeffResult.has_value()) {
+      return failure();
+    }
+
     monomial.exponent = APInt(apintBitWidth, 0);
     *isConstantTerm = true;
     return success();
@@ -46,29 +67,30 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   // Parse exponentiation symbol as **
   // We can't use caret because it's reserved for basic block identifiers
   // If no star is present, it's treated as a polynomial with exponent 1
-  if (failed(parser.parseOptionalStar())) {
-    monomial.coefficient = parsedCoeff;
-    monomial.exponent = APInt(apintBitWidth, 1);
-    return success();
-  }
+  if (succeeded(parser.parseOptionalStar())) {
+    // If there's one * there must be two
+    if (failed(parser.parseStar())) {
+      parser.emitError(parser.getCurrentLocation(),
+                       "exponents must be specified as a double-asterisk `**`");
+      return failure();
+    }
 
-  // If there's one * there must be two
-  if (failed(parser.parseStar())) {
-    parser.emitError(parser.getCurrentLocation(),
-                     "exponents must be specified as a double-asterisk `**`");
-    return failure();
-  }
+    // If there's a **, then the integer exponent is required.
+    APInt parsedExponent(apintBitWidth, 0);
+    if (failed(parser.parseInteger(parsedExponent))) {
+      parser.emitError(parser.getCurrentLocation(),
+                       "found invalid integer exponent");
+      return failure();
+    }
 
-  // If there's a **, then the integer exponent is required.
-  APInt parsedExponent(apintBitWidth, 0);
-  if (failed(parser.parseInteger(parsedExponent))) {
-    parser.emitError(parser.getCurrentLocation(),
-                     "found invalid integer exponent");
-    return failure();
+    monomial.exponent = parsedExponent;
+  } else {
+    monomial.exponent = APInt(apintBitWidth, 1);
   }
 
-  monomial.coefficient = parsedCoeff;
-  monomial.exponent = parsedExponent;
+  if (succeeded(parser.parseOptionalPlus())) {
+    *shouldParseMore = true;
+  }
   return success();
 }
 
@@ -83,9 +105,11 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
   while (true) {
     Monomial parsedMonomial;
     llvm::StringRef parsedVariableRef;
-    bool isConstantTerm = false;
+    bool isConstantTerm;
+    bool shouldParseMore;
     if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef,
-                             &isConstantTerm))) {
+                             &isConstantTerm, &shouldParseMore))) {
+      parser.emitError(parser.getCurrentLocation(), "expected a monomial");
       return {};
     }
 
@@ -105,26 +129,16 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
     }
     exponents.insert(parsedMonomial.exponent);
 
-    // Parse optional +. If a + is absent, require > and break, otherwise forbid
-    // > and continue with the next monomial.
-    // ParseOptional{Plus, Greater} does not return an OptionalParseResult, so
-    // failed means that the token was not found.
-    if (failed(parser.parseOptionalPlus())) {
-      if (succeeded(parser.parseGreater())) {
-        break;
-      }
-      parser.emitError(
-          parser.getCurrentLocation(),
-          "expected + and more monomials, or > to end polynomial attribute");
-      return {};
-    }
+    if (shouldParseMore)
+      continue;
 
     if (succeeded(parser.parseOptionalGreater())) {
-      parser.emitError(
-          parser.getCurrentLocation(),
-          "expected another monomial after +, but found > ending attribute");
-      return {};
+      break;
     }
+    parser.emitError(
+        parser.getCurrentLocation(),
+        "expected + and more monomials, or > to end polynomial attribute");
+    return {};
   }
 
   if (variables.size() > 1) {
diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir
index 9eeec09cbba6be..16e385c520079b 100644
--- a/mlir/test/Dialect/Polynomial/attributes.mlir
+++ b/mlir/test/Dialect/Polynomial/attributes.mlir
@@ -7,6 +7,7 @@
 // -----
 
 // expected-error at below {{expected integer value}}
+// expected-error at below {{expected a monomial}}
 // expected-error at below {{found invalid integer exponent}}
 #my_poly = #polynomial.polynomial<5 + x**f>
 #ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
@@ -19,17 +20,17 @@
 
 // -----
 
-// expected-error at below {{expected '>'}}
 // expected-error at below {{expected + and more monomials, or > to end polynomial attribute}}
 #my_poly = #polynomial.polynomial<5 + x**2 7>
 #ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
 
 // -----
 
+// expected-error at below {{expected a monomial}}
 #my_poly = #polynomial.polynomial<5 + x**2 +>
-// expected-error at below {{expected another monomial after +, but found > ending attribute}}
 #ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
 
+
 // -----
 
 #my_poly = #polynomial.polynomial<5 + x**2>

>From 8d7f5d1c978b1820a571759e385876cfaffd4c4d Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Sun, 31 Mar 2024 15:36:33 -0700
Subject: [PATCH 30/44] don't unique Polynomial, remove std::optional from
 OptionalParameter

---
 .../mlir/Dialect/Polynomial/IR/Polynomial.h   | 63 ++++--------------
 .../Polynomial/IR/PolynomialAttributes.td     | 13 +---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 30 ++-------
 .../Polynomial/IR/PolynomialAttributes.cpp    |  8 +--
 .../Dialect/Polynomial/IR/PolynomialDetail.h  | 64 -------------------
 .../Polynomial/IR/PolynomialDialect.cpp       |  5 --
 6 files changed, 26 insertions(+), 157 deletions(-)
 delete mode 100644 mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 587070866a9633..56b066b1e9440c 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace mlir {
 
@@ -27,10 +28,6 @@ namespace polynomial {
 /// would want to specify 128-bit polynomials statically in the source code.
 constexpr unsigned apintBitWidth = 64;
 
-namespace detail {
-struct PolynomialStorage;
-} // namespace detail
-
 /// A class representing a monomial of a single-variable polynomial with integer
 /// coefficients.
 class Monomial {
@@ -67,8 +64,7 @@ class Monomial {
   APInt exponent;
 };
 
-/// A single-variable polynomial with integer coefficients. Polynomials are
-/// immutable and uniqued.
+/// A single-variable polynomial with integer coefficients.
 ///
 /// Eg: x^1024 + x + 1
 ///
@@ -76,24 +72,19 @@ class Monomial {
 /// it is used consistently throughout the polynomial.
 class Polynomial {
 public:
-  using ImplType = detail::PolynomialStorage;
+  Polynomial() = delete;
 
-  constexpr Polynomial() = default;
-  explicit Polynomial(ImplType *terms) : terms(terms) {}
+  Polynomial(const llvm::SmallVector<Monomial>& terms) : terms(terms) {};
 
-  static Polynomial fromMonomials(ArrayRef<Monomial> monomials,
-                                  MLIRContext *context);
+  static Polynomial fromMonomials(ArrayRef<Monomial> monomials);
 
   /// Returns a polynomial with coefficients given by `coeffs`. The value
   /// coeffs[i] is converted to a monomial with exponent i.
-  static Polynomial fromCoefficients(ArrayRef<int64_t> coeffs,
-                                     MLIRContext *context);
-
-  MLIRContext *getContext() const;
+  static Polynomial fromCoefficients(ArrayRef<int64_t> coeffs);
 
-  explicit operator bool() const { return terms != nullptr; }
-  bool operator==(Polynomial other) const { return other.terms == terms; }
-  bool operator!=(Polynomial other) const { return !(other.terms == terms); }
+  explicit operator bool() const { return !terms.empty(); }
+  bool operator==(const Polynomial& other) const { return other.terms == terms; }
+  bool operator!=(const Polynomial& other) const { return !(other.terms == terms); }
 
   // Prints polynomial to 'os'.
   void print(raw_ostream &os) const;
@@ -104,20 +95,18 @@ class Polynomial {
   // Prints polynomial so that it can be used as a valid identifier
   std::string toIdentifier() const;
 
-  // A polynomial's terms are canonically stored in order of increasing degree.
-  ArrayRef<Monomial> getTerms() const;
-
   unsigned getDegree() const;
 
   friend ::llvm::hash_code hash_value(Polynomial arg);
 
 private:
-  ImplType *terms = nullptr;
+  // The monomial terms for this polynomial.
+  SmallVector<Monomial> terms;
 };
 
 // Make Polynomial hashable.
 inline ::llvm::hash_code hash_value(Polynomial arg) {
-  return ::llvm::hash_value(arg.terms);
+  return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end());
 }
 
 inline ::llvm::hash_code hash_value(const Monomial &arg) {
@@ -125,7 +114,7 @@ inline ::llvm::hash_code hash_value(const Monomial &arg) {
                             ::llvm::hash_value(arg.exponent));
 }
 
-inline raw_ostream &operator<<(raw_ostream &os, Polynomial polynomial) {
+inline raw_ostream &operator<<(raw_ostream &os, const Polynomial& polynomial) {
   polynomial.print(os);
   return os;
 }
@@ -133,30 +122,4 @@ inline raw_ostream &operator<<(raw_ostream &os, Polynomial polynomial) {
 } // namespace polynomial
 } // namespace mlir
 
-namespace llvm {
-
-// Polynomials hash just like pointers
-template <>
-struct DenseMapInfo<mlir::polynomial::Polynomial> {
-  static mlir::polynomial::Polynomial getEmptyKey() {
-    auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
-    return mlir::polynomial::Polynomial(
-        static_cast<mlir::polynomial::Polynomial::ImplType *>(pointer));
-  }
-  static mlir::polynomial::Polynomial getTombstoneKey() {
-    auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
-    return mlir::polynomial::Polynomial(
-        static_cast<mlir::polynomial::Polynomial::ImplType *>(pointer));
-  }
-  static unsigned getHashValue(mlir::polynomial::Polynomial val) {
-    return mlir::polynomial::hash_value(val);
-  }
-  static bool isEqual(mlir::polynomial::Polynomial lhs,
-                      mlir::polynomial::Polynomial rhs) {
-    return lhs == rhs;
-  }
-};
-
-} // namespace llvm
-
 #endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
index 626350813d0dd9..723f6b7c2006b2 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -22,16 +22,7 @@ def Polynomial_PolynomialAttr : Polynomial_Attr<"Polynomial", "polynomial"> {
   let description = [{
      #poly = #polynomial.poly<x**1024 + 1>
   }];
-
   let parameters = (ins "Polynomial":$polynomial);
-
-  let builders = [
-    AttrBuilderWithInferredContext<(ins "Polynomial":$polynomial), [{
-      return $_get(polynomial.getContext(), polynomial);
-    }]>
-  ];
-
-  let skipDefaultBuilders = 1;
   let hasCustomAssemblyFormat = 1;
 }
 
@@ -74,8 +65,8 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
 
   let parameters = (ins
     Builtin_TypeAttr: $coefficientType,
-    OptionalParameter<"std::optional<IntegerAttr>">: $coefficientModulus,
-    OptionalParameter<"std::optional<PolynomialAttr>">: $polynomialModulus
+    OptionalParameter<"IntegerAttr">: $coefficientModulus,
+    OptionalParameter<"PolynomialAttr">: $polynomialModulus
   );
 
   let hasCustomAssemblyFormat = 1;
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index db9752e2e3c3bd..0097e540a3a753 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -8,7 +8,6 @@
 
 #include "mlir/Dialect/Polynomial/IR/Polynomial.h"
 
-#include "PolynomialDetail.h"
 #include "mlir/IR/MLIRContext.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/SmallString.h"
@@ -19,39 +18,26 @@
 namespace mlir {
 namespace polynomial {
 
-MLIRContext *Polynomial::getContext() const { return terms->context; }
-
-ArrayRef<Monomial> Polynomial::getTerms() const { return terms->terms(); }
-
-Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials,
-                                     MLIRContext *context) {
-  auto assignCtx = [context](detail::PolynomialStorage *storage) {
-    storage->context = context;
-  };
-
+Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials) {
   // A polynomial's terms are canonically stored in order of increasing degree.
-  auto monomialsCopy = llvm::OwningArrayRef<Monomial>(monomials);
+  auto monomialsCopy = llvm::SmallVector<Monomial>(monomials);
   std::sort(monomialsCopy.begin(), monomialsCopy.end());
-
-  StorageUniquer &uniquer = context->getAttributeUniquer();
-  return Polynomial(uniquer.get<detail::PolynomialStorage>(
-      assignCtx, monomials.size(), monomialsCopy));
+  return Polynomial(monomialsCopy);
 }
 
-Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs,
-                                        MLIRContext *context) {
+Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs) {
   llvm::SmallVector<Monomial> monomials;
   monomials.reserve(coeffs.size());
   for (size_t i = 0; i < coeffs.size(); i++) {
     monomials.emplace_back(coeffs[i], i);
   }
-  return Polynomial::fromMonomials(monomials, context);
+  return Polynomial::fromMonomials(monomials);
 }
 
 void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
                        ::llvm::StringRef exponentiation) const {
   bool first = true;
-  for (const auto &term : terms->terms()) {
+  for (const auto &term : terms) {
     if (first) {
       first = false;
     } else {
@@ -88,10 +74,8 @@ std::string Polynomial::toIdentifier() const {
 }
 
 unsigned Polynomial::getDegree() const {
-  return terms->terms().back().exponent.getZExtValue();
+  return terms.back().exponent.getZExtValue();
 }
 
 } // namespace polynomial
 } // namespace mlir
-
-MLIR_DEFINE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage)
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index e6f7ac47699c65..4810e79f1c1010 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -149,8 +149,8 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
             vars);
   }
 
-  Polynomial poly = Polynomial::fromMonomials(monomials, parser.getContext());
-  return PolynomialAttr::get(poly);
+  Polynomial poly = Polynomial::fromMonomials(monomials);
+  return PolynomialAttr::get(parser.getContext(), poly);
 }
 
 void RingAttr::print(AsmPrinter &p) const {
@@ -176,7 +176,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
   if (failed(parser.parseComma()))
     return {};
 
-  std::optional<IntegerAttr> coefficientModulusAttr = std::nullopt;
+  IntegerAttr coefficientModulusAttr = nullptr;
   if (succeeded(parser.parseKeyword("coefficientModulus"))) {
     if (failed(parser.parseEqual()))
       return {};
@@ -200,7 +200,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
       return {};
   }
 
-  std::optional<PolynomialAttr> polyAttr = std::nullopt;
+  PolynomialAttr polyAttr = nullptr;
   if (succeeded(parser.parseKeyword("polynomialModulus"))) {
     if (failed(parser.parseEqual()))
       return {};
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h b/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
deleted file mode 100644
index f57dc50e309cde..00000000000000
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialDetail.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//===- Polynomial.h - Storage class details for polynomial ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
-#define INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
-
-#include "mlir/Dialect/Polynomial/IR/Polynomial.h"
-#include "mlir/Support/StorageUniquer.h"
-#include "mlir/Support/TypeID.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/TrailingObjects.h"
-
-namespace mlir {
-namespace polynomial {
-namespace detail {
-
-// A Polynomial is stored as an ordered list of monomial terms, each of which
-// is a tuple of coefficient and exponent.
-struct PolynomialStorage final
-    : public StorageUniquer::BaseStorage,
-      public llvm::TrailingObjects<PolynomialStorage, Monomial> {
-  /// The hash key used for uniquing.
-  using KeyTy = std::tuple<unsigned, ArrayRef<Monomial>>;
-
-  unsigned numTerms;
-
-  MLIRContext *context;
-
-  /// The monomial terms for this polynomial.
-  ArrayRef<Monomial> terms() const {
-    return {getTrailingObjects<Monomial>(), numTerms};
-  }
-
-  bool operator==(const KeyTy &key) const {
-    return std::get<0>(key) == numTerms && std::get<1>(key) == terms();
-  }
-
-  // Constructs a PolynomialStorage from a key. The context must be set by the
-  // caller.
-  static PolynomialStorage *
-  construct(StorageUniquer::StorageAllocator &allocator, const KeyTy &key) {
-    auto terms = std::get<1>(key);
-    auto byteSize = PolynomialStorage::totalSizeToAlloc<Monomial>(terms.size());
-    auto *rawMem = allocator.allocate(byteSize, alignof(PolynomialStorage));
-    auto *res = new (rawMem) PolynomialStorage();
-    res->numTerms = std::get<0>(key);
-    std::uninitialized_copy(terms.begin(), terms.end(),
-                            res->getTrailingObjects<Monomial>());
-    return res;
-  }
-};
-
-} // namespace detail
-} // namespace polynomial
-} // namespace mlir
-
-MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::polynomial::detail::PolynomialStorage)
-
-#endif // INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIALDETAIL_H_
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
index 6b4e26e5fb03c9..f16aa2f55b71ac 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialDialect.cpp
@@ -8,7 +8,6 @@
 
 #include "mlir/Dialect/Polynomial/IR/Polynomial.h"
 
-#include "PolynomialDetail.h"
 #include "mlir/Dialect/Polynomial/IR/PolynomialAttributes.h"
 #include "mlir/Dialect/Polynomial/IR/PolynomialOps.h"
 #include "mlir/Dialect/Polynomial/IR/PolynomialTypes.h"
@@ -39,8 +38,4 @@ void PolynomialDialect::initialize() {
 #define GET_OP_LIST
 #include "mlir/Dialect/Polynomial/IR/PolynomialOps.cpp.inc"
       >();
-
-  getContext()
-      ->getAttributeUniquer()
-      .registerParametricStorageType<detail::PolynomialStorage>();
 }

>From 8227a6ac5ed7239d32474ea0e13642e7276e7c87 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Sun, 31 Mar 2024 15:40:48 -0700
Subject: [PATCH 31/44] clang-format

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 56b066b1e9440c..8388bdd8ebacba 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -74,7 +74,7 @@ class Polynomial {
 public:
   Polynomial() = delete;
 
-  Polynomial(const llvm::SmallVector<Monomial>& terms) : terms(terms) {};
+  Polynomial(const llvm::SmallVector<Monomial> &terms) : terms(terms){};
 
   static Polynomial fromMonomials(ArrayRef<Monomial> monomials);
 
@@ -83,8 +83,12 @@ class Polynomial {
   static Polynomial fromCoefficients(ArrayRef<int64_t> coeffs);
 
   explicit operator bool() const { return !terms.empty(); }
-  bool operator==(const Polynomial& other) const { return other.terms == terms; }
-  bool operator!=(const Polynomial& other) const { return !(other.terms == terms); }
+  bool operator==(const Polynomial &other) const {
+    return other.terms == terms;
+  }
+  bool operator!=(const Polynomial &other) const {
+    return !(other.terms == terms);
+  }
 
   // Prints polynomial to 'os'.
   void print(raw_ostream &os) const;
@@ -114,7 +118,7 @@ inline ::llvm::hash_code hash_value(const Monomial &arg) {
                             ::llvm::hash_value(arg.exponent));
 }
 
-inline raw_ostream &operator<<(raw_ostream &os, const Polynomial& polynomial) {
+inline raw_ostream &operator<<(raw_ostream &os, const Polynomial &polynomial) {
   polynomial.print(os);
   return os;
 }

>From 4f8be047edcb666a1f621ed3f55e70abed3d1c50 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:00:25 -0700
Subject: [PATCH 32/44] address comments about cmake config

---
 .../mlir/Dialect/Polynomial/IR/CMakeLists.txt | 21 ++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
index 3719fda2aec6d4..b51daf5d616e97 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/CMakeLists.txt
@@ -1,19 +1,26 @@
-set(LLVM_TARGET_DEFINITIONS PolynomialOps.td)
+set(LLVM_TARGET_DEFINITIONS PolynomialDialect.td)
 mlir_tablegen(PolynomialDialect.cpp.inc -gen-dialect-defs -dialect=polynomial)
 mlir_tablegen(PolynomialDialect.h.inc -gen-dialect-decls -dialect=polynomial)
 add_public_tablegen_target(MLIRPolynomialDialectIncGen)
+add_dependencies(mlir-headers MLIRPolynomialDialectIncGen)
 
+set(LLVM_TARGET_DEFINITIONS PolynomialAttributes.td)
 mlir_tablegen(PolynomialAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=polynomial)
 mlir_tablegen(PolynomialAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=polynomial)
+add_public_tablegen_target(MLIRPolynomialAttributesIncGen)
+add_dependencies(mlir-headers MLIRPolynomialAttributesIncGen)
+add_mlir_doc(PolynomialAttributes PolynomialAttributes Dialects/ -gen-attrdef-doc)
+
+set(LLVM_TARGET_DEFINITIONS PolynomialOps.td)
 mlir_tablegen(PolynomialOps.cpp.inc -gen-op-defs)
 mlir_tablegen(PolynomialOps.h.inc -gen-op-decls)
-mlir_tablegen(PolynomialTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=polynomial)
-mlir_tablegen(PolynomialTypes.h.inc -gen-typedef-decls -typedefs-dialect=polynomial)
-add_public_tablegen_target(MLIRPolynomialAttributesIncGen)
 add_public_tablegen_target(MLIRPolynomialOpsIncGen)
-add_public_tablegen_target(MLIRPolynomialTypesIncGen)
 add_dependencies(mlir-headers MLIRPolynomialOpsIncGen)
-
 add_mlir_doc(PolynoialOps PolynoialOps Dialects/ -gen-dialect-doc -dialect polynomial)
-add_mlir_doc(PolynomialAttributes PolynomialAttributes Dialects/ -gen-attrdef-doc)
+
+set(LLVM_TARGET_DEFINITIONS PolynomialTypes.td)
+mlir_tablegen(PolynomialTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=polynomial)
+mlir_tablegen(PolynomialTypes.h.inc -gen-typedef-decls -typedefs-dialect=polynomial)
+add_public_tablegen_target(MLIRPolynomialTypesIncGen)
+add_dependencies(mlir-headers MLIRPolynomialTypesIncGen)
 add_mlir_doc(PolynomialTypes PolynomialTypes Dialects/ -gen-typedef-doc)

>From 5154bee21d4058bbf101644f031c4b581ce761fe Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:03:28 -0700
Subject: [PATCH 33/44] fix include guard

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 8388bdd8ebacba..cde196e3485ebd 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
-#define MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#ifndef MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#define MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
 
 #include <utility>
 
@@ -126,4 +126,4 @@ inline raw_ostream &operator<<(raw_ostream &os, const Polynomial &polynomial) {
 } // namespace polynomial
 } // namespace mlir
 
-#endif // MLIR_INCLUDE_MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
+#endif // MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_

>From 254d54f7ea18fe32c26a4a792dd795999b68938a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:04:13 -0700
Subject: [PATCH 34/44] remove std::move

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index cde196e3485ebd..2313ab00ec0820 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -35,8 +35,8 @@ class Monomial {
   Monomial(int64_t coeff, uint64_t expo)
       : coefficient(apintBitWidth, coeff), exponent(apintBitWidth, expo) {}
 
-  Monomial(APInt coeff, APInt expo)
-      : coefficient(std::move(coeff)), exponent(std::move(expo)) {}
+  Monomial(const APInt &coeff, const APInt &expo)
+      : coefficient(coeff), exponent(expo) {}
 
   Monomial() : coefficient(apintBitWidth, 0), exponent(apintBitWidth, 0) {}
 

>From dc639f6e1abc23f6ade74c9445674515c678952f Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:13:06 -0700
Subject: [PATCH 35/44] use explicit and ArrayRef in polynomial constructor

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 2313ab00ec0820..b4bfc9ca8a61bd 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -13,7 +13,7 @@
 
 #include "mlir/Support/LLVM.h"
 #include "llvm/ADT/APInt.h"
-#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SmallVector.h"
 
@@ -74,7 +74,7 @@ class Polynomial {
 public:
   Polynomial() = delete;
 
-  Polynomial(const llvm::SmallVector<Monomial> &terms) : terms(terms){};
+  explicit Polynomial(ArrayRef<Monomial> terms) : terms(terms) {};
 
   static Polynomial fromMonomials(ArrayRef<Monomial> monomials);
 

>From 77dc029158c1ca808297948406d41f118359b74a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:13:58 -0700
Subject: [PATCH 36/44] const hash_value arg

---
 mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index b4bfc9ca8a61bd..6a71da6089d202 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -101,7 +101,7 @@ class Polynomial {
 
   unsigned getDegree() const;
 
-  friend ::llvm::hash_code hash_value(Polynomial arg);
+  friend ::llvm::hash_code hash_value(const Polynomial &arg);
 
 private:
   // The monomial terms for this polynomial.
@@ -109,7 +109,7 @@ class Polynomial {
 };
 
 // Make Polynomial hashable.
-inline ::llvm::hash_code hash_value(Polynomial arg) {
+inline ::llvm::hash_code hash_value(const Polynomial &arg) {
   return ::llvm::hash_combine_range(arg.terms.begin(), arg.terms.end());
 }
 

>From 4c0303494555176807c42fc4a3d85ed37504e084 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:15:53 -0700
Subject: [PATCH 37/44] don't evaluate size in ever loop iteration

---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 0097e540a3a753..0a76d55ca58537 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -27,8 +27,9 @@ Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials) {
 
 Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs) {
   llvm::SmallVector<Monomial> monomials;
-  monomials.reserve(coeffs.size());
-  for (size_t i = 0; i < coeffs.size(); i++) {
+  auto size = coeffs.size();
+  monomials.reserve(size);
+  for (size_t i = 0; i < size; i++) {
     monomials.emplace_back(coeffs[i], i);
   }
   return Polynomial::fromMonomials(monomials);

>From 2cd987b843d3cd78e40bc0462ffe6b9bc17ce498 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:20:25 -0700
Subject: [PATCH 38/44] expand auto

---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 0a76d55ca58537..00c503720942b8 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -38,7 +38,7 @@ Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs) {
 void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
                        ::llvm::StringRef exponentiation) const {
   bool first = true;
-  for (const auto &term : terms) {
+  for (const Monomial &term : terms) {
     if (first) {
       first = false;
     } else {

>From 6c2526dbc74b51c4c6152dee7945bcfb0049e1ab Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:21:09 -0700
Subject: [PATCH 39/44] 512 -> 16 chars smallstring

---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index 00c503720942b8..b18df98f86824c 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -48,7 +48,7 @@ void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
     if (term.coefficient == 1 && term.exponent.uge(1)) {
       coeffToPrint = "";
     } else {
-      llvm::SmallString<512> coeffString;
+      llvm::SmallString<16> coeffString;
       term.coefficient.toStringSigned(coeffString);
       coeffToPrint = coeffString.str();
     }
@@ -58,7 +58,7 @@ void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
     } else if (term.exponent == 1) {
       os << coeffToPrint << "x";
     } else {
-      llvm::SmallString<512> expString;
+      llvm::SmallString<16> expString;
       term.exponent.toStringSigned(expString);
       os << coeffToPrint << "x" << exponentiation << expString;
     }

>From 23dc522304225785348b2a5141ca16ead32591dd Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:22:36 -0700
Subject: [PATCH 40/44] add period to end of comments, remove SmallSet include

---
 .../Dialect/Polynomial/IR/PolynomialAttributes.cpp    | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 4810e79f1c1010..e8ea4439f6b5ba 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -10,7 +10,6 @@
 #include "mlir/Dialect/Polynomial/IR/Polynomial.h"
 #include "mlir/Support/LLVM.h"
 #include "mlir/Support/LogicalResult.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -51,7 +50,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
     return success();
   }
 
-  // A monomial can be a trailing constant term, as in `x + 1`
+  // A monomial can be a trailing constant term, as in `x + 1`.
   if (failed(parser.parseOptionalKeyword(&variable))) {
     // If neither a coefficient nor a variable was found, then it's effectively
     // parsing an empty string.
@@ -64,11 +63,11 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
     return success();
   }
 
-  // Parse exponentiation symbol as **
-  // We can't use caret because it's reserved for basic block identifiers
-  // If no star is present, it's treated as a polynomial with exponent 1
+  // Parse exponentiation symbol as `**`. We can't use caret because it's
+  // reserved for basic block identifiers If no star is present, it's treated
+  // as a polynomial with exponent 1.
   if (succeeded(parser.parseOptionalStar())) {
-    // If there's one * there must be two
+    // If there's one * there must be two.
     if (failed(parser.parseStar())) {
       parser.emitError(parser.getCurrentLocation(),
                        "exponents must be specified as a double-asterisk `**`");

>From a1eb2b6e1ee9af1ddf4fce955f697b66cb5562e6 Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:23:26 -0700
Subject: [PATCH 41/44] remove parseStar error message

---
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index e8ea4439f6b5ba..1362c1b343fabb 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -69,8 +69,6 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   if (succeeded(parser.parseOptionalStar())) {
     // If there's one * there must be two.
     if (failed(parser.parseStar())) {
-      parser.emitError(parser.getCurrentLocation(),
-                       "exponents must be specified as a double-asterisk `**`");
       return failure();
     }
 

>From 16b8d968b74933d498b6835c63622e01e7deec5a Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:24:14 -0700
Subject: [PATCH 42/44] pass mutated bools by reference

---
 .../Polynomial/IR/PolynomialAttributes.cpp     | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 1362c1b343fabb..0e1e686191f218 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -28,14 +28,14 @@ void PolynomialAttr::print(AsmPrinter &p) const {
 /// variable name. Sets shouldParseMore to true if the monomial is followed by
 /// a '+'.
 ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
-                          llvm::StringRef &variable, bool *isConstantTerm,
-                          bool *shouldParseMore) {
+                          llvm::StringRef &variable, bool &isConstantTerm,
+                          bool &shouldParseMore) {
   APInt parsedCoeff(apintBitWidth, 1);
   auto parsedCoeffResult = parser.parseOptionalInteger(parsedCoeff);
   monomial.coefficient = parsedCoeff;
 
-  *isConstantTerm = false;
-  *shouldParseMore = false;
+  isConstantTerm = false;
+  shouldParseMore = false;
 
   // A + indicates it's a constant term with more to go, as in `1 + x`.
   if (succeeded(parser.parseOptionalPlus())) {
@@ -45,8 +45,8 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
       return failure();
     }
     monomial.exponent = APInt(apintBitWidth, 0);
-    *isConstantTerm = true;
-    *shouldParseMore = true;
+    isConstantTerm = true;
+    shouldParseMore = true;
     return success();
   }
 
@@ -59,7 +59,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
     }
 
     monomial.exponent = APInt(apintBitWidth, 0);
-    *isConstantTerm = true;
+    isConstantTerm = true;
     return success();
   }
 
@@ -86,7 +86,7 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
   }
 
   if (succeeded(parser.parseOptionalPlus())) {
-    *shouldParseMore = true;
+    shouldParseMore = true;
   }
   return success();
 }
@@ -105,7 +105,7 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
     bool isConstantTerm;
     bool shouldParseMore;
     if (failed(parseMonomial(parser, parsedMonomial, parsedVariableRef,
-                             &isConstantTerm, &shouldParseMore))) {
+                             isConstantTerm, shouldParseMore))) {
       parser.emitError(parser.getCurrentLocation(), "expected a monomial");
       return {};
     }

>From f6b0a6ffcaad38c80116583bfeeafee257e77ceb Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:36:12 -0700
Subject: [PATCH 43/44] move duplicate exponent check to fromMonomials

---
 .../mlir/Dialect/Polynomial/IR/Polynomial.h   |  7 ++++---
 mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp | 20 ++++++++++++++++---
 .../Polynomial/IR/PolynomialAttributes.cpp    | 20 +++++++------------
 mlir/test/Dialect/Polynomial/attributes.mlir  |  2 +-
 4 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
index 6a71da6089d202..adfb275d70223e 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/Polynomial.h
@@ -9,8 +9,7 @@
 #ifndef MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
 #define MLIR_DIALECT_POLYNOMIAL_IR_POLYNOMIAL_H_
 
-#include <utility>
-
+#include "mlir/Support/LogicalResult.h"
 #include "mlir/Support/LLVM.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -76,7 +75,9 @@ class Polynomial {
 
   explicit Polynomial(ArrayRef<Monomial> terms) : terms(terms) {};
 
-  static Polynomial fromMonomials(ArrayRef<Monomial> monomials);
+  // Returns a Polynomial from a list of monomials.
+  // Fails if two monomials have the same exponent.
+  static FailureOr<Polynomial> fromMonomials(ArrayRef<Monomial> monomials);
 
   /// Returns a polynomial with coefficients given by `coeffs`. The value
   /// coeffs[i] is converted to a monomial with exponent i.
diff --git a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
index b18df98f86824c..5916ffba78e246 100644
--- a/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/Polynomial.cpp
@@ -8,7 +8,7 @@
 
 #include "mlir/Dialect/Polynomial/IR/Polynomial.h"
 
-#include "mlir/IR/MLIRContext.h"
+#include "mlir/Support/LogicalResult.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
@@ -18,10 +18,20 @@
 namespace mlir {
 namespace polynomial {
 
-Polynomial Polynomial::fromMonomials(ArrayRef<Monomial> monomials) {
+FailureOr<Polynomial> Polynomial::fromMonomials(ArrayRef<Monomial> monomials) {
   // A polynomial's terms are canonically stored in order of increasing degree.
   auto monomialsCopy = llvm::SmallVector<Monomial>(monomials);
   std::sort(monomialsCopy.begin(), monomialsCopy.end());
+
+  // Ensure non-unique exponents are not present. Since we sorted the list by
+  // exponent, a linear scan of adjancent monomials suffices.
+  if (std::adjacent_find(monomialsCopy.begin(), monomialsCopy.end(),
+                         [](const Monomial &lhs, const Monomial &rhs) {
+                           return lhs.exponent == rhs.exponent;
+                         }) != monomialsCopy.end()) {
+    return failure();
+  }
+
   return Polynomial(monomialsCopy);
 }
 
@@ -32,7 +42,11 @@ Polynomial Polynomial::fromCoefficients(ArrayRef<int64_t> coeffs) {
   for (size_t i = 0; i < size; i++) {
     monomials.emplace_back(coeffs[i], i);
   }
-  return Polynomial::fromMonomials(monomials);
+  auto result = Polynomial::fromMonomials(monomials);
+  // Construction guarantees unique exponents, so the failure mode of
+  // fromMonomials can be bypassed.
+  assert(succeeded(result));
+  return result.value();
 }
 
 void Polynomial::print(raw_ostream &os, ::llvm::StringRef separator,
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 0e1e686191f218..7730e110f71dc2 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -97,7 +97,6 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
 
   llvm::SmallVector<Monomial> monomials;
   llvm::StringSet<> variables;
-  llvm::DenseSet<APInt> exponents;
 
   while (true) {
     Monomial parsedMonomial;
@@ -116,16 +115,6 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
     }
     monomials.push_back(parsedMonomial);
 
-    if (llvm::is_contained(exponents, parsedMonomial.exponent)) {
-      llvm::SmallString<16> coeffString;
-      parsedMonomial.exponent.toStringSigned(coeffString);
-      parser.emitError(parser.getCurrentLocation())
-          << "at most one monomial may have exponent " << coeffString
-          << ", but found multiple";
-      return {};
-    }
-    exponents.insert(parsedMonomial.exponent);
-
     if (shouldParseMore)
       continue;
 
@@ -146,8 +135,13 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
             vars);
   }
 
-  Polynomial poly = Polynomial::fromMonomials(monomials);
-  return PolynomialAttr::get(parser.getContext(), poly);
+  auto result = Polynomial::fromMonomials(monomials);
+  if (failed(result)) {
+      parser.emitError(parser.getCurrentLocation())
+          << "parsed polynomial must have unique exponents among monomials";
+      return {};
+  }
+  return PolynomialAttr::get(parser.getContext(), result.value());
 }
 
 void RingAttr::print(AsmPrinter &p) const {
diff --git a/mlir/test/Dialect/Polynomial/attributes.mlir b/mlir/test/Dialect/Polynomial/attributes.mlir
index 16e385c520079b..3973ae3944335e 100644
--- a/mlir/test/Dialect/Polynomial/attributes.mlir
+++ b/mlir/test/Dialect/Polynomial/attributes.mlir
@@ -14,8 +14,8 @@
 
 // -----
 
-// expected-error at below {{at most one monomial may have exponent 2, but found multiple}}
 #my_poly = #polynomial.polynomial<5 + x**2 + 3x**2>
+// expected-error at below {{parsed polynomial must have unique exponents among monomials}}
 #ring1 = #polynomial.ring<coefficientType=i32, coefficientModulus=2837465, polynomialModulus=#my_poly>
 
 // -----

>From 429f253550833affb7c82fa3ea3f7e44403e709b Mon Sep 17 00:00:00 2001
From: Jeremy Kun <j2kun at users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:52:36 -0700
Subject: [PATCH 44/44] use Type instead of TypeAttr

---
 .../mlir/Dialect/Polynomial/IR/PolynomialAttributes.td    | 2 +-
 mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp   | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
index 723f6b7c2006b2..726f2ea8d3b7bc 100644
--- a/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
+++ b/mlir/include/mlir/Dialect/Polynomial/IR/PolynomialAttributes.td
@@ -64,7 +64,7 @@ def Polynomial_RingAttr : Polynomial_Attr<"Ring", "ring"> {
   }];
 
   let parameters = (ins
-    Builtin_TypeAttr: $coefficientType,
+    "Type": $coefficientType,
     OptionalParameter<"IntegerAttr">: $coefficientModulus,
     OptionalParameter<"PolynomialAttr">: $polynomialModulus
   );
diff --git a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
index 7730e110f71dc2..445cb0bb91ea02 100644
--- a/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
+++ b/mlir/lib/Dialect/Polynomial/IR/PolynomialAttributes.cpp
@@ -160,8 +160,8 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
   if (failed(parser.parseEqual()))
     return {};
 
-  TypeAttr typeAttr;
-  if (failed(parser.parseAttribute<TypeAttr>(typeAttr)))
+  Type ty;
+  if (failed(parser.parseType(ty)))
     return {};
 
   if (failed(parser.parseComma()))
@@ -172,7 +172,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
     if (failed(parser.parseEqual()))
       return {};
 
-    IntegerType iType = typeAttr.getValue().dyn_cast<IntegerType>();
+    IntegerType iType = ty.dyn_cast<IntegerType>();
     if (!iType) {
       parser.emitError(parser.getCurrentLocation(),
                        "coefficientType must specify an integer type");
@@ -205,7 +205,7 @@ Attribute RingAttr::parse(AsmParser &parser, Type type) {
   if (failed(parser.parseGreater()))
     return {};
 
-  return RingAttr::get(parser.getContext(), typeAttr, coefficientModulusAttr,
+  return RingAttr::get(parser.getContext(), ty, coefficientModulusAttr,
                        polyAttr);
 }
 



More information about the Mlir-commits mailing list