[Mlir-commits] [mlir] [mlir] Clone attrs of unregistered dialect ops (PR #151847)

Boyana Norris llvmlistbot at llvm.org
Mon Aug 4 12:17:16 PDT 2025


https://github.com/brnorris03 updated https://github.com/llvm/llvm-project/pull/151847

>From 0261c171eeb699d8108a1a2aa429abaca87fbfd1 Mon Sep 17 00:00:00 2001
From: Boyana Norris <brnorris03 at gmail.com>
Date: Sat, 2 Aug 2025 21:22:42 -0700
Subject: [PATCH 1/4] clone attrs of unregistered ops; fixes #151640

---
 mlir/lib/IR/Operation.cpp    | 11 +++++++++--
 mlir/test/IR/test-clone.mlir | 34 +++++++++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp
index 8bcfa465e4a22..75e1f408e3256 100644
--- a/mlir/lib/IR/Operation.cpp
+++ b/mlir/lib/IR/Operation.cpp
@@ -732,8 +732,15 @@ Operation *Operation::clone(IRMapping &mapper, CloneOptions options) {
     successors.push_back(mapper.lookupOrDefault(successor));
 
   // Create the new operation.
-  auto *newOp = create(getLoc(), getName(), getResultTypes(), operands, attrs,
-                       getPropertiesStorage(), successors, getNumRegions());
+  auto *newOp = create(getLoc(), getName(), getResultTypes(), operands,
+                       getAttrDictionary(), getPropertiesStorage(), successors,
+                       getNumRegions());
+
+  // The builder overwrites the opaque properties with the attributes; hence,
+  // copy them after building the operation.
+  if (!isRegistered())
+    newOp->copyProperties(getPropertiesStorage());
+
   mapper.map(this, newOp);
 
   // Clone the regions.
diff --git a/mlir/test/IR/test-clone.mlir b/mlir/test/IR/test-clone.mlir
index 0c07593aef32d..6bfc690bd1dbe 100644
--- a/mlir/test/IR/test-clone.mlir
+++ b/mlir/test/IR/test-clone.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(test-clone))" | FileCheck %s
+// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="builtin.module(func.func(test-clone))" --split-input-file | FileCheck %s
 
 module {
   func.func @fixpoint(%arg1 : i32) -> i32 {
@@ -33,3 +33,35 @@ module {
 // CHECK-NEXT:     }) : (i32) -> i32
 // CHECK-NEXT:     return %[[i1]] : i32
 // CHECK-NEXT:   }
+
+// -----
+
+func.func @clone_unregistered_with_attrs() {
+  "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = 3.14 : f32}> : () -> ()
+  "unregistered.bar"() : () -> ()
+  "unregistered.empty_dict"() <{}> : () -> ()
+  "unregistered.complex"() <{
+    array = [1, 2, 3],
+    dict = {key1 = 42 : i32, key2 = "value"},
+    nested = {inner = {deep = 100 : i64}}
+  }> : () -> ()
+  return
+}
+
+// CHECK: notifyOperationInserted: unregistered.foo
+// CHECK-NEXT: notifyOperationInserted: unregistered.bar
+// CHECK-NEXT: notifyOperationInserted: unregistered.empty_dict
+// CHECK-NEXT: notifyOperationInserted: unregistered.complex
+// CHECK-NEXT: notifyOperationInserted: func.return
+
+// CHECK:   func @clone_unregistered_with_attrs() {
+// CHECK-NEXT:     "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = [[PI:.+]] : f32}> : () -> ()
+// CHECK-NEXT:     "unregistered.bar"() : () -> ()
+// CHECK-NEXT:     "unregistered.empty_dict"() <{}> : () -> ()
+// CHECK-NEXT:     "unregistered.complex"() <{array = [1, 2, 3], dict = {key1 = 42 : i32, key2 = "value"}, nested = {inner = {deep = 100 : i64}}}> : () -> ()
+// CHECK-NEXT:     "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = [[PI]] : f32}> : () -> ()
+// CHECK-NEXT:     "unregistered.bar"() : () -> ()
+// CHECK-NEXT:     "unregistered.empty_dict"() <{}> : () -> ()
+// CHECK-NEXT:     "unregistered.complex"() <{array = [1, 2, 3], dict = {key1 = 42 : i32, key2 = "value"}, nested = {inner = {deep = 100 : i64}}}> : () -> ()
+// CHECK-NEXT:     return
+// CHECK-NEXT:   }

>From 50156265f4e1324869d516b359396e213a61afa2 Mon Sep 17 00:00:00 2001
From: Boyana Norris <brnorris03 at gmail.com>
Date: Sat, 2 Aug 2025 21:30:56 -0700
Subject: [PATCH 2/4] revert unnecessary change

Signed-off-by: Boyana Norris <brnorris03 at gmail.com>
---
 mlir/lib/IR/Operation.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp
index 75e1f408e3256..633a335121cc6 100644
--- a/mlir/lib/IR/Operation.cpp
+++ b/mlir/lib/IR/Operation.cpp
@@ -732,9 +732,8 @@ Operation *Operation::clone(IRMapping &mapper, CloneOptions options) {
     successors.push_back(mapper.lookupOrDefault(successor));
 
   // Create the new operation.
-  auto *newOp = create(getLoc(), getName(), getResultTypes(), operands,
-                       getAttrDictionary(), getPropertiesStorage(), successors,
-                       getNumRegions());
+  auto *newOp = create(getLoc(), getName(), getResultTypes(), operands, attrs,
+                       getPropertiesStorage(), successors, getNumRegions());
 
   // The builder overwrites the opaque properties with the attributes; hence,
   // copy them after building the operation.

>From 161b5ad7c481a41e1044924bb6c5831d7f96a297 Mon Sep 17 00:00:00 2001
From: Boyana Norris <brnorris03 at gmail.com>
Date: Mon, 4 Aug 2025 07:35:58 -0700
Subject: [PATCH 3/4] instead of copying properties after op creation in clone,
 initialize them as attributes in
 `OperationName::UnregisteredOpModel::initProperties`

---
 mlir/lib/IR/MLIRContext.cpp | 2 ++
 mlir/lib/IR/Operation.cpp   | 6 ------
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index 06ec1c85fb4d5..2d5381d43f863 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -884,6 +884,8 @@ int OperationName::UnregisteredOpModel::getOpPropertyByteSize() {
 void OperationName::UnregisteredOpModel::initProperties(
     OperationName opName, OpaqueProperties storage, OpaqueProperties init) {
   new (storage.as<Attribute *>()) Attribute();
+  if (init)
+    *storage.as<Attribute *>() = *init.as<Attribute *>();
 }
 void OperationName::UnregisteredOpModel::deleteProperties(
     OpaqueProperties prop) {
diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp
index 633a335121cc6..8bcfa465e4a22 100644
--- a/mlir/lib/IR/Operation.cpp
+++ b/mlir/lib/IR/Operation.cpp
@@ -734,12 +734,6 @@ Operation *Operation::clone(IRMapping &mapper, CloneOptions options) {
   // Create the new operation.
   auto *newOp = create(getLoc(), getName(), getResultTypes(), operands, attrs,
                        getPropertiesStorage(), successors, getNumRegions());
-
-  // The builder overwrites the opaque properties with the attributes; hence,
-  // copy them after building the operation.
-  if (!isRegistered())
-    newOp->copyProperties(getPropertiesStorage());
-
   mapper.map(this, newOp);
 
   // Clone the regions.

>From 06217a542eb423a763d85d01f00a02268052ba60 Mon Sep 17 00:00:00 2001
From: Boyana Norris <brnorris03 at gmail.com>
Date: Mon, 4 Aug 2025 09:31:56 -0700
Subject: [PATCH 4/4] address comments

---
 mlir/test/IR/test-clone.mlir | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/mlir/test/IR/test-clone.mlir b/mlir/test/IR/test-clone.mlir
index 6bfc690bd1dbe..f723efc1a2c53 100644
--- a/mlir/test/IR/test-clone.mlir
+++ b/mlir/test/IR/test-clone.mlir
@@ -18,7 +18,8 @@ module {
 // CHECK-NEXT: notifyOperationInserted: test.yield
 // CHECK-NEXT: notifyOperationInserted: func.return
 
-// CHECK:   func @fixpoint(%[[arg0:.+]]: i32) -> i32 {
+// CHECK-LABEL: func @fixpoint
+// CHECK-SAME:       (%[[arg0:.+]]: i32) -> i32 {
 // CHECK-NEXT:     %[[i0:.+]] = "test.use"(%[[arg0]]) ({
 // CHECK-NEXT:       %[[r2:.+]] = "test.use2"(%[[arg0]]) ({
 // CHECK-NEXT:         "test.yield2"(%[[arg0]]) : (i32) -> ()
@@ -54,7 +55,7 @@ func.func @clone_unregistered_with_attrs() {
 // CHECK-NEXT: notifyOperationInserted: unregistered.complex
 // CHECK-NEXT: notifyOperationInserted: func.return
 
-// CHECK:   func @clone_unregistered_with_attrs() {
+// CHECK-LABEL:  func @clone_unregistered_with_attrs() {
 // CHECK-NEXT:     "unregistered.foo"() <{bar = 1 : i64, flag = true, name = "test", value = [[PI:.+]] : f32}> : () -> ()
 // CHECK-NEXT:     "unregistered.bar"() : () -> ()
 // CHECK-NEXT:     "unregistered.empty_dict"() <{}> : () -> ()
@@ -63,5 +64,3 @@ func.func @clone_unregistered_with_attrs() {
 // CHECK-NEXT:     "unregistered.bar"() : () -> ()
 // CHECK-NEXT:     "unregistered.empty_dict"() <{}> : () -> ()
 // CHECK-NEXT:     "unregistered.complex"() <{array = [1, 2, 3], dict = {key1 = 42 : i32, key2 = "value"}, nested = {inner = {deep = 100 : i64}}}> : () -> ()
-// CHECK-NEXT:     return
-// CHECK-NEXT:   }



More information about the Mlir-commits mailing list