-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[MLIR] Add no-inline attribute #117392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MLIR] Add no-inline attribute #117392
Conversation
|
@llvm/pr-subscribers-mlir-core @llvm/pr-subscribers-mlir Author: William Moses (wsmoses) ChangesFull diff: https://github.com/llvm/llvm-project/pull/117392.diff 4 Files Affected:
diff --git a/mlir/include/mlir/Dialect/Func/IR/FuncOps.td b/mlir/include/mlir/Dialect/Func/IR/FuncOps.td
index 22efe15aa83a50..e0560c8e1e038a 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 c6002da0d491ce..35f33bf4797f6a 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 8acfc96d2b611b..1e329935b7807b 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 79a2936b104fa1..262047132064c7 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
|
River707
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this should be a hook on CallInterface. The Inliner interface already allows for expressing various types of legality that could reference attributes: e.g.
| virtual bool isLegalToInline(Operation *call, Operation *callable, |
|
@River707 I moved the interface, per suggestion (pardon the delay) |
You can test this locally with the following command:git-clang-format --diff 76f0ff8210d56a050d2679926a2fdddd3a8c16d6 691eb770a65e4ad1e66d6f711d3fe92f360e4317 --extensions cpp -- mlir/lib/Dialect/Func/Extensions/InlinerExtension.cppView the diff from clang-format here.diff --git a/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp b/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
index 59e108c5b6..3e29ef5fd6 100644
--- a/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
+++ b/mlir/lib/Dialect/Func/Extensions/InlinerExtension.cpp
@@ -23,7 +23,7 @@ namespace {
struct FuncInlinerInterface : public DialectInlinerInterface {
using DialectInlinerInterface::DialectInlinerInterface;
- static constexpr const char* NoInlineAttrName = "noinline";
+ static constexpr const char *NoInlineAttrName = "noinline";
//===--------------------------------------------------------------------===//
// Analysis Hooks
@@ -32,7 +32,8 @@ struct FuncInlinerInterface : public DialectInlinerInterface {
/// All call operations can be inlined.
bool isLegalToInline(Operation *call, Operation *callable,
bool wouldBeCloned) const final {
- return !call->hasAttr(NoInlineAttrName) && !callable->hasAttr(NoInlineAttrName);
+ return !call->hasAttr(NoInlineAttrName) &&
+ !callable->hasAttr(NoInlineAttrName);
}
/// All operations can be inlined.
|
ftynse
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix clang-format.
| struct FuncInlinerInterface : public DialectInlinerInterface { | ||
| using DialectInlinerInterface::DialectInlinerInterface; | ||
|
|
||
| static constexpr const char* NoInlineAttrName = "noinline"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, would it make sense to have this as a proper ODS attribute on FuncOp and CallOp? LLVM dialect already has one
| OptionalAttr<UnitAttr>:$no_inline, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it'd be good to integrate this directly into the dialect if possible (makes it much cleaner to target). Otherwise you're at the whims of attribute propagation.
No description provided.