-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[ASan][libc++] String annotations optimizations fix with lambda #76200
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
[ASan][libc++] String annotations optimizations fix with lambda #76200
Conversation
This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - : __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) { - : __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) { However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne.
@llvm/pr-subscribers-libcxx Author: Tacet (AdvenamTacet) ChangesThis commit addresses optimization and instrumentation challenges encountered within comma constructors.
However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne. Full diff: https://github.com/llvm/llvm-project/pull/76200.diff 1 Files Affected:
diff --git a/libcxx/include/string b/libcxx/include/string
index c676182fba8bac..03f6655bb1e76e 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -922,7 +922,10 @@ public:
// Turning off ASan instrumentation for variable initialization with _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
// does not work consistently during initialization of __r_, so we instead unpoison __str's memory manually first.
// __str's memory needs to be unpoisoned only in the case where it's a short string.
- : __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {
+ // Lambda is used because of optimization challenges encountered within comma constructors.
+ // Lambda with argument is correctly optimized, but it does not solve the problem with internal memory
+ // access macro.
+ : __r_([](basic_string &__s){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}(__str)) {
__str.__r_.first() = __rep();
__str.__annotate_new(0);
if (!__is_long())
|
This does not answer problem of Alternative is a function like that: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS
__compressed_pair<__rep, allocator_type> && __compressed_pair_id(basic_string &__str) {
if (!__str.__is_long())
__str.__annotate_delete();
return std::move(__str.__r_);
}
But I support lambda solution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with this (with a nitpick about the comment, which I think doesn't add much). This is kind of just a cleaner way to write the same thing as before, so even better if it fixes an optimization problem.
If this were making the code harder to read or more complicated, I'd ask for at least a regression test but in this case we can pretend that it's just a slight "refactoring", even though it is motivated by fixing a regression. It would be good to have some kind of regression test is that's feasible, though.
Since this change is motivated by issues reported by @EricWF, I think it would be relevant for Eric to stamp this change as well, to make sure it solves at least some of the problems he was seeing. |
It also makes the code easier to read. Code inside of the lambda is easy to read, instead of being a hack with comma operator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I would like to see some actual assembly before and after in the review thread. Could you provide a godbolt or diff of the assembly generated?
I found some other things unrelated to this review while looking at this, which I'll bring up offline.
@EricWF the difference is the same as described here: #76192 (comment) I can create dedicated examples to that patch on Monday. I also see a big benefit in readability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'm happy to generate the examples myself.
You've won me on the readability argument alone.
Difference between no string annotations and current head with flags Example (but not only) difference: mov byte ptr [rdi], r15b
movzx eax, byte ptr [rbp - 33]
mov byte ptr [rdi + 1], al
mov eax, dword ptr [rbp - 40]
mov dword ptr [rdi + 2], eax
movzx eax, word ptr [rbp - 36]
mov word ptr [rdi + 6], ax
mov qword ptr [rdi + 8], r14
mov qword ptr [rdi + 16], rbx is changed to mov byte ptr [rbx], r14b
movzx eax, byte ptr [rbp - 33]
mov byte ptr [rbx + 1], al
mov eax, dword ptr [rbp - 40]
mov dword ptr [rbx + 2], eax
movzx eax, word ptr [rbp - 36]
mov word ptr [rbx + 6], ax
mov qword ptr [rbx + 8], r12
mov qword ptr [rbx + 16], rdi
mov byte ptr [rbp - 33], 0
mov dword ptr [rbp - 40], 0
mov word ptr [rbp - 36], 0
xor edi, edi
xor r15d, r15d
test r15b, r15b
je .LBB1_16 But when we apply this PR, there is no difference between ASm before annotations were added and the new one: https://godbolt.org/z/Mb4bKsoGW |
It looks like this PR made a buildbot fail. I'm trying to understand why. Edit: |
This commit is a refactor (increases readability) and optimization fix. This is a fixed commit of llvm#76200 First reverthed here: llvm@1ea7a56 The difference is a return type of the lambda. Original description: This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - `: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {` - `: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {` However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne.
This commit is a refactor (increases readability) and optimization fix. This is a fixed commit of #76200 First reverthed here: 1ea7a56 Please, check original PR for details. The difference is a return type of the lambda. Original description: This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - `: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {` - `: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {` However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne.
…#76200) This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - `: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {` - `: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {` However, lambda with argument seems to be correctly optimized. The patch employs this. Use of lambda based on an idea from @ldionne.
…da (llvm#76200)" This reverts commit c68a9d2.
This commit is a refactor (increases readability) and optimization fix. This is a fixed commit of llvm#76200 First reverthed here: llvm@1ea7a56 Please, check original PR for details. The difference is a return type of the lambda. Original description: This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - `: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {` - `: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {` However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne.
This commit is a refactor (increases readability) and optimization fix. This is a fixed commit of llvm/llvm-project#76200 First reverthed here: llvm/llvm-project@1ea7a56 Please, check original PR for details. The difference is a return type of the lambda. Original description: This commit addresses optimization and instrumentation challenges encountered within comma constructors. 1) _LIBCPP_STRING_INTERNAL_MEMORY_ACCESS does not work in comma constructors. 2) Code inside comma constructors is not always correctly optimized. Problematic code examples: - `: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {` - `: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {` However, lambda with argument seems to be correctly optimized. This patch uses that fact. Use of lambda based on idea from @ldionne. NOKEYCHECK=True GitOrigin-RevId: 75efddba0f507282df479a6e296d67fd88aed489
This commit addresses optimization and instrumentation challenges encountered within comma constructors.
: __r_(((__str.__is_long() ? 0 : (__str.__annotate_delete(), 0)), std::move(__str.__r_))) {
: __r_(__r_([&](){ if(!__s.__is_long()) __s.__annotate_delete(); return std::move(__s.__r_);}())) {
However, lambda with argument seems to be correctly optimized. This patch uses that fact.
Use of lambda based on idea from @ldionne.