[Mlir-commits] [mlir] 5e28271 - [MLIR][Func] Enable strict property assembly format (#217300)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Sep 8 16:47:02 PDT 2026


Author: Mehdi Amini
Date: 2026-09-08T23:46:56Z
New Revision: 5e282718a88c5e19dfe3524dee0bc91a5fa1e224

URL: https://github.com/llvm/llvm-project/commit/5e282718a88c5e19dfe3524dee0bc91a5fa1e224
DIFF: https://github.com/llvm/llvm-project/commit/5e282718a88c5e19dfe3524dee0bc91a5fa1e224.diff

LOG: [MLIR][Func] Enable strict property assembly format (#217300)

Enable the strict properties assembly format mode for the Func dialect.
Spell inherent call attributes directly in the call formats so they are
no longer parsed from attr-dict in strict mode.

Assisted-by: Codex

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Func/IR/FuncOps.td
    mlir/lib/Dialect/Func/IR/FuncOps.cpp
    mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
    mlir/test/IR/core-ops.mlir
    mlir/test/Transforms/canonicalize.mlir
    mlir/test/Transforms/inlining.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
index 7d984092f5e33..d7a0d5fc4f277 100644
--- a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
+++ b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
@@ -22,6 +22,7 @@ def Func_Dialect : Dialect {
   let name = "func";
   let cppNamespace = "::mlir::func";
   let hasConstantMaterializer = 1;
+  let useStrictPropertiesInAssemblyFormat = 1;
 }
 
 // Base class for Func dialect ops.
@@ -120,7 +121,8 @@ def CallOp : Func_Op<"call",
   }];
 
   let assemblyFormat = [{
-    $callee `(` $operands `)` attr-dict `:` functional-type($operands, results)
+    $callee `(` $operands `)` prop-dict attr-dict `:`
+    functional-type($operands, results)
   }];
 }
 
@@ -197,7 +199,12 @@ def CallIndirectOp : Func_Op<"call_indirect", [
 
   let hasCanonicalizeMethod = 1;
   let assemblyFormat = [{
-    $callee `(` $callee_operands `)` attr-dict `:` type($callee)
+    $callee `(` $callee_operands `)`
+    oilist<`,`>(
+        `arg_attrs` `=` $arg_attrs
+      | `res_attrs` `=` $res_attrs
+    )
+    attr-dict `:` type($callee)
   }];
 }
 

