[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