(original) (raw)

Looks like both Clang and GCC discard the inline function definition even if the function is not inlined and the definition is needed (because C requires there be a separate non-inline definition for correctness): https://godbolt.org/z/hPjv1d1db

This code is probably (in C++ standard terminology, I'm not sure what terminology the C standard uses) "invalid, no diagnostic required" - that's usually the language for stuff that can cause linker errors like this.

On Mon, Aug 2, 2021 at 10:05 AM Mariusz Sikora <msikora87@gmail.com> wrote:
I'm just trying to understand is this \_Code\_ undefined behavior or this is a bug in LLVM? Because why LLVM is removing functions without inlining it? For example GCC is not removing function event after inlining it.

On Fri, Jul 30, 2021 at 7:16 PM Fangrui Song <maskray@google.com> wrote:
On 2021-07-30, David Blaikie via llvm-dev wrote:
\>You're probably looking for some documentation about C inline semantics:
\>https://www.iar.com/knowledge/support/technical-notes/compiler/linker-error-undefined-external-for-inline-functions/

Additional notes: I think the -fgnu89-inline & C99 inline semantics were
designed explicitly the way so that vague linkage
(https://itanium-cxx-abi.github.io/cxx-abi/abi/prop-72-comdat.html) can
be avoided. The C inline behaviors are like always explicit
instantiation in C++.

(Seems that GNU has extensions for weak symbols on the a.out binary
format. Otherwise, if a binary format has neither weak symbol nor
COMDAT, vague linkage is not representable.)

\>On Fri, Jul 30, 2021 at 9:16 AM Mariusz Sikora via llvm-dev <
\>llvm-dev@lists.llvm.org> wrote:
\>
\>> Hello,
\>>
\>> I'm trying to understand why LLVM-12 is removing function which is marked
\>> inline despite the fact it was not inlined inside caller. Caller function
\>> still has a call to inline function and compilation is failing because of a
\>> lack of the symbol.
\>>
\>> Looking at debug logs I see:
\>>
\>> Inliner visiting SCC: sort: 1 call sites.
\>> Analyzing call of calculate... (caller:sort)
\>> .
\>> Cost: 960
\>> Threshold: 487
\>> NOT Inlining (cost=960, threshold=487), Call: call void
\>> @calculate(i32\* %a, i32\* %b)
\>>
\>> Code:
\>> int global = 0;
\>> void inline calculate(int a\[100\], int b\[100\]) {
\>> int i;
\>> #pragma unroll
\>> for (i = 0; i < 50; i++) {
\>> a\[i\] = b\[i\] + a\[i\];
\>> }
\>> }
\>>
\>> int sort(int a\[100\], int b\[100\]) {
\>> calculate(a, b);
\>> return a\[20\] + b\[30\] + global;
\>> }
\>>
\>> cli: clang -O3 -c inline1.c -o inline1\_clang.o
\>>
\>> ll file:
\>> ; Function Attrs: nounwind uwtable
\>> define dso\_local i32 @sort(i32\* %a, i32\* %b) local\_unnamed\_addr #0 {
\>> entry:
\>> tail call void @calculate(i32\* %a, i32\* %b)
\>> %arrayidx = getelementptr inbounds i32, i32\* %a, i64 20
\>> %0 = load i32, i32\* %arrayidx, align 4, !tbaa !2
\>> %arrayidx1 = getelementptr inbounds i32, i32\* %b, i64 30
\>> %1 = load i32, i32\* %arrayidx1, align 4, !tbaa !2
\>> %add = add nsw i32 %1, %0
\>> %2 = load i32, i32\* @global, align 4, !tbaa !2
\>> %add2 = add nsw i32 %add, %2
\>> ret i32 %add2
\>> }
\>>
\>> ; Function Attrs: inlinehint nounwind uwtable
\>> declare dso\_local void @calculate(i32\*, i32\*) local\_unnamed\_addr #1
\>>
\>> Thanks
\>> Mariusz Sikora
\>> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
\>> LLVM Developers mailing list
\>> llvm-dev@lists.llvm.org
\>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
\>>

\>\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
\>LLVM Developers mailing list
\>llvm-dev@lists.llvm.org
\>https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



--
Pozdrawiam
Mariusz Sikora