[Mlir-commits] [mlir] IntegerAttr accessor returning APInt by reference. (PR #187351)

Jacques Pienaar llvmlistbot at llvm.org
Mon Mar 23 02:47:02 PDT 2026


https://github.com/jpienaar updated https://github.com/llvm/llvm-project/pull/187351

>From e589c8036eb94f819e7f315e9fcc470a383ca329 Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Wed, 18 Mar 2026 18:27:17 +0000
Subject: [PATCH 1/2] IntegerAttr accessor returning APInt by reference.

IntegerAttr accessor getValue() returns an APInt by value. This works
well for the case where APInt is small, but leads to unnecessary copies
for larger bitwidths. This CL provides a new getValueRef() accessor that
returns a const APInt& directly from the internal storage.

I considered having the regular accessor return a const reference. This
would similar to what we do for StringAttr. This would change the
lifetime expectations of the existing attribute though.
---
 mlir/include/mlir/IR/BuiltinAttributes.td | 3 +++
 mlir/lib/CAPI/IR/BuiltinAttributes.cpp    | 2 +-
 mlir/lib/Dialect/Arith/IR/ArithOps.cpp    | 4 ++--
 mlir/lib/IR/BuiltinAttributes.cpp         | 4 +++-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index dced379d1f979..8a242b5127cc4 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -764,6 +764,9 @@ def Builtin_IntegerAttr : Builtin_Attr<"Integer", "integer",
     /// the attribute.  This traps on signless integers types!
     APSInt getAPSInt() const;
 
+    /// Return the integer value as a reference to an APInt.
+    const APInt &getValueRef() const;
+
   private:
     /// Return a boolean attribute. This is a special variant of the `get`
     /// method that is used by the MLIRContext to cache the boolean IntegerAttr
diff --git a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
index 65d72801889ec..08d57d6d3ee36 100644
--- a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
@@ -184,7 +184,7 @@ unsigned mlirIntegerAttrGetValueNumWords(MlirAttribute attr) {
 }
 
 void mlirIntegerAttrGetValueWords(MlirAttribute attr, uint64_t *words) {
-  const APInt &value = llvm::cast<IntegerAttr>(unwrap(attr)).getValue();
+  const APInt &value = llvm::cast<IntegerAttr>(unwrap(attr)).getValueRef();
   unsigned numWords = value.getNumWords();
   const uint64_t *rawData = value.getRawData();
   std::copy(rawData, rawData + numWords, words);
diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index f26aef625fd4a..b7bf29360c886 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -42,8 +42,8 @@ static IntegerAttr
 applyToIntegerAttrs(PatternRewriter &builder, Value res, Attribute lhs,
                     Attribute rhs,
                     function_ref<APInt(const APInt &, const APInt &)> binFn) {
-  APInt lhsVal = llvm::cast<IntegerAttr>(lhs).getValue();
-  APInt rhsVal = llvm::cast<IntegerAttr>(rhs).getValue();
+  const APInt &lhsVal = llvm::cast<IntegerAttr>(lhs).getValueRef();
+  const APInt &rhsVal = llvm::cast<IntegerAttr>(rhs).getValueRef();
   APInt value = binFn(lhsVal, rhsVal);
   return IntegerAttr::get(res.getType(), value);
 }
diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index bbbc9198a68ab..5b0a65832e799 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -362,6 +362,8 @@ StringAttr SymbolRefAttr::getLeafReference() const {
 // IntegerAttr
 //===----------------------------------------------------------------------===//
 
+const APInt &IntegerAttr::getValueRef() const { return getImpl()->value; }
+
 int64_t IntegerAttr::getInt() const {
   assert((getType().isIndex() || getType().isSignlessInteger()) &&
          "must be signless integer");
@@ -383,7 +385,7 @@ uint64_t IntegerAttr::getUInt() const {
 APSInt IntegerAttr::getAPSInt() const {
   assert(!getType().isSignlessInteger() &&
          "Signless integers don't carry a sign for APSInt");
-  return APSInt(getValue(), getType().isUnsignedInteger());
+  return APSInt(getValueRef(), getType().isUnsignedInteger());
 }
 
 LogicalResult IntegerAttr::verify(function_ref<InFlightDiagnostic()> emitError,

>From 31c06c4238c3c24170e6a056415d0064522cc12e Mon Sep 17 00:00:00 2001
From: Jacques Pienaar <jacques+gh at japienaar.info>
Date: Mon, 23 Mar 2026 09:40:34 +0000
Subject: [PATCH 2/2] Just change return type

---
 mlir/include/mlir/IR/AttrTypeBase.td      | 2 +-
 mlir/include/mlir/IR/BuiltinAttributes.td | 3 ---
 mlir/lib/CAPI/IR/BuiltinAttributes.cpp    | 2 +-
 mlir/lib/Dialect/Arith/IR/ArithOps.cpp    | 4 ++--
 mlir/lib/IR/BuiltinAttributes.cpp         | 4 +---
 5 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/mlir/include/mlir/IR/AttrTypeBase.td b/mlir/include/mlir/IR/AttrTypeBase.td
index 16f7f8b532521..ac7ac8fdb3039 100644
--- a/mlir/include/mlir/IR/AttrTypeBase.td
+++ b/mlir/include/mlir/IR/AttrTypeBase.td
@@ -390,7 +390,7 @@ class StringRefParameter<string desc = "", string value = ""> :
 // default APInt comparison operator asserts when the bitwidths differ, so
 // a custom implementation is necessary.
 class APIntParameter<string desc> :
-    AttrOrTypeParameter<"::llvm::APInt", desc> {
+    AttrOrTypeParameter<"::llvm::APInt", desc, "const ::llvm::APInt &"> {
   let comparator = "$_lhs.getBitWidth() == $_rhs.getBitWidth() && $_lhs == $_rhs";
 }
 
diff --git a/mlir/include/mlir/IR/BuiltinAttributes.td b/mlir/include/mlir/IR/BuiltinAttributes.td
index 8a242b5127cc4..dced379d1f979 100644
--- a/mlir/include/mlir/IR/BuiltinAttributes.td
+++ b/mlir/include/mlir/IR/BuiltinAttributes.td
@@ -764,9 +764,6 @@ def Builtin_IntegerAttr : Builtin_Attr<"Integer", "integer",
     /// the attribute.  This traps on signless integers types!
     APSInt getAPSInt() const;
 
-    /// Return the integer value as a reference to an APInt.
-    const APInt &getValueRef() const;
-
   private:
     /// Return a boolean attribute. This is a special variant of the `get`
     /// method that is used by the MLIRContext to cache the boolean IntegerAttr
diff --git a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
index 08d57d6d3ee36..65d72801889ec 100644
--- a/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/CAPI/IR/BuiltinAttributes.cpp
@@ -184,7 +184,7 @@ unsigned mlirIntegerAttrGetValueNumWords(MlirAttribute attr) {
 }
 
 void mlirIntegerAttrGetValueWords(MlirAttribute attr, uint64_t *words) {
-  const APInt &value = llvm::cast<IntegerAttr>(unwrap(attr)).getValueRef();
+  const APInt &value = llvm::cast<IntegerAttr>(unwrap(attr)).getValue();
   unsigned numWords = value.getNumWords();
   const uint64_t *rawData = value.getRawData();
   std::copy(rawData, rawData + numWords, words);
diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index b7bf29360c886..155edc5070a9d 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -42,8 +42,8 @@ static IntegerAttr
 applyToIntegerAttrs(PatternRewriter &builder, Value res, Attribute lhs,
                     Attribute rhs,
                     function_ref<APInt(const APInt &, const APInt &)> binFn) {
-  const APInt &lhsVal = llvm::cast<IntegerAttr>(lhs).getValueRef();
-  const APInt &rhsVal = llvm::cast<IntegerAttr>(rhs).getValueRef();
+  const APInt &lhsVal = llvm::cast<IntegerAttr>(lhs).getValue();
+  const APInt &rhsVal = llvm::cast<IntegerAttr>(rhs).getValue();
   APInt value = binFn(lhsVal, rhsVal);
   return IntegerAttr::get(res.getType(), value);
 }
diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp
index 5b0a65832e799..bbbc9198a68ab 100644
--- a/mlir/lib/IR/BuiltinAttributes.cpp
+++ b/mlir/lib/IR/BuiltinAttributes.cpp
@@ -362,8 +362,6 @@ StringAttr SymbolRefAttr::getLeafReference() const {
 // IntegerAttr
 //===----------------------------------------------------------------------===//
 
-const APInt &IntegerAttr::getValueRef() const { return getImpl()->value; }
-
 int64_t IntegerAttr::getInt() const {
   assert((getType().isIndex() || getType().isSignlessInteger()) &&
          "must be signless integer");
@@ -385,7 +383,7 @@ uint64_t IntegerAttr::getUInt() const {
 APSInt IntegerAttr::getAPSInt() const {
   assert(!getType().isSignlessInteger() &&
          "Signless integers don't carry a sign for APSInt");
-  return APSInt(getValueRef(), getType().isUnsignedInteger());
+  return APSInt(getValue(), getType().isUnsignedInteger());
 }
 
 LogicalResult IntegerAttr::verify(function_ref<InFlightDiagnostic()> emitError,



More information about the Mlir-commits mailing list