Mariusz Sikora via llvm-dev
2021-Aug-02 17:05 UTC
[llvm-dev] Inline function not eventually inlined is removed
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 at 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 at 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 at lists.llvm.org > >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >> > > >_______________________________________________ > >LLVM Developers mailing list > >llvm-dev at lists.llvm.org > >https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-- Pozdrawiam Mariusz Sikora -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210802/89b8b1fd/attachment.html>
Fāng-ruì Sòng via llvm-dev
2021-Aug-02 18:17 UTC
[llvm-dev] Inline function not eventually inlined is removed
On Mon, Aug 2, 2021 at 10:05 AM Mariusz Sikora <msikora87 at 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.This is a user error. You may be looking for -fgnu89-inline & C99 inline documentation. An extern inline definition is needed. Inlining can paper over the user error. clang decides that inlining is not good because the trip count is too large. If you decrease the number of iterations, you may find that clang inlines the function and the linker error goes away.> On Fri, Jul 30, 2021 at 7:16 PM Fangrui Song <maskray at 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 at 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 at lists.llvm.org >> >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> >> >> >> >_______________________________________________ >> >LLVM Developers mailing list >> >llvm-dev at lists.llvm.org >> >https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> > > > -- > Pozdrawiam > Mariusz Sikora
David Blaikie via llvm-dev
2021-Aug-02 19:18 UTC
[llvm-dev] Inline function not eventually inlined is removed
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 at 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 at 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 at 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 at lists.llvm.org >> >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> >> >> >> >_______________________________________________ >> >LLVM Developers mailing list >> >llvm-dev at lists.llvm.org >> >https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >> >> > > -- > Pozdrawiam > Mariusz Sikora >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210802/f664987d/attachment.html>
David Chisnall via llvm-dev
2021-Aug-04 11:46 UTC
[llvm-dev] Inline function not eventually inlined is removed
On 02/08/2021 18:05, Mariusz Sikora via llvm-dev 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. C++ `inline` means 'the definition is provided in line with the declaration, the compiler and linker are responsible for ensuring that exactly one definition exists in the final binary' C `inline` means 'this definition is provided in line with a declaration and may be used by the compiler in preference to one that a linker finds' C `inline extern` means 'a definition of this may appear in line with the declaration but please provide a canonical definition here for when the compiler decides not to emit it' C `inline static` means 'a definition exists here inline and it is not an error if this is not used. If it is, then it is private to this compilation unit and it is not an error for the same static function to exist in multiple compilation units'. *None* of these say anything about whether the compiler is required to inline the function, but they all specify what must happen to the original definition: - C++ `inline`: Must exist in at least one compilation unit and the linker must discard duplicates. - C `inline`: Must be eliminated - C `inline extern`: must be emitted, the linker should error if two definitions of the same inline extern function exist in different compilation units. - C `inline static`: It must be emitted if references to it exist in the object code but it may be eliminated if it is unused (including if all uses of it are inlined). Clang is generating IR that makes LLVM do exactly what the language semantics require: eliminate the definition. The `inline` keyword is probably the most confusingly named keyword in C/C++, though `static` comes close. The general rule of thumb for C is: - If you think you mean `inline` you probably mean `inline static`. - If you're really sure you mean `inline`, you almost certainly mean `__attribute__((always_inline))` or `__forceinline` (depending on whether you're writing GNU or Microsoft-flavoured C) - If you're not sure but think you might mean `inline`, you really mean to be writing C++ and not C. David