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
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-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.