Thread: When to inline your *tors

  1. #16
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Which version of gcc/g++ have you been using. The common version for Windows (gcc-mingw) is about 3.4. It automatically inlines functions it sees fit.

    gcc 4.0 has "whole program optimization", which, like MS Visual Studio I believe in the most recent version(s) and I know Intel's compilers, allow the ENTIRE program to be considered for inlining, common subexpression, constant folding, and other such tricks that can not be solved with a traditional compiler that produces machine code immediately from each compilation unit (compilation unit == .cpp file in general, although sometimes that's not entirely true).

    Expect more of this from other compiler vendors, as machines get faster, memories bigger, etc. It used to be that a compiler needed to live within a few megabytes (or in the case of Turbo C, be able to generate code in a machine with 2MB of memory, and 640KB limit in some cases). Nowadays, machines have hundreds of megabytes or even gigabytes of RAM, and processors run 10-20x the speed they did 15 years ago. So we can allow the compiler to do more complicated "thinkiing", and still be able to compile more complicated code better than before.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #17
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Eh? I thought LTO was still an experimental branch of the current GCC development.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #18
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    Isn't function inlining only enabled during optimizations (i.e. by default optimization is off). In either case you may also be able to control the behaviour given some compile-time options:
    Quote Originally Posted by gcc
    -finline-limit=n
    By default, GCC limits the size of functions that can be inlined. This flag allows coarse control of this limit. n is the size of functions that can be inlined in number of pseudo instructions.

    Inlining is actually controlled by a number of parameters, which may be specified individually by using --param name=value. The -finline-limit=n option sets some of these parameters as follows:

    max-inline-insns-single
    is set to n/2.
    max-inline-insns-auto
    is set to n/2.

    See below for a documentation of the individual parameters controlling inlining and for the defaults of these parameters.

    Note: there may be no value to -finline-limit that results in default behavior.

    Note: pseudo instruction represents, in this particular context, an abstract measurement of function's size. In no way does it represent a count of assembly instructions and as such its exact meaning might change from one release to an another.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Of course it is enabled with optimizations only. If you do not enable optimizations, the compiler will leave the code alone - not make any changes.
    It does make sense to have it on when optimizations are not enabled.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    Quote Originally Posted by matsp View Post
    Which version of gcc/g++ have you been using. The common version for Windows (gcc-mingw) is about 3.4. It automatically inlines functions it sees fit.

    gcc 4.0 has "whole program optimization", which, like MS Visual Studio I believe in the most
    I'm very surprised to hear this. I have the Linux version of gcc 4.2, and I don't think it does whole program optmization. I tried Googling 'gcc "whole program optimization"' and get little indication that it does this. If they do it, they must call it something else.
    Besides, I once tested how GNU dealt with uncalled leaf functions. I defined a bogus function in a program that never gets called, and it was still included in the source. I would think that removing an uncalled leaf would be the most basic of LTOs.

  6. #21
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    I would think that removing an uncalled leaf would be the most basic of LTOs.
    Depends. What did you set its visibility to? In ELF systems, all symbols have external visibility by default, so the compiler can't remove them - a shared object might want to load the function.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #22
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    Quote Originally Posted by CornedBee View Post
    Depends. What did you set its visibility to? In ELF systems, all symbols have external visibility by default, so the compiler can't remove them - a shared object might want to load the function.
    I don't remember. I don't think I used any special keywords. It wasn't in a shared library, though, it was part of an executable. In what context do you mean "visibility"?

  8. #23
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    ELF visibility is whether other modules of the program can import a function. It applies equally to shared libraries (.so) as to core executables - ELF doesn't see much of a difference between them.
    If the visibility is the default public, then the linker cannot remove the function, because even shared objects loaded dynamically with dlopen() could reference it.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #24
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    Quote Originally Posted by CornedBee View Post
    ELF visibility is whether other modules of the program can import a function. It applies equally to shared libraries (.so) as to core executables - ELF doesn't see much of a difference between them.
    If the visibility is the default public, then the linker cannot remove the function, because even shared objects loaded dynamically with dlopen() could reference it.
    But what does that mean to the langauge? What keywords affect this "visibility"?

  10. #25
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    static, in the case of functions, will mean that the compiler KNOWS that no other module uses this function (unless it's used as a function pointer).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #26
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    That's compiler-specific. Most use GCC's __attribute__ syntax.
    E.g.
    Code:
    __attribute__((visibility("hidden"))) void fn(); // Function is not visible outside the module.
    __attribute__((visibility("default"))) void some_function(); // Function is visible.
    More info here:
    http://gcc.gnu.org/wiki/Visibility

    Edit: And yeah, static functions are marked hidden automatically. I think those in the unnamed namespace might be as well.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #27
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    Quote Originally Posted by CornedBee View Post
    That's compiler-specific. Most use GCC's __attribute__ syntax.
    E.g.
    Code:
    __attribute__((visibility("hidden"))) void fn(); // Function is not visible outside the module.
    __attribute__((visibility("default"))) void some_function(); // Function is visible.
    More info here:
    http://gcc.gnu.org/wiki/Visibility

    Edit: And yeah, static functions are marked hidden automatically. I think those in the unnamed namespace might be as well.
    Oh yeah, those. But those are visibility wrt the modules in which they are defined. A LTOer should be able to dock a function that's never called in an executable program, w/out hints from keywords or vendor-specific directives

  13. #28
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Angus View Post
    Oh yeah, those. But those are visibility wrt the modules in which they are defined. A LTOer should be able to dock a function that's never called in an executable program, w/out hints from keywords or vendor-specific directives
    That was entirely what Cornedbee was saying: Unless the LTO also understands what happens in every shared library/DLL that is used in conjunction with the application code, it can not know if a function is used as an external call from a shared library.

    For example, I could write some code in a shared library that does this:
    Code:
    extern void ErrorHandler(int errorcode);
    
    void Error(int errorcode)
    {
       CleanUp();
       ErrorHandler(errorcode);
    }
    then expect the main application to supply an ErrorHandler function that does something meaningfull to the applicaton.

    I admit this is not a COMMON scenario, but it's certainly possible - and the compiler can't assume (at least not without special options supplied) that this MUSTN'T happen.

    In fact I have seen code similar to that in RTOS implementations, where the user-supplied side is SUPPOSED to supply certain functions with certain names and arguments, or the system will not work.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #29
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Moreover, the executable can contain code like this:
    Code:
    for every file in directory
      if file is a shared library
        load shared library
        if shared library contains plugin init function
          register and initialize plugin
        else
          unload shared library
    So there's absolutely no way even an LTO optimizer can know for sure which dynamic libraries will be ultimately loaded.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  15. #30
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    Quote Originally Posted by matsp View Post
    That was entirely what Cornedbee was saying: Unless the LTO also understands what happens in every shared library/DLL that is used in conjunction with the application code, it can not know if a function is used as an external call from a shared library.

    For example, I could write some code in a shared library that does this:
    Code:
    extern void ErrorHandler(int errorcode);
    
    void Error(int errorcode)
    {
       CleanUp();
       ErrorHandler(errorcode);
    }
    then expect the main application to supply an ErrorHandler function that does something meaningfull to the applicaton.

    I admit this is not a COMMON scenario, but it's certainly possible - and the compiler can't assume (at least not without special options supplied) that this MUSTN'T happen.

    In fact I have seen code similar to that in RTOS implementations, where the user-supplied side is SUPPOSED to supply certain functions with certain names and arguments, or the system will not work.

    --
    Mats
    I see. I guess I assumed that in order for a shared library to do something like that, there would have to be some funny keywords to used to prepare ErrorHandler() for such usage.

    Still, I don't believe GNU does LTO, and if you can't rely on LTO the onus for optimization wrt inlining is on the programmer.
    Last edited by Angus; 10-28-2008 at 09:55 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Inline functions and inheritance
    By hpy_gilmore8 in forum C++ Programming
    Replies: 3
    Last Post: 01-14-2004, 06:46 PM
  3. Certain functions
    By Lurker in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2003, 01:26 AM
  4. bit shifting
    By Nor in forum C++ Programming
    Replies: 9
    Last Post: 08-08-2003, 11:55 AM
  5. Replies: 5
    Last Post: 09-17-2001, 06:18 AM

Tags for this Thread