[Mlir-commits] [mlir] [MLIR] Add no-inline attribute (PR #117392)
William Moses
llvmlistbot at llvm.org
Fri Dec 13 11:57:06 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 b2942abbba6f7e3d074ea8722a35c0af78478394 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 | 6 +-----
mlir/lib/Transforms/Utils/Inliner.cpp | 4 ----
3 files changed, 1 insertion(+), 13 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..e10baaad4f810c2 100644
--- a/mlir/include/mlir/Interfaces/CallInterfaces.td
+++ b/mlir/include/mlir/Interfaces/CallInterfaces.td
@@ -85,11 +85,7 @@ def CallOpInterface : OpInterface<"CallOpInterface"> {
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