This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Remove the usage of __init in operator+
ClosedPublic

Authored by philnik on Apr 4 2022, 11:27 AM.

Details

Reviewers
ldionne
Mordante
Group Reviewers
Restricted Project
Commits
rG732920d847e5: [libc++] Remove the usage of __init in operator+
Summary

operator+ currently calls __init. This patch removes the usage of implementation details.

Diff Detail

Event Timeline

philnik created this revision.Apr 4 2022, 11:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 4 2022, 11:27 AM
philnik requested review of this revision.Apr 4 2022, 11:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 4 2022, 11:27 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne added inline comments.Apr 4 2022, 12:23 PM
libcxx/include/string
4180–4189

IMO this makes a lot more sense. However, I'm going to push the reasoning further and ask this: Would this *also* be equivalent?

using _String = basic_string<_CharT, _Traits, _Allocator>;
typename _String::size_type __lhs_sz = __lhs.size();
typename _String::size_type __rhs_sz = __rhs.size();
_String __r(_String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
__r.reserve(__lhs_sz + __rhs_sz);
__r.append(__lhs.data(), __lhs_sz);
__r.append(__rhs.data(), __rhs_sz);
return __r;

If so, then perhaps we don't really need the constructor after all?

philnik added inline comments.Apr 4 2022, 12:40 PM
libcxx/include/string
4180–4189

It think this is equivalent for runtime. For constant evaluation the constructor saves an allocation, but I don't think we care enough about that to add a new constructor.

philnik updated this revision to Diff 420449.Apr 5 2022, 4:22 AM
philnik marked an inline comment as done.
  • Address comments
philnik retitled this revision from [libc++] Add capacity constructor to string to [libc++] Remove the usage of __init in operator+.Apr 5 2022, 4:24 AM
philnik edited the summary of this revision. (Show Details)
Mordante accepted this revision as: Mordante.Apr 5 2022, 9:14 AM

LGTM! Since @ldionne had some request I leave the final approval to him.

We just looked at the codegen for the current code and the reserve-based version, and the reserve-based version ends up calling reserve, append and push_back separately, whereas the old version is simpler (it calls operator new and memcpy directly): https://godbolt.org/z/EWs78arre. I think this is due to the fact that the old version (with __init) can assume that we don't have any constructed state before, so it doesn't need to be as complicated. Also, push_back is exported in the dylib (which is a strange choice IMO since we ought to have a fast path). Can you run a quick benchmark to see if there's a noticeable difference? If so, we could go with this patch but also try to provide a fast path for push_back (which is probably a good idea regardless).

philnik updated this revision to Diff 421235.Apr 7 2022, 8:56 AM
  • Use constructor


The old constructor style was a bit slower than the __init approach. The new one is significantly faster.
Here is the benchmark:

ldionne requested changes to this revision.Apr 8 2022, 1:27 PM
ldionne added inline comments.
libcxx/include/string
751

Let's make it explicit.

Can you also add a comment documenting what this constructor does? Something like:

// Construct a string with the given allocator and enough storage to hold `__size` characters, but
// don't initialize the characters. The contents of the string, including the null terminator, must be
// initialized separately.
753

We need to handle the case where __size > max_size() like we used to in __init.

4205

This would need to be value_type() instead of '\0'. We support non-char character types as well.

This revision now requires changes to proceed.Apr 8 2022, 1:27 PM
philnik updated this revision to Diff 421697.Apr 9 2022, 12:31 AM
philnik marked 3 inline comments as done.
  • Address comments
  • Try to CI
philnik updated this revision to Diff 421730.Apr 9 2022, 7:20 AM
  • Try to fix CI
ldionne accepted this revision.Apr 11 2022, 6:35 AM

LGTM, thanks!

This revision is now accepted and ready to land.Apr 11 2022, 6:35 AM
This revision was automatically updated to reflect the committed changes.