[Inliner] Respect noinline call site attribute
authorDávid Bolvanský <david.bolvansky@gmail.com>
Mon, 14 Feb 2022 17:35:29 +0000 (18:35 +0100)
committerDávid Bolvanský <david.bolvansky@gmail.com>
Mon, 14 Feb 2022 17:35:52 +0000 (18:35 +0100)
```
always_inline foo() { }

bar () {

noinline foo();
}
```
We should prefer call site attribute over attribute on decl.

Related to https://reviews.llvm.org/D119061

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D119579

llvm/lib/Analysis/InlineCost.cpp
llvm/test/Transforms/Inline/call-site-attrs.ll [new file with mode: 0644]

index 5333626..2a1a976 100644 (file)
@@ -2864,6 +2864,9 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision(
   // Calls to functions with always-inline attributes should be inlined
   // whenever possible.
   if (Call.hasFnAttr(Attribute::AlwaysInline)) {
+    if (Call.getAttributes().hasFnAttr(Attribute::NoInline))
+      return InlineResult::failure("noinline call site attribute");
+
     auto IsViable = isInlineViable(*Callee);
     if (IsViable.isSuccess())
       return InlineResult::success();
diff --git a/llvm/test/Transforms/Inline/call-site-attrs.ll b/llvm/test/Transforms/Inline/call-site-attrs.ll
new file mode 100644 (file)
index 0000000..50af344
--- /dev/null
@@ -0,0 +1,59 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
+
+; Always prefer call site attribute over function attribute
+
+define internal i32 @inner1() {
+; CHECK: @inner1(
+  ret i32 1
+}
+
+define i32 @outer1() {
+; CHECK-LABEL: @outer1(
+; CHECK: call
+
+   %r = call i32 @inner1() noinline
+   ret i32 %r
+}
+
+define internal i32 @inner2() alwaysinline {
+; CHECK: @inner2(
+  ret i32 1
+}
+
+define i32 @outer2() {
+; CHECK-LABEL: @outer2(
+; CHECK: call
+
+   %r = call i32 @inner2() noinline
+   ret i32 %r
+}
+
+define i32 @inner3() alwaysinline {
+; CHECK: @inner3(
+  ret i32 1
+}
+
+define i32 @outer3() {
+; CHECK-LABEL: @outer3(
+; CHECK: call
+
+   %r = call i32 @inner3() noinline
+   ret i32 %r
+}
+
+define i32 @inner4() noinline {
+; CHECK: @inner4(
+  ret i32 1
+}
+
+define i32 @outer4() {
+; CHECK-LABEL: @outer4(
+; CHECK-NOT: call
+; CHECK: ret
+
+   %r = call i32 @inner4() alwaysinline
+
+   ret i32 %r
+}
+