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

Boyana Norris llvmlistbot at llvm.org
Sat Aug 2 21:18:15 PDT 2025


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

`Operation::clone` does not clone the properties of unregistered ops. This patch copies the opaque properties after the new operation is built.

fixes #151640

>From b0dbc5b1563b41e194479667dad95fa64e8d365a Mon Sep 17 00:00:00 2001
From: Boyana Norris <bnorris03 at gmail.com>
Date: Sat, 2 Aug 2025 21:14:04 -0700
Subject: [PATCH] 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:   }



More information about the Mlir-commits mailing list