[Mlir-commits] [mlir] [MLIR][TableGen] Warn on APInt parameter without custom comparator (PR #135970)

Robert Konicar llvmlistbot at llvm.org
Thu Apr 17 01:24:03 PDT 2025


https://github.com/Jezurko updated https://github.com/llvm/llvm-project/pull/135970

>From b0d36fb79aa9663567415d7e5f4c287689be76a6 Mon Sep 17 00:00:00 2001
From: Robert Konicar <rkonicar at mail.muni.cz>
Date: Wed, 16 Apr 2025 15:20:55 +0200
Subject: [PATCH 1/3] [MLIR][TableGen] Warn on APInt parameter without custom
 comparator

---
 .../mlir/Dialect/SMT/IR/SMTAttributes.td      | 12 +------
 mlir/include/mlir/IR/BuiltinAttributes.td     |  2 +-
 mlir/include/mlir/TableGen/AttrOrTypeDef.h    |  6 +++-
 mlir/lib/Dialect/SMT/IR/SMTAttributes.cpp     | 36 -------------------
 mlir/lib/TableGen/AttrOrTypeDef.cpp           |  4 +++
 mlir/test/mlir-tblgen/apint-param-warn.td     | 17 +++++++++
 mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp   | 13 ++++++-
 7 files changed, 40 insertions(+), 50 deletions(-)
 create mode 100644 mlir/test/mlir-tblgen/apint-param-warn.td

diff --git a/mlir/include/mlir/Dialect/SMT/IR/SMTAttributes.td b/mlir/include/mlir/Dialect/SMT/IR/SMTAttributes.td
index 0909c9abad951..c1c5bfc76e055 100644
--- a/mlir/include/mlir/Dialect/SMT/IR/SMTAttributes.td
+++ b/mlir/include/mlir/Dialect/SMT/IR/SMTAttributes.td
@@ -45,21 +45,11 @@ def BitVectorAttr : AttrDef<SMTDialect, "BitVector", [
     present).
   }];
 
-  let parameters = (ins "llvm::APInt":$value);
+  let parameters = (ins APIntParameter<"">:$value);
 
   let hasCustomAssemblyFormat = true;
   let genVerifyDecl = true;
 
