The CodeGen is missing to add the NoInline attribute to the target of a call, even the declaration has the attribute presented. This fixes it.
Details
Diff Detail
Unit Tests
Event Timeline
If this won't be used at all I guess the compiler should throw a warning at least.
One example comes to my mind, and it includes LTO (and cross-compile unit inlining).
$ cat test-1.c extern int __attribute__((noinline)) bar(void); int foo() { int v1 = bar(); if (v1 > 100) return 0; v1--; return v1; } $ cat $ cat test-2.c int __attribute__((always_inline)) bar(void); int foo2() { int v2 = bar(); if (v2 > 1000) return 0; v2++; return v2; } $ cat test.c #include <stdio.h> extern int foo(); extern int foo2(); int bar() { int x; scanf("%d", &x); ++x; return x; } int main() { int i = foo(); int j = foo2(); return i - j; } $ clang test.c -g -S -flto -emit-llvm $ clang test-1.c -g -S -flto -emit-llvm $ clang test-2.c -g -S -flto -emit-llvm $ llvm-link -S -o linked.ll test-1.ll test-2.ll test.ll $ opt -S -O1 linked.ll -o optimized.ll
Having these simple compile units, I can expect that compiler is able to inline the bar() into foo2() but not into foo().
Does LLVM model noinline as a call-site attribute in the way that would be necessary to get that effect? Also, are you actually having a problem here, or is this just something you noticed in the code?
I'm not sure we can warn about putting the attribute on a declaration; it's presumably still picked up by later definitions. There's probably a warning if they conflict, as they would if the first declaration was in a header included in both places, which is best practice.
It is being ignored completely, anyway :/ I am not having a problem, actually. It has been noticed accidentally when looking at some other attribute, but then I've started playing with some Debug Info cases (since that is the area I mostly work on) by dancing around with some cross CU referencing when using LTO -- all in all, this isn't necessary.
I'm not sure we can warn about putting the attribute on a declaration; it's presumably still picked up by later definitions. There's probably a warning if they conflict, as they would if the first declaration was in a header included in both places, which is best practice.
Oh yes... It is very hard to warn during compilation since we don't have the definition -- even though we have conflicts in test-1.c and test-2.c.
@rjmccall Thanks for your comments anyway :)