Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 21 additions & 11 deletions benchmarks/src/find_and_count.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,21 @@ enum class Op {

using namespace std;

template <class T, template <class> class Alloc, Op Operation>
template <class T, template <class> class Alloc, Op Operation, T FillVal = T{'0'}, T FoundVal = T{'1'}>
void bm(benchmark::State& state) {
const auto size = static_cast<size_t>(state.range(0));
const auto pos = static_cast<size_t>(state.range(1));

using Container =
conditional_t<Operation >= Op::StringFind, basic_string<T, char_traits<T>, Alloc<T>>, vector<T, Alloc<T>>>;

Container a(size, T{'0'});
Container a(size, FillVal);

if (pos < size) {
if constexpr (Operation == Op::StringRFind || Operation == Op::StringFindNotLastOne) {
a[size - pos - 1] = T{'1'};
a[size - pos - 1] = FoundVal;
} else {
a[pos] = T{'1'};
a[pos] = FoundVal;
}
} else {
if constexpr (Operation == Op::FindUnsized) {
Expand All @@ -49,19 +49,19 @@ void bm(benchmark::State& state) {

for (auto _ : state) {
if constexpr (Operation == Op::FindSized) {
benchmark::DoNotOptimize(ranges::find(a.begin(), a.end(), T{'1'}));
benchmark::DoNotOptimize(ranges::find(a.begin(), a.end(), FoundVal));
} else if constexpr (Operation == Op::FindUnsized) {
benchmark::DoNotOptimize(ranges::find(a.begin(), unreachable_sentinel, T{'1'}));
benchmark::DoNotOptimize(ranges::find(a.begin(), unreachable_sentinel, FoundVal));
} else if constexpr (Operation == Op::Count) {
benchmark::DoNotOptimize(ranges::count(a.begin(), a.end(), T{'1'}));
benchmark::DoNotOptimize(ranges::count(a.begin(), a.end(), FoundVal));
} else if constexpr (Operation == Op::StringFind) {
benchmark::DoNotOptimize(a.find(T{'1'}));
benchmark::DoNotOptimize(a.find(FoundVal));
} else if constexpr (Operation == Op::StringRFind) {
benchmark::DoNotOptimize(a.rfind(T{'1'}));
benchmark::DoNotOptimize(a.rfind(FoundVal));
} else if constexpr (Operation == Op::StringFindNotFirstOne) {
benchmark::DoNotOptimize(a.find_first_not_of(T{'0'}));
benchmark::DoNotOptimize(a.find_first_not_of(FillVal));
} else if constexpr (Operation == Op::StringFindNotLastOne) {
benchmark::DoNotOptimize(a.find_last_not_of(T{'0'}));
benchmark::DoNotOptimize(a.find_last_not_of(FillVal));
}
}
}
Expand All @@ -72,6 +72,13 @@ void common_args(auto bm) {
bm->Args({63, 62})->Args({31, 30})->Args({15, 14})->Args({7, 6});
}

struct point {
int16_t x;
int16_t y;

bool operator==(const point&) const = default;
};

BENCHMARK(bm<uint8_t, not_highly_aligned_allocator, Op::FindSized>)->Apply(common_args);
BENCHMARK(bm<uint8_t, highly_aligned_allocator, Op::FindSized>)->Apply(common_args);
BENCHMARK(bm<uint8_t, not_highly_aligned_allocator, Op::FindUnsized>)->Apply(common_args);
Expand Down Expand Up @@ -99,4 +106,7 @@ BENCHMARK(bm<char32_t, not_highly_aligned_allocator, Op::StringFindNotLastOne>)-
BENCHMARK(bm<uint64_t, not_highly_aligned_allocator, Op::FindSized>)->Apply(common_args);
BENCHMARK(bm<uint64_t, not_highly_aligned_allocator, Op::Count>)->Apply(common_args);

BENCHMARK(bm<point, not_highly_aligned_allocator, Op::FindSized>)->Apply(common_args);
BENCHMARK(bm<point, not_highly_aligned_allocator, Op::Count>)->Apply(common_args);

BENCHMARK_MAIN();
48 changes: 15 additions & 33 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -259,43 +259,31 @@ _Ty* _Is_sorted_until_vectorized(_Ty* const _First, _Ty* const _Last, const bool
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 (is_pointer_v<_Ty>) {
#ifdef _WIN64
::__std_replace_8(_First, _Last, reinterpret_cast<uint64_t>(_Old_val), reinterpret_cast<uint64_t>(_New_val));
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
::__std_replace_4(_First, _Last, reinterpret_cast<uint32_t>(_Old_val), reinterpret_cast<uint32_t>(_New_val));
#endif // ^^^ !defined(_WIN64) ^^^
} else if constexpr (sizeof(_Ty) == 4) {
::__std_replace_4(_First, _Last, static_cast<uint32_t>(_Old_val), static_cast<uint32_t>(_New_val));
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, static_cast<uint64_t>(_Old_val), static_cast<uint64_t>(_New_val));
::__std_replace_8(
_First, _Last, _STD _Find_arg_cast<uint64_t>(_Old_val), _STD _Find_arg_cast<uint64_t>(_New_val));
} else {
_STL_INTERNAL_STATIC_ASSERT(false); // unexpected size
}
}

template <class _Ty, class _TVal>
_Ty* _Search_n_vectorized(_Ty* const _First, _Ty* const _Last, const size_t _Count, const _TVal _Val) noexcept {
if constexpr (is_pointer_v<_Ty>) {
#ifdef _WIN64
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_8(_First, _Last, _Count, reinterpret_cast<uint64_t>(_Val))));
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_4(_First, _Last, _Count, reinterpret_cast<uint32_t>(_Val))));
#endif // ^^^ !defined(_WIN64) ^^^
} else if constexpr (sizeof(_Ty) == 1) {
if constexpr (sizeof(_Ty) == 1) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_1(_First, _Last, _Count, static_cast<uint8_t>(_Val))));
static_cast<const _Ty*>(::__std_search_n_1(_First, _Last, _Count, _STD _Find_arg_cast<uint8_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 2) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_2(_First, _Last, _Count, static_cast<uint16_t>(_Val))));
static_cast<const _Ty*>(::__std_search_n_2(_First, _Last, _Count, _STD _Find_arg_cast<uint16_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 4) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_4(_First, _Last, _Count, static_cast<uint32_t>(_Val))));
static_cast<const _Ty*>(::__std_search_n_4(_First, _Last, _Count, _STD _Find_arg_cast<uint32_t>(_Val))));
} else if constexpr (sizeof(_Ty) == 8) {
return const_cast<_Ty*>(
static_cast<const _Ty*>(::__std_search_n_8(_First, _Last, _Count, static_cast<uint64_t>(_Val))));
static_cast<const _Ty*>(::__std_search_n_8(_First, _Last, _Count, _STD _Find_arg_cast<uint64_t>(_Val))));
} else {
_STL_INTERNAL_STATIC_ASSERT(false); // unexpected size
}
Expand All @@ -319,20 +307,14 @@ _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept {
template <class _Ty, class _TVal>
_Ty* _Remove_copy_vectorized(
const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest, const _TVal _Val) noexcept {
if constexpr (is_pointer_v<_Ty>) {
#ifdef _WIN64
return reinterpret_cast<_Ty*>(::__std_remove_copy_8(_First, _Last, _Dest, reinterpret_cast<uint64_t>(_Val)));
#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv
return reinterpret_cast<_Ty*>(::__std_remove_copy_4(_First, _Last, _Dest, reinterpret_cast<uint32_t>(_Val)));
#endif // ^^^ !defined(_WIN64) ^^^
} else if constexpr (sizeof(_Ty) == 1) {
return reinterpret_cast<_Ty*>(::__std_remove_copy_1(_First, _Last, _Dest, static_cast<uint8_t>(_Val)));
if constexpr (sizeof(_Ty) == 1) {
return reinterpret_cast<_Ty*>(::__std_remove_copy_1(_First, _Last, _Dest, _STD _Find_arg_cast<uint8_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 2) {
return reinterpret_cast<_Ty*>(::__std_remove_copy_2(_First, _Last, _Dest, static_cast<uint16_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_copy_2(_First, _Last, _Dest, _STD _Find_arg_cast<uint16_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 4) {
return reinterpret_cast<_Ty*>(::__std_remove_copy_4(_First, _Last, _Dest, static_cast<uint32_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_copy_4(_First, _Last, _Dest, _STD _Find_arg_cast<uint32_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 8) {
return reinterpret_cast<_Ty*>(::__std_remove_copy_8(_First, _Last, _Dest, static_cast<uint64_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_copy_8(_First, _Last, _Dest, _STD _Find_arg_cast<uint64_t>(_Val)));
} else {
_STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size
}
Expand Down
16 changes: 5 additions & 11 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,14 @@ void* __stdcall __std_remove_8(void* _First, void* _Last, uint64_t _Val) noexcep
_STD_BEGIN
template <class _Ty, class _TVal>
_Ty* _Remove_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept {
if constexpr (is_pointer_v<_Ty>) {
#ifdef _WIN64
return reinterpret_cast<_Ty*>(::__std_remove_8(_First, _Last, reinterpret_cast<uint64_t>(_Val)));
#else
return reinterpret_cast<_Ty*>(::__std_remove_4(_First, _Last, reinterpret_cast<uint32_t>(_Val)));
#endif
} else if constexpr (sizeof(_Ty) == 1) {
return reinterpret_cast<_Ty*>(::__std_remove_1(_First, _Last, static_cast<uint8_t>(_Val)));
if constexpr (sizeof(_Ty) == 1) {
return reinterpret_cast<_Ty*>(::__std_remove_1(_First, _Last, _STD _Find_arg_cast<uint8_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 2) {
return reinterpret_cast<_Ty*>(::__std_remove_2(_First, _Last, static_cast<uint16_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_2(_First, _Last, _STD _Find_arg_cast<uint16_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 4) {
return reinterpret_cast<_Ty*>(::__std_remove_4(_First, _Last, static_cast<uint32_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_4(_First, _Last, _STD _Find_arg_cast<uint32_t>(_Val)));
} else if constexpr (sizeof(_Ty) == 8) {
return reinterpret_cast<_Ty*>(::__std_remove_8(_First, _Last, static_cast<uint64_t>(_Val)));
return reinterpret_cast<_Ty*>(::__std_remove_8(_First, _Last, _STD _Find_arg_cast<uint64_t>(_Val)));
} else {
_STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size
}
Expand Down
Loading