Why does the `noprofile` attribute restrict inlining?

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 :slightly_smiling_face:). 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.

1 Like

CC @petrhosek @nickdesaulniers @MaskRay

Perhaps introduce an additional (and optional) option arg to indicate the intention? -fprofile-list=,<omit|forbid>

Similarly this can be done for the source level attribute.

1 Like

I’ve just published a few diffs:
https://reviews.llvm.org/D130806
https://reviews.llvm.org/D130807
https://reviews.llvm.org/D130808

I don’t know the reason why noprofile restricts inlining, that decision predates me, but I’m not sure if we can change it at this point without breaking existing users. Having a separate attribute might the best way forward.

I saw your discussion with @ilovepi on ⚙ D130807 [InstrProf] Add the skipprofile attribute. I’d personally avoid renaming the existing attribute, I don’t think the churn is worth it. I’d rather try and pick a name for the new attribute that communicates the intent. With that being said, I don’t have a lot of great suggestions. The best I could come up with is skipprofile; I also like @ilovepi’s nodirectprofile suggestion, but I’m not sure if any of those is better than omitprofile.

1 Like

Agree with what Petr says. I like ‘skipprofile’ name – as it communicates that the profiling is skipped by user – not because it can not be profiled (due to correctness reasons).

I decided to go with skipprofile. Thanks for the suggestion!