[PATCH] D127988: [Inliner] Introduce a backend option to suppress inlining of functions with large stack sizes
Wolfgang Pieb via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 16 10:50:54 PDT 2022
wolfgangp created this revision.
wolfgangp added a reviewer: aeubanks.
Herald added subscribers: ChuanqiXu, haicheng, hiraditya.
Herald added a project: All.
wolfgangp requested review of this revision.
Herald added a project: LLVM.
See discussion here <https://discourse.llvm.org/t/impact-of-stack-size-on-inlining-decisions/62472>.
-mllvm -inline-max-stacksize=<NBytes>
The intent is to give the user a way to prevent inlining of functions with large stack sizes. There is no change in behavior if the option is not used. I opted for direct suppression instead of adding to the inlining cost, as that would have added uncertainty.
Works for LTO as well.
If this is acceptable I'll add a clang option in a separate patch.
Any opinions or suggestions are welcome.
https://reviews.llvm.org/D127988
Files:
llvm/lib/Analysis/InlineCost.cpp
llvm/test/Transforms/Inline/inline-stacksize.ll
Index: llvm/test/Transforms/Inline/inline-stacksize.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/Inline/inline-stacksize.ll
@@ -0,0 +1,33 @@
+; Check the inliner doesn't inline a function with a stack size exceeding a given limit.
+; RUN: opt < %s -inline -S | FileCheck --check-prefixes=ALL,UNLIMITED %s
+; RUN: opt < %s -inline -S -inline-max-stacksize=256 | FileCheck --check-prefixes=ALL,LIMITED %s
+
+declare void @init([65 x i32]*)
+
+define internal i32 @foo() {
+ %1 = alloca [65 x i32], align 16
+ %2 = getelementptr inbounds [65 x i32], [65 x i32]* %1, i65 0, i65 0
+ call void @init([65 x i32]* %1)
+ %3 = load i32, i32* %2, align 4
+ ret i32 %3
+}
+
+define i32 @bar() {
+ %1 = call i32 @foo()
+ ret i32 %1
+; ALL: define {{.*}}@bar
+; ALL-NOT: define
+; UNLIMITED-NOT: call {{.*}}@foo
+; LIMITED: call {{.*}}@foo
+}
+
+; Check that, under the imposed limit, baz() inlines bar(), but not foo().
+define i32 @baz() {
+ %1 = call i32 @bar()
+ ret i32 %1
+; ALL: define {{.*}}@baz
+; UNLIMITED-NOT: call {{.*}}@bar
+; UNLIMITED-NOT: call {{.*}}@foo
+; LIMITED-NOT: call {{.*}}@bar
+; LIMITED: call {{.*}}@foo
+}
Index: llvm/lib/Analysis/InlineCost.cpp
===================================================================
--- llvm/lib/Analysis/InlineCost.cpp
+++ llvm/lib/Analysis/InlineCost.cpp
@@ -42,6 +42,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
+#include <limits>
using namespace llvm;
@@ -127,6 +128,13 @@
"inline-call-penalty", cl::Hidden, cl::init(25),
cl::desc("Call penalty that is applied per callsite when inlining"));
+static cl::opt<size_t>
+ StackSizeThreshold("inline-max-stacksize", cl::Hidden,
+ cl::init(std::numeric_limits<size_t>::max()),
+ cl::ZeroOrMore,
+ cl::desc("Do not inline functions with a stack size "
+ "that exceeds the specified limit"));
+
static cl::opt<bool> OptComputeFullInlineCost(
"inline-cost-full", cl::Hidden, cl::init(false), cl::ZeroOrMore,
cl::desc("Compute the full inline cost of a call site even when the cost "
@@ -2711,6 +2719,11 @@
if (!OnlyOneCallAndLocalLinkage && ContainsNoDuplicateCall)
return InlineResult::failure("noduplicate");
+ // If the callee's stack size exceeds the user-specified threshold,
+ // do not let it be inlined.
+ if (AllocatedSize > StackSizeThreshold)
+ return InlineResult::failure("stacksize");
+
return finalizeAnalysis();
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127988.437279.patch
Type: text/x-patch
Size: 2620 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220616/6383e215/attachment.bin>
More information about the llvm-commits
mailing list