Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ae6c3ed
Add replace benchmarks for all types
hazzlim Feb 5, 2026
f3b8b1c
Add SVE implementation of `replace`
hazzlim Feb 17, 2026
37a368b
Merge branch 'main' into replace-sve-pr
StephanTLavavej Apr 2, 2026
7437ad0
Add braces, fix endif comments, clang-format.
StephanTLavavej Apr 2, 2026
2adfc55
Further reduce test coverage for ARM64EC fallbacks.
StephanTLavavej Apr 2, 2026
9c45110
Add _VECTORIZED_REPLACE_1_2 macro
hazzlim Apr 2, 2026
9b3bdd5
Remove const to match declarations.
StephanTLavavej Apr 3, 2026
ae5d1f3
Add const.
StephanTLavavej Apr 3, 2026
4898076
Merge branch 'main' into replace-sve-pr
StephanTLavavej Jun 22, 2026
4bef3d4
Add a comment about the SVE vector length, citing the Arm ARM.
StephanTLavavej Jun 22, 2026
2e42751
Update test coverage to enable 1 and 2 bytes for ARM64/ARM64EC.
StephanTLavavej Jun 22, 2026
eb3dcbe
Merge branch 'main' into replace-sve-pr
StephanTLavavej Jul 3, 2026
1c9b962
Merge branch 'main' into replace-sve-pr
StephanTLavavej Jul 17, 2026
756cf3b
Restore the definition of `_VECTORIZED_FOR_X64_X86_ARM64`.
StephanTLavavej Jul 17, 2026
eefc86c
Disable `_VECTORIZED_REPLACE` and `_VECTORIZED_REPLACE_1_2` for ARM64…
StephanTLavavej Jul 17, 2026
b6facda
Also introduce `_VECTORIZED_FOR_ARM64`.
StephanTLavavej Jul 20, 2026
9e938b3
Adjust test coverage: replace() is always vectorized for ARM64 only.
StephanTLavavej Jul 17, 2026
da75150
Restore fallback test coverage for ARM64EC.
StephanTLavavej Jul 17, 2026
81ec21a
Drop unused `_Use_FEAT_MEOW()`.
StephanTLavavej Jul 17, 2026
6215eb0
Guard SVE for native ARM64 only, not ARM64EC.
StephanTLavavej Jul 17, 2026
ccb1cbd
Guard AVX2 codepaths against ARM64EC in `__std_replace_4`/`__std_repl…
StephanTLavavej Jul 17, 2026
5b75b3e
`<isa_availability.h>` now declares `__isa_enabled`.
StephanTLavavej Jul 20, 2026
a2d541d
Use `__processor_features_0_63` and `__arm64_xstate_features`.
StephanTLavavej Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion benchmarks/src/replace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ void rc(benchmark::State& state) {
}
}

// replace() is vectorized for 4 and 8 bytes only.
BENCHMARK(r<std::uint8_t>);
BENCHMARK(r<std::uint16_t>);
BENCHMARK(r<std::uint32_t>);
BENCHMARK(r<std::uint64_t>);

Expand Down
44 changes: 35 additions & 9 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ __declspec(noalias) bool __stdcall __std_includes_less_8u(
#endif // ^^^ _VECTORIZED_INCLUDES ^^^

#if _VECTORIZED_REPLACE
#if _VECTORIZED_REPLACE_1_2
__declspec(noalias) void __stdcall __std_replace_1(
void* _First, void* _Last, uint8_t _Old_val, uint8_t _New_val) noexcept;
__declspec(noalias) void __stdcall __std_replace_2(
void* _First, void* _Last, uint16_t _Old_val, uint16_t _New_val) noexcept;
#endif // ^^^ _VECTORIZED_REPLACE_1_2 ^^^

// TRANSITION, DevCom-10610477
__declspec(noalias) void __stdcall __std_replace_4(
void* _First, void* _Last, uint32_t _Old_val, uint32_t _New_val) noexcept;
Expand Down Expand Up @@ -383,14 +390,25 @@ bool _Includes_vectorized(
template <class _Ty, class _TVal1, class _TVal2>
__declspec(noalias) void _Replace_vectorized(
_Ty* const _First, _Ty* const _Last, const _TVal1 _Old_val, const _TVal2 _New_val) noexcept {
if constexpr (sizeof(_Ty) == 4) {
::__std_replace_4(
_First, _Last, _STD _Find_arg_cast<uint32_t>(_Old_val), _STD _Find_arg_cast<uint32_t>(_New_val));
} else if constexpr (sizeof(_Ty) == 8) {
::__std_replace_8(
_First, _Last, _STD _Find_arg_cast<uint64_t>(_Old_val), _STD _Find_arg_cast<uint64_t>(_New_val));
} else {
static_assert(false, "unexpected size");
#if _VECTORIZED_REPLACE_1_2
if constexpr (sizeof(_Ty) == 1) {
::__std_replace_1(
_First, _Last, _STD _Find_arg_cast<uint8_t>(_Old_val), _STD _Find_arg_cast<uint8_t>(_New_val));
} else if constexpr (sizeof(_Ty) == 2) {
::__std_replace_2(
_First, _Last, _STD _Find_arg_cast<uint16_t>(_Old_val), _STD _Find_arg_cast<uint16_t>(_New_val));
} else
#endif // ^^^ _VECTORIZED_REPLACE_1_2 ^^^
{
if constexpr (sizeof(_Ty) == 4) {
::__std_replace_4(
_First, _Last, _STD _Find_arg_cast<uint32_t>(_Old_val), _STD _Find_arg_cast<uint32_t>(_New_val));
} else if constexpr (sizeof(_Ty) == 8) {
::__std_replace_8(
_First, _Last, _STD _Find_arg_cast<uint64_t>(_Old_val), _STD _Find_arg_cast<uint64_t>(_New_val));
} else {
static_assert(false, "unexpected size");
}
}
}
#endif // ^^^ _VECTORIZED_REPLACE ^^^
Expand Down Expand Up @@ -491,10 +509,18 @@ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _T
#endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^

#if _VECTORIZED_REPLACE
#if _VECTORIZED_REPLACE_1_2
template <class _Iter>
constexpr bool _Have_masked_op_for_iter = true;
#else // ^^^ _VECTORIZED_REPLACE_1_2 / !_VECTORIZED_REPLACE_1_2 vvv
template <class _Iter>
constexpr bool _Have_masked_op_for_iter = sizeof(_Iter_value_t<_Iter>) >= 4; // avx masked op compatible size
#endif // ^^^ !_VECTORIZED_REPLACE_1_2 ^^^

// Can we activate the vector algorithms for replace?
template <class _Iter, class _Ty1>
constexpr bool _Vector_alg_in_replace_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty1> // can search for the value
&& sizeof(_Iter_value_t<_Iter>) >= 4; // avx masked op compatible size
&& _Have_masked_op_for_iter<_Iter>;

// Can we activate the vector algorithms for ranges::replace?
template <class _Iter, class _Ty1, class _Ty2>
Expand Down
21 changes: 16 additions & 5 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,26 @@ _STL_DISABLE_CLANG_WARNINGS
// In the STL's implementation, we inspect the following detection macros,
// because various algorithms are vectorized for various architectures.

// _CALL_ALL_X64_VECTOR_ALGORITHMS_ON_ARM64EC is a macro to test ARM64EC fallbacks for x64 algorithms.

#if !_USE_STD_VECTOR_ALGORITHMS
#define _VECTORIZED_FOR_X64_X86 0
#define _VECTORIZED_FOR_X64_X86_ARM64 0
#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 0
#elif defined(_M_ARM64) || (defined(_M_ARM64EC) && !defined(_CALL_ALL_X64_VECTOR_ALGORITHMS_ON_ARM64EC))
#define _VECTORIZED_FOR_ARM64 0
#elif defined(_M_ARM64EC) && !defined(_CALL_ALL_X64_VECTOR_ALGORITHMS_ON_ARM64EC) // normal ARM64EC usage
#define _VECTORIZED_FOR_X64_X86 0
#define _VECTORIZED_FOR_X64_X86_ARM64 0
#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1
#define _VECTORIZED_FOR_ARM64 0
#elif defined(_M_ARM64)
#define _VECTORIZED_FOR_X64_X86 0
#define _VECTORIZED_FOR_X64_X86_ARM64 1
#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1
#elif defined(_M_X64) || defined(_M_IX86)
#define _VECTORIZED_FOR_ARM64 1
#elif defined(_M_X64) || defined(_M_IX86) // also when testing ARM64EC fallbacks for x64 algorithms
#define _VECTORIZED_FOR_X64_X86 1
#define _VECTORIZED_FOR_X64_X86_ARM64 1
#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1
#define _VECTORIZED_FOR_ARM64 0
#else // ^^^ known architecture / unknown architecture vvv
#error Unknown architecture
#endif // ^^^ unknown architecture ^^^
Expand All @@ -89,7 +98,7 @@ _STL_DISABLE_CLANG_WARNINGS
#define _VECTORIZED_MISMATCH _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
#define _VECTORIZED_REMOVE _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
#define _VECTORIZED_REMOVE_COPY _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
#define _VECTORIZED_REPLACE _VECTORIZED_FOR_X64_X86
#define _VECTORIZED_REPLACE _VECTORIZED_FOR_X64_X86_ARM64 // not ARM64EC, which lacks SVE
#define _VECTORIZED_REPLACE_COPY _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
#define _VECTORIZED_REVERSE _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
#define _VECTORIZED_REVERSE_COPY _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC
Expand All @@ -104,6 +113,8 @@ _STL_DISABLE_CLANG_WARNINGS
// as this does not improve performance over the scalar code.
#define _VECTORIZED_MINMAX_ELEMENT_64BIT_INT _VECTORIZED_FOR_X64_X86

#define _VECTORIZED_REPLACE_1_2 _VECTORIZED_FOR_ARM64 // not ARM64EC, which lacks SVE

#ifndef _USE_STD_VECTOR_FLOATING_ALGORITHMS
#if _USE_STD_VECTOR_ALGORITHMS && !defined(_M_FP_EXCEPT)
#define _USE_STD_VECTOR_FLOATING_ALGORITHMS 1
Expand Down
Loading
Loading