From 93db40a147a219f6b5a60bdfe34afae33545deed Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Sat, 12 Sep 2015 01:07:37 +0000 Subject: Always_inline codegen rewrite. Current implementation may end up emitting an undefined reference for an "inline __attribute__((always_inline))" function by generating an "available_externally alwaysinline" IR function for it and then failing to inline all the calls. This happens when a call to such function is in dead code. As the inliner is an SCC pass, it does not process dead code. Libc++ relies on the compiler never emitting such undefined reference. With this patch, we emit a pair of 1. internal alwaysinline definition (called F.alwaysinline) 2a. A stub F() { musttail call F.alwaysinline } -- or, depending on the linkage -- 2b. A declaration of F. The frontend ensures that F.inlinefunction is only used for direct calls, and the stub is used for everything else (taking the address of the function, really). Declaration (2b) is emitted in the case when "inline" is meant for inlining only (like __gnu_inline__ and some other cases). This approach, among other nice properties, ensures that alwaysinline functions are always internal, making it impossible for a direct call to such function to produce an undefined symbol reference. This patch is based on ideas by Chandler Carruth and Richard Smith. llvm-svn: 247494 --- clang/test/Frontend/optimization-remark-line-directive.c | 3 ++- clang/test/Frontend/optimization-remark.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'clang/test/Frontend') diff --git a/clang/test/Frontend/optimization-remark-line-directive.c b/clang/test/Frontend/optimization-remark-line-directive.c index f4c0011fb4f..23d63c9aa1e 100644 --- a/clang/test/Frontend/optimization-remark-line-directive.c +++ b/clang/test/Frontend/optimization-remark-line-directive.c @@ -5,8 +5,9 @@ // RUN: %clang_cc1 %s -Rpass=inline -gline-tables-only -dwarf-column-info -emit-llvm-only -verify int foo(int x, int y) __attribute__((always_inline)); +// expected-remark@+1 {{foo.alwaysinline inlined into foo}} int foo(int x, int y) { return x + y; } -// expected-remark@+2 {{foo inlined into bar}} expected-note@+2 {{could not determine the original source location for /bad/path/to/original.c:1230:25}} +// expected-remark@+2 {{foo.alwaysinline inlined into bar}} expected-note@+2 {{could not determine the original source location for /bad/path/to/original.c:1230:25}} #line 1230 "/bad/path/to/original.c" int bar(int j) { return foo(j, j - 2); } diff --git a/clang/test/Frontend/optimization-remark.c b/clang/test/Frontend/optimization-remark.c index 6ada0030a70..604fec00204 100644 --- a/clang/test/Frontend/optimization-remark.c +++ b/clang/test/Frontend/optimization-remark.c @@ -32,6 +32,8 @@ // CHECK-NOT: !llvm.dbg.cu = !{ int foo(int x, int y) __attribute__((always_inline)); +// expected-remark@+2 {{foo.alwaysinline should always be inlined}} +// expected-remark@+1 {{foo.alwaysinline inlined into foo}} int foo(int x, int y) { return x + y; } float foz(int x, int y) __attribute__((noinline)); @@ -45,7 +47,7 @@ int bar(int j) { // expected-remark@+5 {{foz will not be inlined into bar}} // expected-remark@+4 {{foz should never be inlined}} // expected-remark@+3 {{foz will not be inlined into bar}} -// expected-remark@+2 {{foo should always be inlined}} -// expected-remark@+1 {{foo inlined into bar}} +// expected-remark@+2 {{foo.alwaysinline should always be inlined}} +// expected-remark@+1 {{foo.alwaysinline inlined into bar}} return foo(j, j - 2) * foz(j - 2, j); } -- cgit v1.2.3