Skip to content

Add SVE implementations of bitset_meow_string - #6420

Merged
Stephan T. Lavavej (StephanTLavavej) merged 18 commits into
microsoft:mainfrom
hazzlim:bitset-meow-string-pr
Sep 16, 2026
Merged

Stephan T. Lavavej (StephanTLavavej) merged 18 commits into
microsoft:mainfrom
hazzlim:bitset-meow-string-pr

Conversation

@hazzlim

Copy link
Copy Markdown
Contributor

This PR adds SVE implementations of bitset_meow_string.

As discussed on the STL discord, the ACLE does not expose explicit predicate load/store intrinsics, so this implementation uses explicit casts to/from svbool_t*.

Benchmark Results ⏲️

Neoverse N2 (Cobalt 100)

benchmark speedup
BM_bitset_to_string_large_single<512, char> 1.016
BM_bitset_to_string_large_single<2048, char> 1.254
BM_bitset_to_string_large_single<512, wchar_t> 1.152
BM_bitset_to_string_large_single<2048, wchar_t> 1.433
bitset_from_string<length_type::char_count, 16, char> 1.087
bitset_from_string<length_type::char_count, 36, char> 1.163
bitset_from_string<length_type::char_count, 64, char> 1.408
bitset_from_string<length_type::char_count, 512, char> 1.674
bitset_from_string<length_type::char_count, 2048, char> 1.629
bitset_from_string<length_type::char_count, 16, wchar_t> 1.111
bitset_from_string<length_type::char_count, 36, wchar_t> 1.12
bitset_from_string<length_type::char_count, 64, wchar_t> 1.209
bitset_from_string<length_type::char_count, 512, wchar_t> 1.42
bitset_from_string<length_type::char_count, 2048, wchar_t> 1.452
bitset_from_string<length_type::null_term, 16, char> 1.148
bitset_from_string<length_type::null_term, 36, char> 1.241
bitset_from_string<length_type::null_term, 64, char> 1.327
bitset_from_string<length_type::null_term, 512, char> 1.333
bitset_from_string<length_type::null_term, 2048, char> 1.356
bitset_from_string<length_type::null_term, 16, wchar_t> 1.125
bitset_from_string<length_type::null_term, 36, wchar_t> 1.122
bitset_from_string<length_type::null_term, 64, wchar_t> 1.122
bitset_from_string<length_type::null_term, 512, wchar_t> 1.309
bitset_from_string<length_type::null_term, 2048, wchar_t> 1.264
bitset_from_stream<16, char> 1
bitset_from_stream<36, char> 1.025
bitset_from_stream<64, char> 1.045
bitset_from_stream<512, char> 1
bitset_from_stream<2048, char> 1
bitset_from_stream<16, wchar_t> 1.023
bitset_from_stream<36, wchar_t> 1.023
bitset_from_stream<64, wchar_t> 1.022
bitset_from_stream<512, wchar_t> 1
bitset_from_stream<2048, wchar_t> 1.045

@azure-pipelines

This comment was marked as resolved.

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) added performance Must go faster ARM64 Related to the ARM64 architecture labels Aug 31, 2026
This computation was identical.
This isn't needed to guard against a do-nothing for-loop.
…`[_Size_convert, _Size_chars)`.

`_Size_convert` is defined as `(_Size_chars <= _Size_bits) ? _Size_chars : _Size_bits`.

That's equivalent to: `(_Size_bits < _Size_chars) ? _Size_bits : _Size_chars`

`_Size_bits < _Size_chars` is the condition when this for-loop is going to do anything.
When it's going to do something, `_Size_convert` is `_Size_bits`, so the behavior is unchanged.
When it's going to be a no-op, `_Size_convert` is `_Size_chars`, so `_Ix < _Size_chars` is immediately false, so the no-op is unchanged.
…e_chars, _Size_convert` without confusing variation.
This matches how `_Size_convert` is used as the SVE threshold and makes much more sense.
When `_Size_chars <= _Size_bits`, we set `_Size_convert` to `_Size_chars` and vectorize that much. The remaining bits are memset.
…lidate_extra`, equivalent to the first part of `_Finish_sve`.
This makes more sense given how it's used.
Comment thread stl/src/vector_algorithms.cpp Outdated
Comment thread stl/src/vector_algorithms.cpp Outdated
Comment thread stl/src/vector_algorithms.cpp
Comment thread stl/src/vector_algorithms.cpp Outdated
Comment thread stl/src/vector_algorithms.cpp Outdated
Comment thread stl/src/vector_algorithms.cpp
Comment thread stl/src/vector_algorithms.cpp Outdated
@StephanTLavavej

Copy link
Copy Markdown
Member

Thanks! 😻 I pushed fairly significant refactorings to avoid code duplication, reusing the old _Fallback after splitting up its "extra" validation.

I kept the old _Fallback's practice of calling memset even when it might be zero-length (we could branch if it helps performance). Also I pushed one behavioral change for x64 (which I'm sure you don't care about 😹); your SVE threshold inspecting _Size_convert >= _Sve_vl() made me realize that the AVX2 threshold should be inspecting _Size_convert as well.

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) moved this from Initial Review to Ready To Merge in STL Code Reviews Sep 15, 2026
@StephanTLavavej

Copy link
Copy Markdown
Member

I'm mirroring this to the MSVC-internal repo. Please notify me if any further changes are pushed, otherwise no action is required.

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) moved this from Ready To Merge to Merging in STL Code Reviews Sep 15, 2026
@StephanTLavavej
Stephan T. Lavavej (StephanTLavavej) merged commit cb7268f into microsoft:main Sep 16, 2026
48 checks passed
@github-project-automation github-project-automation Bot moved this from Merging to Done in STL Code Reviews Sep 16, 2026
@StephanTLavavej

Copy link
Copy Markdown
Member

🧶 😻 🧵

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ARM64 Related to the ARM64 architecture performance Must go faster

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants