Do C functions with always_inline get consistently inlined in Swift?

On a large project, we have a lot of code like:

#if DEBUG
...
#endif

We'd like to replace it with if (IsDebug()) { ... } and the following in a header file:

__attribute__((always_inline)) bool IsDebug(void) {
  #if DEBUG
    return true;
  #else
    return false;
  #endif
}

Then, we expect the inlining to cause dead branches to be stripped. This is very important to avoid sensitive debug code reaching production. Can we trust that invocations of this function in Swift will have the same inlining and dead branch stripping? Does @inline(__always) for Swift functions behave any differently? Thanks.

Swift will honor always_inline on imported C functions, and LLVM will most likely behave the same as it would on the resulting code if it were in pure C as far as dead code elimination. Relying on dead branch stripping to remove sensitive information is not advisable in either language, IMO.

1 Like

A couple things to note:

  • always_inline is not quite a guarantee of inlining. In particular, in the presence of recursion, you may not get inlining, even if the recursion is on a dead branch after optimization. There are a few other scenarios in which it can fail to occur.

  • LLVM is pretty good about stripping dead branches, but it's not a formal guarantee.

  • If it ain't broke, don't fix it. This will probably work out OK, but it sounds like a lot of change for effectively zero real benefit.

2 Likes

Do you mean recursion specifically within the function marked always_inline? That makes sense. What other situations might prevent it, and is there a way of knowing when it's prevented?

Anything that isn't a direct call, like if you pass it around as a first-class value, or a call through a cast.

3 Likes

The benefits here is that code on all branches is verified by the compiler, meaning that CI catches errors for more schemes. There are still cases where preprocessor gating is needed, but for the many cases where a function will do, this is very nice to not accidentally break schemes.