-  // We need to manually define the storage class because the generated one is
-  // buggy (because the APInt asserts matching bitwidth in the `==` operator and
-  // the generated storage uses that directly.
-  // Alternatively: add a type parameter to redundantly store the bitwidth of
-  // of the attribute type, it it's in the order before the 'value' it will be
-  // checked before the APInt equality (this is the reason it works for the
-  // builtin integer attribute), but would be more fragile (and we'd store
-  // duplicate data).
-  let genStorageClass = false;
-
   let builders = [
     AttrBuilder<(ins "llvm::StringRef":$value)>,
     AttrBuilder<(ins "uint64_t":$value, "unsigned":$width)>,
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index 6826d1a437775..50dcb8de1f7e7 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -700,7 +700,7 @@ def Builtin_IntegerAttr : Builtin_Attr<"Integer", "integer",
     false // A bool, i.e. i1, value.
     ```
   }];
-  let parameters = (ins AttributeSelfTypeParameter<"">:$type, "APInt":$value);
+  let parameters = (ins AttributeSelfTypeParameter<"">:$type, APIntParameter<"">:$value);
   let builders = [
     AttrBuilderWithInferredContext<(ins "Type":$type,
                                         "const APInt &":$value), [{
diff --git a/mlir/include/mlir/TableGen/AttrOrTypeDef.h b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
index c3d730e42ef70..8c1d399b39e0b 100644
--- a/mlir/include/mlir/TableGen/AttrOrTypeDef.h
+++ b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
@@ -68,7 +68,11 @@ class AttrOrTypeParameter {
   /// If specified, get the custom allocator code for this parameter.
   std::optional<StringRef> getAllocator() const;
 
-  /// If specified, get the custom comparator code for this parameter.
+  /// Return true if user defined comparator is specified.
+  bool hasCustomComparator() const;
+
+  /// Get the custom comparator code for this parameter or fallback to the
+  /// default.
   StringRef getComparator() const;
 
   /// Get the C++ type of this parameter.
diff --git a/mlir/lib/Dialect/SMT/IR/SMTAttributes.cpp b/mlir/lib/Dialect/SMT/IR/SMTAttributes.cpp
index c28f3558a02d2..3f40d6a42eafd 100644
--- a/mlir/lib/Dialect/SMT/IR/SMTAttributes.cpp
+++ b/mlir/lib/Dialect/SMT/IR/SMTAttributes.cpp
@@ -21,42 +21,6 @@ using namespace mlir::smt;
 // BitVectorAttr
 //===----------------------------------------------------------------------===//
 
-namespace mlir {
-namespace smt {
-namespace detail {
-struct BitVectorAttrStorage : public mlir::AttributeStorage {
-  using KeyTy = APInt;
-  BitVectorAttrStorage(APInt value) : value(std::move(value)) {}
-
-  KeyTy getAsKey() const { return value; }
-
-  // NOTE: the implementation of this operator is the reason we need to define
-  // the storage manually. The auto-generated version would just do the direct
-  // equality check of the APInt, but that asserts the bitwidth of both to be
-  // the same, leading to a crash. This implementation, therefore, checks for
-  // matching bit-width beforehand.
-  bool operator==(const KeyTy &key) const {
-    return (value.getBitWidth() == key.getBitWidth() && value == key);
-  }
-
-  static llvm::hash_code hashKey(const KeyTy &key) {
-    return llvm::hash_value(key);
-  }
-
-  static BitVectorAttrStorage *
-  construct(mlir::AttributeStorageAllocator &allocator, KeyTy &&key) {
-    return new (allocator.allocate<BitVectorAttrStorage>())
-        BitVectorAttrStorage(std::move(key));
-  }
-
-  APInt value;
-};
-} // namespace detail
-} // namespace smt
-} // namespace mlir
-
-APInt BitVectorAttr::getValue() const { return getImpl()->value; }
-
 LogicalResult BitVectorAttr::verify(
     function_ref<InFlightDiagnostic()> emitError,
     APInt value) { // NOLINT(performance-unnecessary-value-param)
diff --git a/mlir/lib/TableGen/AttrOrTypeDef.cpp b/mlir/lib/TableGen/AttrOrTypeDef.cpp
index 9e8f789d71b5e..ccb0a6c6c261e 100644
--- a/mlir/lib/TableGen/AttrOrTypeDef.cpp
+++ b/mlir/lib/TableGen/AttrOrTypeDef.cpp
@@ -278,6 +278,10 @@ std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {
   return getDefValue<StringInit>("allocator");
 }
 
+bool AttrOrTypeParameter::hasCustomComparator() const {
+  return getDefValue<StringInit>("comparator").has_value();
+}
+
 StringRef AttrOrTypeParameter::getComparator() const {
   return getDefValue<StringInit>("comparator").value_or("$_lhs == $_rhs");
 }
diff --git a/mlir/test/mlir-tblgen/apint-param-warn.td b/mlir/test/mlir-tblgen/apint-param-warn.td
new file mode 100644
index 0000000000000..ecfa97e5b5355
--- /dev/null
+++ b/mlir/test/mlir-tblgen/apint-param-warn.td
@@ -0,0 +1,17 @@
+// RUN: mlir-tblgen -gen-attrdef-decls -I %S/../../include %s 2>&1 | FileCheck %s
+
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/OpBase.td"
+
+def Test_Dialect: Dialect {
+  let name = "TestDialect";
+  let cppNamespace = "::test";
+}
+
+def RawAPIntAttr : AttrDef<Test_Dialect, "RawAPInt"> {
+  let mnemonic = "raw_ap_int";
+  let parameters = (ins "APInt":$value);
+  let hasCustomAssemblyFormat = 1;
+}
+
+// CHECK: apint-param-warn.td:11:5: warning: Using a raw APInt parameter
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index cf0d827942949..4b0a72ec60a0b 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -678,8 +678,19 @@ void DefGen::emitStorageClass() {
   emitConstruct();
   // Emit the storage class members as public, at the very end of the struct.
   storageCls->finalize();
-  for (auto &param : params)
+  for (auto &param : params) {
+     if (param.getCppType().contains("APInt") &&
+         !param.hasCustomComparator()) {
+       PrintWarning(
+           def.getLoc(),
+           "Using a raw APInt parameter without a custom comparator is "
+           "discouraged because an assert in the equality operator is "
+           "triggered when the two APInts have different bit widths. This can "
+           "lead to unexpected crashes. Consider using an `APIntParameter` or "
+           "providing a custom comparator.");
+     }
     storageCls->declare<Field>(param.getCppType(), param.getName());
+  }
 }
 
 //===----------------------------------------------------------------------===//

>From 5992ca8420bdd135de158247bd4cfa0ab24f52df Mon Sep 17 00:00:00 2001
From: Robert Konicar <rkonicar at mail.muni.cz>
Date: Wed, 16 Apr 2025 16:37:11 +0200
Subject: [PATCH 2/3] fixup! [MLIR][TableGen] Warn on APInt parameter without
 custom comparator

---
 mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index 4b0a72ec60a0b..c34cbfe47dc35 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -679,16 +679,15 @@ void DefGen::emitStorageClass() {
   // Emit the storage class members as public, at the very end of the struct.
   storageCls->finalize();
   for (auto &param : params) {
-     if (param.getCppType().contains("APInt") &&
-         !param.hasCustomComparator()) {
-       PrintWarning(
-           def.getLoc(),
-           "Using a raw APInt parameter without a custom comparator is "
-           "discouraged because an assert in the equality operator is "
-           "triggered when the two APInts have different bit widths. This can "
-           "lead to unexpected crashes. Consider using an `APIntParameter` or "
-           "providing a custom comparator.");
-     }
+    if (param.getCppType().contains("APInt") && !param.hasCustomComparator()) {
+      PrintWarning(
+          def.getLoc(),
+          "Using a raw APInt parameter without a custom comparator is "
+          "discouraged because an assert in the equality operator is "
+          "triggered when the two APInts have different bit widths. This can "
+          "lead to unexpected crashes. Consider using an `APIntParameter` or "
+          "providing a custom comparator.");
+    }
     storageCls->declare<Field>(param.getCppType(), param.getName());
   }
 }

>From 38b3e8bf140c2998a711eaa794eed46f5d78a07b Mon Sep 17 00:00:00 2001
From: Robert Konicar <robert.konicar at trailofbits.com>
Date: Thu, 17 Apr 2025 10:23:53 +0200
Subject: [PATCH 3/3] fixup!  [MLIR][TableGen] Warn on APInt parameter without
 custom comparator

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
index c34cbfe47dc35..1b314a149c418 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
@@ -683,10 +683,10 @@ void DefGen::emitStorageClass() {
       PrintWarning(
           def.getLoc(),
           "Using a raw APInt parameter without a custom comparator is "
-          "discouraged because an assert in the equality operator is "
+          "not supported because an assert in the equality operator is "
           "triggered when the two APInts have different bit widths. This can "
-          "lead to unexpected crashes. Consider using an `APIntParameter` or "
-          "providing a custom comparator.");
+          "lead to unexpected crashes. Use an `APIntParameter` or "
+          "provide a custom comparator.");
     }
     storageCls->declare<Field>(param.getCppType(), param.getName());
   }



More information about the Mlir-commits mailing list