diff  --git a/mlir/lib/Dialect/Func/IR/FuncOps.cpp b/mlir/lib/Dialect/Func/IR/FuncOps.cpp
index be31234f98d1f..6c41eeb36e9cb 100644
--- a/mlir/lib/Dialect/Func/IR/FuncOps.cpp
+++ b/mlir/lib/Dialect/Func/IR/FuncOps.cpp
@@ -86,14 +86,17 @@ FunctionType CallOp::getCalleeType() {
 LogicalResult CallIndirectOp::canonicalize(CallIndirectOp indirectCall,
                                            PatternRewriter &rewriter) {
   // Check that the callee is a constant callee.
-  SymbolRefAttr calledFn;
+  FlatSymbolRefAttr calledFn;
   if (!matchPattern(indirectCall.getCallee(), m_Constant(&calledFn)))
     return failure();
 
-  // Replace with a direct call.
-  rewriter.replaceOpWithNewOp<CallOp>(indirectCall, calledFn,
-                                      indirectCall.getResultTypes(),
-                                      indirectCall.getArgOperands());
+  // Replace with a direct call, preserving the call-site attributes.
+  auto directCall = CallOp::create(
+      rewriter, indirectCall.getLoc(), indirectCall.getResultTypes(), calledFn,
+      indirectCall.getArgOperands(), indirectCall.getArgAttrsAttr(),
+      indirectCall.getResAttrsAttr());
+  directCall->setDiscardableAttrs(indirectCall->getDiscardableAttrDictionary());
+  rewriter.replaceOp(indirectCall, directCall.getResults());
   return success();
 }
 

diff  --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
index d20f06fd3278a..dbe44cba4d98f 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir
@@ -599,8 +599,8 @@ func.func @equivalent_func_arg(%t0: tensor<?xf32> {bufferization.writable = true
   // CHECK: scf.for {{.*}} iter_args(%[[t1:.*]] = %[[arg0]])
   %1 = scf.for %iv = %c0 to %c10 step %c1 iter_args(%t1 = %t0) -> (tensor<?xf32>) {
     // CHECK: call @inner_func(%[[t1]])
-    // INHERENT: call @inner_func({{.*}}) {no_inline}
-    %3 = func.call @inner_func(%t1) {no_inline} : (tensor<?xf32>) -> tensor<?xf32>
+    // INHERENT: call @inner_func({{.*}}) <no_inline>
+    %3 = func.call @inner_func(%t1) <no_inline> : (tensor<?xf32>) -> tensor<?xf32>
     // CHECK: scf.yield %[[t1]]
     scf.yield %3 : tensor<?xf32>
   }

diff  --git a/mlir/test/IR/core-ops.mlir b/mlir/test/IR/core-ops.mlir
index 5d1583111541c..0ab6775068a51 100644
--- a/mlir/test/IR/core-ops.mlir
+++ b/mlir/test/IR/core-ops.mlir
@@ -201,6 +201,25 @@ func.func @calls(%arg0: i32) {
   // CHECK: %4 = call_indirect %f_0(%arg0) : (i32) -> i32
   %3 = "func.call_indirect"(%f_0, %arg0) : ((i32) -> i32, i32) -> i32
 
+  // CHECK: %{{.*}} = call @return_op(%arg0) <arg_attrs = [{test.arg}],
+  // CHECK-SAME: res_attrs = [{test.res = 42 : i64}], no_inline> : (i32) -> i32
+  %4 = call @return_op(%arg0) <arg_attrs = [{test.arg}],
+      res_attrs = [{test.res = 42 : i64}], no_inline> : (i32) -> i32
+
+  // CHECK: %{{.*}} = call_indirect %f_0(%arg0)
+  // CHECK-SAME: arg_attrs = [{test.arg}],
+  // CHECK-SAME: res_attrs = [{test.res = 42 : i64}] : (i32) -> i32
+  %5 = call_indirect %f_0(%arg0) res_attrs = [{test.res = 42 : i64}],
+      arg_attrs = [{test.arg}] : (i32) -> i32
+
+  // CHECK: call @affine_apply() <arg_attrs = [], res_attrs = []>
+  // CHECK-SAME: {test.marker} : () -> ()
+  call @affine_apply() <arg_attrs = [], res_attrs = []> {test.marker} : () -> ()
+
+  // CHECK: call_indirect %f() arg_attrs = [], res_attrs = []
+  // CHECK-SAME: {test.marker} : () -> ()
+  call_indirect %f() arg_attrs = [], res_attrs = [] {test.marker} : () -> ()
+
   return
 }
 

diff  --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir
index 8e02c06a0a293..8337cccbb7538 100644
--- a/mlir/test/Transforms/canonicalize.mlir
+++ b/mlir/test/Transforms/canonicalize.mlir
@@ -587,6 +587,22 @@ func.func @indirect_call_folding() {
   return
 }
 
+func.func @attributed_indirect_target(%arg: i32) -> i32 {
+  return %arg : i32
+}
+
+// CHECK-LABEL: func @attributed_indirect_call_folding
+// CHECK-SAME: (%[[ARG:.*]]: i32)
+func.func @attributed_indirect_call_folding(%arg: i32) -> i32 {
+  // CHECK: %[[RESULT:.*]] = call @attributed_indirect_target(%[[ARG]])
+  // CHECK-SAME: <arg_attrs = [{test.arg}], res_attrs = [{test.res}]>
+  // CHECK-SAME: {test.discardable} : (i32) -> i32
+  %fn = constant @attributed_indirect_target : (i32) -> i32
+  %result = call_indirect %fn(%arg) arg_attrs = [{test.arg}],
+      res_attrs = [{test.res}] {test.discardable} : (i32) -> i32
+  return %result : i32
+}
+
 //
 // IMPORTANT NOTE: the operations in this test are exactly those produced by
 // lowering affine.apply affine_map<(i) -> (i mod 42)> to standard operations.  Please only

diff  --git a/mlir/test/Transforms/inlining.mlir b/mlir/test/Transforms/inlining.mlir
index da3f1a28deaac..5b3b1d8cd211f 100644
--- a/mlir/test/Transforms/inlining.mlir
+++ b/mlir/test/Transforms/inlining.mlir
@@ -28,7 +28,7 @@ func.func @noinline_with_arg(%arg0 : i32) -> i32 {
   // CHECK-NEXT: func_with_arg
   // CHECK-NEXT: return
 
-  %0 = call @func_with_arg(%arg0) {no_inline} : (i32) -> i32
+  %0 = call @func_with_arg(%arg0) <no_inline> : (i32) -> i32
   return %0 : i32
 }
 


        


More information about the Mlir-commits mailing list