[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