I was recently surprised to learn that the noprofile
attribute impacts function inlining. After some digging I found ⚙ D104810 [Inline] prevent inlining on noprofile mismatch which prevents inlining in certain cases. Suppose we add the noprofile
attribute to function foo()
, then suddenly 1) inlining is restricted for all calls inside foo()
unless they have the noprofile
attribute. Furthermore, 2) none of foo()
's callsites can be inlined unless the caller has the noprofile
attribute.
Restriction 1) makes sense if foo()
cannot safely be instrumented, but 2) doesn’t make sense to me. If we are worried about foo()
being inlined in a function with special code, then we should probably add the noinline
attribute anyway. Is there another reason we have restriction 2)?
On the other hand, we might want to prevent instrumentation in foo()
simply to reduce code size or performance overhead. If foo()
is called in lots of places, adding the noprofile
attribute can actually degrade performance because it likely won’t be inlined anywhere.
I’m wondering if it makes sense to create a new function attribute omitprofile
(feel free to suggest a better name ). The original
noprofile
attribute wouldn’t change, but would be used to ensure correctness. This new omitprofile
attribute would be used for performance instead of correctness reasons and so the inlining restrictions are not needed on it. When we want to prevent instrumentation using -fprofile-list
or -fprofile-function-groups
the new omitprofile
attribute would be used. So the only place the noprofile
attribute would be used is in source code. I’m not sure how others use -fprofile-list=
. If it is used to block instrumentation for correctness, then we can change the list format to support differentiating between blocking for correctness and blocking for performance.