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
Nick Desaulniers via llvm-dev
2021-Aug-09 18:16 UTC
[llvm-dev] Inline function not eventually inlined is removed
On Wed, Aug 4, 2021 at 4:46 AM David Chisnall via llvm-dev <llvm-dev at lists.llvm.org> wrote:> > > 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.Also, note that the meaning of `extern inline` changed between C90 and C99; it's one of the few semantic changes that are drastic changes that I know of between C standard revisions. You can get the previous behavior by either compiling with -std=c89/c90/gnu89, -fgnu89-inline, or using __attribute__((gnu_inline)) on function definitions. The behavior of the prior standard and gnu_inline was to NOT emit any symbol; a definition was provided only for the purposes of inline substitution. We've actually used this in the Linux kernel to provide two definitions of a function; one in C for inlining, one in assembler to avoid stack protectors and other compiler instrumentation (such as coverage and sanitizers), though now we have better constructs for describing these intents.> - 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)It's also useful to note that always (in always_inline) doesn't mean always. The machinery handling inline substitution can still bail. Use -Rpass-missed=inline (or maybe -Rpass-missed=always-inline) to learn *why*.> - If you're not sure but think you might mean `inline`, you really > mean to be writing C++ and not C. > > David-- Thanks, ~Nick Desaulniers