Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MCA] use std::function instead of function_ref when storing #91039

Merged

Conversation

boomanaiden154
Copy link
Contributor

This patch changes uses of llvm::function_ref for std::function when storing the callback inside of a class. The LLVM Programmer's manual mentions that llvm::function_ref is not safe to store as it contains pointers to external memory that are not guaranteed to exist in the future when it is stored.

This causes issues when setting callbacks inside of a class that manages MCA state. Passing a lambda directly to the set callback functions will end up causing UB/segfaults when the lambda is called as some external memory is now invalid. This is easy to work around (create a separate std::function, pass that into the function setting the callback), but isn't ideal.

This patch changes uses of llvm::function_ref for std::function when
storing the callback inside of a class. The LLVM Programmer's manual
mentions that llvm::function_ref is not safe to store as it contains
pointers to external memory that are not guaranteed to exist in the
future when it is stored.

This causes issues when setting callbacks inside of a class that manages
MCA state. Passing a lambda directly to the set callback functions will
end up causing UB/segfaults when the lambda is called as some external
memory is now invalid. This is easy to work around (create a separate
std::function, pass that into the function setting the callback), but
isn't ideal.
@mshockwave
Copy link
Member

Passing a lambda directly to the set callback functions will end up causing UB/segfaults when the lambda is called as some external memory is now invalid. This is easy to work around (create a separate std::function, pass that into the function setting the callback), but isn't ideal.

Yeah, in that case it definitely creates a dangling function pointer.

My original motivation behind using llvm::function_ref over std::function was that the latter is not cheap and sometime pretty expensive, and presumably it's not really difficult for the users (of IncrementalSrcManager and InstrBuilder) to store/manage the callbacks somewhere else. Do you find cases where storing callbacks outside these two classes challenging?

Copy link
Collaborator

@dwblaikie dwblaikie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fix the correctness issue/API subtlety first (function_ref isn't guaranteed to work in this way, even if the caller is very careful about preserving the functor for the lifetime of the object)

It'd be pretty easy for callers to get cleaned up/have the functors inlined into the call sites, etc, and break this code.

Some other tool should be created/used if there's a need for a lightweight functor reference that can be preserved in a longer-term situation like this.

@boomanaiden154
Copy link
Contributor Author

Doing some quick microbenchmarks, I'm only seeing a 2-3% performance regression for computing the cost of 10000 instructions, so I think fixing the correctness/API design issue is probably worth the performance cost. I'm going to land this and we can revisit this if the performance regression causes issues for people/or someone is willing to implement a lightweight function reference for this situation.

@boomanaiden154 boomanaiden154 merged commit 7ecdf62 into llvm:main May 20, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants