Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Clang] noinline call site attribute
Motivation: ``` int foo(int x, int y) { // any compiler will happily inline this function return x / y; } int test(int x, int y) { int r = 0; [[clang::noinline]] r += foo(x, y); // for some reason we don't want any inlining here return r; } ``` In 2018, @kuhar proposed "Introduce per-callsite inline intrinsics" in https://reviews.llvm.org/D51200 to solve this motivation case (and many others). This patch solves this problem with call site attribute. The implementation is "smaller" wrt approach which uses new intrinsics and thanks to https://reviews.llvm.org/D79121 (Add nomerge statement attribute to clang), we have got some basic infrastructure to deal with attrs on statements with call expressions. GCC devs are more inclined to call attribute solution as well, as builtins are problematic for them - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104187. But they have no patch proposal yet so.. We have free hands here. If this approach makes sense, next future steps would be support for call site attributes for always_inline / flatten. Reviewed By: aaron.ballman, kuhar Differential Revision: https://reviews.llvm.org/D119061
- Loading branch information
1 parent
96dea20
commit 223b824
Showing
11 changed files
with
178 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// RUN: %clang_cc1 -S -emit-llvm %s -triple x86_64-unknown-linux-gnu -o - | FileCheck %s | ||
|
||
bool bar(); | ||
void f(bool, bool); | ||
void g(bool); | ||
|
||
static int baz(int x) { | ||
return x * 10; | ||
} | ||
|
||
[[clang::noinline]] bool noi() { } | ||
|
||
void foo(int i) { | ||
[[clang::noinline]] bar(); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR:[0-9]+]] | ||
[[clang::noinline]] i = baz(i); | ||
// CHECK: call noundef i32 @_ZL3bazi({{.*}}) #[[NOINLINEATTR]] | ||
[[clang::noinline]] (i = 4, bar()); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
[[clang::noinline]] (void)(bar()); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
[[clang::noinline]] f(bar(), bar()); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
// CHECK: call void @_Z1fbb({{.*}}) #[[NOINLINEATTR]] | ||
[[clang::noinline]] [] { bar(); bar(); }(); // noinline only applies to the anonymous function call | ||
// CHECK: call void @"_ZZ3fooiENK3$_0clEv"(%class.anon* {{[^,]*}} %ref.tmp) #[[NOINLINEATTR]] | ||
[[clang::noinline]] for (bar(); bar(); bar()) {} | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
// CHECK: call noundef zeroext i1 @_Z3barv() #[[NOINLINEATTR]] | ||
bar(); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() | ||
[[clang::noinline]] noi(); | ||
// CHECK: call noundef zeroext i1 @_Z3noiv() | ||
noi(); | ||
// CHECK: call noundef zeroext i1 @_Z3noiv() | ||
[[gnu::noinline]] bar(); | ||
// CHECK: call noundef zeroext i1 @_Z3barv() | ||
} | ||
|
||
struct S { | ||
friend bool operator==(const S &LHS, const S &RHS); | ||
}; | ||
|
||
void func(const S &s1, const S &s2) { | ||
[[clang::noinline]]g(s1 == s2); | ||
// CHECK: call noundef zeroext i1 @_ZeqRK1SS1_({{.*}}) #[[NOINLINEATTR]] | ||
// CHECK: call void @_Z1gb({{.*}}) #[[NOINLINEATTR]] | ||
bool b; | ||
[[clang::noinline]] b = s1 == s2; | ||
// CHECK: call noundef zeroext i1 @_ZeqRK1SS1_({{.*}}) #[[NOINLINEATTR]] | ||
} | ||
|
||
// CHECK: attributes #[[NOINLINEATTR]] = { noinline } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// RUN: %clang_cc1 -verify -fsyntax-only %s | ||
|
||
int bar(); | ||
|
||
[[gnu::always_inline]] void always_inline_fn(void) { } | ||
[[gnu::flatten]] void flatten_fn(void) { } | ||
|
||
[[gnu::noinline]] void noinline_fn(void) { } | ||
|
||
void foo() { | ||
[[clang::noinline]] bar(); | ||
[[clang::noinline(0)]] bar(); // expected-error {{'noinline' attribute takes no arguments}} | ||
int x; | ||
[[clang::noinline]] x = 0; // expected-warning {{'noinline' attribute is ignored because there exists no call expression inside the statement}} | ||
[[clang::noinline]] { asm("nop"); } // expected-warning {{'noinline' attribute is ignored because there exists no call expression inside the statement}} | ||
[[clang::noinline]] label: x = 1; // expected-error {{'noinline' attribute only applies to functions and statements}} | ||
|
||
|
||
[[clang::noinline]] always_inline_fn(); // expected-warning {{statement attribute 'noinline' has higher precedence than function attribute 'always_inline'}} | ||
[[clang::noinline]] flatten_fn(); // expected-warning {{statement attribute 'noinline' has higher precedence than function attribute 'flatten'}} | ||
[[clang::noinline]] noinline_fn(); | ||
|
||
[[gnu::noinline]] bar(); // expected-warning {{attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements}} | ||
__attribute__((noinline)) bar(); // expected-warning {{attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements}} | ||
} | ||
|
||
[[clang::noinline]] static int i = bar(); // expected-error {{'noinline' attribute only applies to functions and statements}} |