1. 22
  1.  

  2. 2

    Hmm, but you could already control whether a function was inlined by defining versions with and without __attribute__((always_inline)), i.e.

    /* In header */
    __attribute__((inline)) static inline int foo_inline(int x) { ... };
    int foo(int x);
    
    /* In some .c file */
    int foo(int x) { return foo_inline(x); }
    

    __attribute__((flatten)) seems to be interesting chiefly because it recursively inlines functions, i.e. inlines functions called from foo_inline() above. Right?

    1. 2

      There’s still a couple of things thing missing. Today these are possible:

      • A function definition can require that it always be inlined by all callers (always_inline)
      • A function definition can require that it never be inlined by any caller (noinline)
      • A caller can require all functions are inlined, recursively unless the explicitly opt out.

      The obvious missing thing from this {inline, noinline} decision made by {caller, callee} quad is that there’s no per-function flag to specify that no functions are inlined unless they are always_inline. The other important ones that are missing are the ability to specify inline / no-inline at individual call sites, rather than at the calling function.

      Of course, this assumes that your compiler is doing full function inlining. With branch weights, there’s a lot of work on partial inlining, where you either inline only the hot paths or do things like inline guards that can probably be eliminated in some callers and outline the rest of the function.

      1. 1

        Must be in the same translation unit.

        1. 1

          is it true that always_inline always causes a function to be inlined? my impression is that it’s up to the compiler still, and in some/many cases things marked always_inline aren’t inlined, but i haven’t actually investigated this at all…

          1. 2

            There are various things that will prevent the compiler from inlining even in the presence of “always_inline”. For example:

            • recursive functions
            • C varargs
            • dynamic alloca()

            You can look at the LLVM source code to see what causes it to disable inlining. :)