Inquiry about Function Inlining in Clang/LLVM

Hello,

I recently applied the always_inline attribute to all functions in ReedSolomon.c to ensure complete function inlining during compilation. To assess the inlining behavior, I used the following command:

clang -O3 -Rpass=inline -Rpass-analysis=inline -Rpass-missed=inline inline_ReedSolomon.c
inline_ReedSolomon.c (15.9 KB)

Despite applying the always_inline attribute and setting the optimization level to -O3, the functions rsdec_204 and rsenc_204 were not fully inlined. I am curious to understand the reasons behind this behavior.

Are there specific considerations or limitations that I should be aware of regarding function inlining in this context? or inline pass behaves incorrectly in this situation.

This is the output of the objdump -d a.out | grep ">:" command, which shows that these functions remain in the binary.

Screenshot from 2023-07-22 22-04-48

Thank you.

Could you try to mark rsdec_204 and rsenc_204 as static ? They have external linkage.

How did you assess that they aren’t fully inlined? You screenshot only shows messages saying “inlined into ‘xxxx’”, I don’t see any inlining failure reported?

That does not mean that they haven’t been inlined everywhere though: they remain external function with global linkage. You can either make them private to the module (use static as mentioned above) or mark them inline (which in general is likely better than always_inline) which changes the linkage of these.

1 Like

Inlining means the function is totally removed from the binary, no longer part of the binary. When it reports function x inlined into function y, that means function x is not in the binary, not in debug info, and not elsewhere.

So, here is a wrong decision: when it reports rsdec_204 & rsenc_204 inlined into main, regardless of how it is defined in the source code, I should not see rsdec_204 & rsenc_204 in the final binary.

Inlining means a copy of the function is inlined in the other function. It does not mean that the function is removed from the binary. As mentioned above the two functions have external linkage and therefore are still in the final binary.

See https://reviews.llvm.org/D119061

Let me rephrase this. Visibility in the final binary relates to linkage, e.g., static or not. For inlining, you have various tools inline, noinline, always_inline, … . They are unrelated concepts.

2 Likes

I disabled inlining during compiling this code using -fno-inline O3, but even though the switchcase function is defined with the static keyword, it is not eliminated. However, when I used O3 without disabling inlining, it gets eliminated. Can I conclude that linkage alone is not enough to eliminate the function?
funcptr.c (1.7 KB)

The switchcase function is used, so the definition has to exist somewhere; either as an independent function, or by inlining it. If you disable inlining, it can’t be eliminated.

If it is inlined into all call sites, and is static, then it can be eliminated.