[Mlir-commits] [mlir] [MLIR] Add no-inline attribute (PR #117392)

William Moses llvmlistbot at llvm.org
Fri Dec 13 11:58:01 PST 2024


https://github.com/wsmoses updated https://github.com/llvm/llvm-project/pull/117392

>From 5fc968780649d8ab2cbb6208aa8e9dca0a28d9c6 Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Fri, 22 Nov 2024 17:42:12 -0500
Subject: [PATCH 1/3] Add no-inline attribute

---
 mlir/include/mlir/Dialect/Func/IR/FuncOps.td   |  4 ++++
 mlir/include/mlir/Interfaces/CallInterfaces.td | 10 ++++++++++
 mlir/lib/Transforms/Utils/Inliner.cpp          |  4 ++++
 mlir/test/Transforms/inlining.mlir             |  9 +++++++++
 4 files changed, 27 insertions(+)

diff --git a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
index 22efe15aa83a50a..e0560c8e1e038a3 100644
--- a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
+++ b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
@@ -98,6 +98,10 @@ def CallOp : Func_Op<"call",
     void setCalleeFromCallable(CallInterfaceCallable callee) {
       (*this)->setAttr("callee", callee.get<SymbolRefAttr>());
     }
+
+    bool legalToInline() {
+      return !(*this)->hasAttr("noinline");
+    }
   }];
 
   let assemblyFormat = [{
diff --git a/mlir/include/mlir/Interfaces/CallInterfaces.td b/mlir/include/mlir/Interfaces/CallInterfaces.td
index c6002da0d491cef..35f33bf4797f6a2 100644
--- a/mlir/include/mlir/Interfaces/CallInterfaces.td
+++ b/mlir/include/mlir/Interfaces/CallInterfaces.td
@@ -80,6 +80,16 @@ def CallOpInterface : OpInterface<"CallOpInterface"> {
       /*methodBody=*/[{}], /*defaultImplementation=*/[{
         return ::mlir::call_interface_impl::resolveCallable($_op);
       }]
+    >,
+    InterfaceMethod<[{
+        Return whether a given call is legal to inline or not (assuming all other requirements are met,
+        like the callee is direct, the parent region supports multiple blocks and the resolved, etc).
+        This can be used to implement a `noinline`-like attribute.
+    }],
+      "bool", "legalToInline", (ins),
+      /*methodBody=*/[{}], /*defaultImplementation=*/[{
+        return true;
+      }]
     >
   ];
 }
diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp
index 8acfc96d2b611b2..1e329935b7807b2 100644
--- a/mlir/lib/Transforms/Utils/Inliner.cpp
+++ b/mlir/lib/Transforms/Utils/Inliner.cpp
@@ -712,6 +712,10 @@ bool Inliner::Impl::shouldInline(ResolvedCall &resolvedCall) {
   if (resolvedCall.call->hasTrait<OpTrait::IsTerminator>())
     return false;
 
+  // Don't inline calls which explicitly forbit inlining.
+  if (!resolvedCall.call.legalToInline())
+    return false;
+
   // Don't allow inlining if the target is a self-recursive function.
   if (llvm::count_if(*resolvedCall.targetNode,
                      [&](CallGraphNode::Edge const &edge) -> bool {
diff --git a/mlir/test/Transforms/inlining.mlir b/mlir/test/Transforms/inlining.mlir
index 79a2936b104fa1c..262047132064c7f 100644
--- a/mlir/test/Transforms/inlining.mlir
+++ b/mlir/test/Transforms/inlining.mlir
@@ -19,6 +19,15 @@ func.func @inline_with_arg(%arg0 : i32) -> i32 {
   return %0 : i32
 }
 
+// CHECK-LABEL: func @noinline_with_arg
+func.func @noinline_with_arg(%arg0 : i32) -> i32 {
+  // CHECK-NEXT: func_with_arg
+  // CHECK-NEXT: return
+
+  %0 = call @func_with_arg(%arg0) {"noinline"=""} : (i32) -> i32
+  return %0 : i32
+}
+
 // Inline a function that has multiple return operations.
 func.func @func_with_multi_return(%a : i1) -> (i32) {
   cf.cond_br %a, ^bb1, ^bb2

>From 78ecd803fc33ba80a8bbd720840fbfc2164a9181 Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Fri, 13 Dec 2024 14:53:41 -0500
Subject: [PATCH 2/3] update

---
 mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp b/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
index 719a74a29a62214..59e108c5b6c9ef4 100644
--- a/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
+++ b/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
@@ -23,6 +23,8 @@ namespace {
 struct FuncInlinerInterface : public DialectInlinerInterface {
   using DialectInlinerInterface::DialectInlinerInterface;
 
+  static constexpr const char* NoInlineAttrName = "noinline";
+
   //===--------------------------------------------------------------------===//
   // Analysis Hooks
   //===--------------------------------------------------------------------===//
@@ -30,7 +32,7 @@ struct FuncInlinerInterface : public DialectInlinerInterface {
   /// All call operations can be inlined.
   bool isLegalToInline(Operation *call, Operation *callable,
                        bool wouldBeCloned) const final {
-    return true;
+    return !call->hasAttr(NoInlineAttrName) && !callable->hasAttr(NoInlineAttrName);
   }
 
   /// All operations can be inlined.

>From 691eb770a65e4ad1e66d6f711d3fe92f360e4317 Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Fri, 13 Dec 2024 14:56:55 -0500
Subject: [PATCH 3/3] fix

---
 mlir/include/mlir/Dialect/Func/IR/FuncOps.td   |  4 ----
 mlir/include/mlir/Interfaces/CallInterfaces.td | 10 ----------
 mlir/lib/Transforms/Utils/Inliner.cpp          |  4 ----
 3 files changed, 18 deletions(-)

diff --git a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
index e0560c8e1e038a3..22efe15aa83a50a 100644
--- a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
+++ b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
@@ -98,10 +98,6 @@ def CallOp : Func_Op<"call",
     void setCalleeFromCallable(CallInterfaceCallable callee) {
       (*this)->setAttr("callee", callee.get<SymbolRefAttr>());
     }
-
-    bool legalToInline() {
-      return !(*this)->hasAttr("noinline");
-    }
   }];
 
   let assemblyFormat = [{
diff --git a/mlir/include/mlir/Interfaces/CallInterfaces.td b/mlir/include/mlir/Interfaces/CallInterfaces.td
index 35f33bf4797f6a2..c6002da0d491cef 100644
--- a/mlir/include/mlir/Interfaces/CallInterfaces.td
+++ b/mlir/include/mlir/Interfaces/CallInterfaces.td
@@ -80,16 +80,6 @@ def CallOpInterface : OpInterface<"CallOpInterface"> {
       /*methodBody=*/[{}], /*defaultImplementation=*/[{
         return ::mlir::call_interface_impl::resolveCallable($_op);
       }]
-    >,
-    InterfaceMethod<[{
-        Return whether a given call is legal to inline or not (assuming all other requirements are met,
-        like the callee is direct, the parent region supports multiple blocks and the resolved, etc).
-        This can be used to implement a `noinline`-like attribute.
-    }],
-      "bool", "legalToInline", (ins),
-      /*methodBody=*/[{}], /*defaultImplementation=*/[{
-        return true;
-      }]
     >
   ];
 }
diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp
index 1e329935b7807b2..8acfc96d2b611b2 100644
--- a/mlir/lib/Transforms/Utils/Inliner.cpp
+++ b/mlir/lib/Transforms/Utils/Inliner.cpp
@@ -712,10 +712,6 @@ bool Inliner::Impl::shouldInline(ResolvedCall &resolvedCall) {
   if (resolvedCall.call->hasTrait<OpTrait::IsTerminator>())
     return false;
 
-  // Don't inline calls which explicitly forbit inlining.
-  if (!resolvedCall.call.legalToInline())
-    return false;
-
   // Don't allow inlining if the target is a self-recursive function.
   if (llvm::count_if(*resolvedCall.targetNode,
                      [&](CallGraphNode::Edge const &edge) -> bool {



More information about the Mlir-commits mailing list