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
6 changes: 5 additions & 1 deletion stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -3738,7 +3738,11 @@ _NODISCARD _CONSTEXPR20 _VbIt _Find_vbool(_VbIt _First, const _VbIt _Last, const
const auto _SourceMask = _FirstSourceMask & _LastSourceMask;
const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask;
const auto _Count = _Countr_zero(_SelectVal);
return _Count == _VBITS ? _Last : _First + static_cast<_Iter_diff_t<_VbIt>>(_Count - _First._Myoff);
if (_Count == _VBITS) {
return _Last;
} else {
return _First + static_cast<_Iter_diff_t<_VbIt>>(_Count - _First._Myoff);
}
}

const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask;
Expand Down
77 changes: 57 additions & 20 deletions tests/std/tests/GH_000625_vector_bool_optimization/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
#include <random>
#include <vector>

#if _HAS_CXX20
#define CONSTEXPR20 constexpr
#else
#define CONSTEXPR20 inline
#endif

#pragma warning(disable : 4365) // conversion from 'unsigned __int64' to 'const __int64', signed/unsigned mismatch

using namespace std;
Expand All @@ -20,7 +26,7 @@ constexpr int blockSize = 32;
static_assert(blockSize == _VBITS, "Invalid block size");

// This test data is not random, but irregular enough to ensure confidence in the tests
const vector<bool> source = { //
constexpr bool source_raw[] = { //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false, //
Expand All @@ -39,8 +45,7 @@ const vector<bool> source = { //
true, false, true, false, true, true, true, false, //
true, false, true, false, true, true, true, false};


void test_fill_helper(const size_t length) {
CONSTEXPR20 void test_fill_helper(const size_t length) {
// No offset
{
vector<bool> result_true(length, true);
Expand Down Expand Up @@ -102,7 +107,7 @@ void test_fill_helper(const size_t length) {
}
}

bool test_fill() {
CONSTEXPR20 bool test_fill() {
// Empty
test_fill_helper(0);

Expand All @@ -126,7 +131,7 @@ bool test_fill() {
return true;
}

void test_find_helper(const size_t length) {
CONSTEXPR20 void test_find_helper(const size_t length) {
// No offset
{
vector<bool> input_true(length + 3, false);
Expand Down Expand Up @@ -160,7 +165,7 @@ void test_find_helper(const size_t length) {
}
}

bool test_find() {
CONSTEXPR20 bool test_find() {
// Empty range
test_find_helper(0);

Expand All @@ -178,10 +183,11 @@ bool test_find() {
return true;
}

void test_count_helper(const ptrdiff_t length) {
CONSTEXPR20 void test_count_helper(const ptrdiff_t length) {
const vector<bool> source(begin(source_raw), end(source_raw));
const int counts_true[] = {0, 1, 1, 2, 2, 3, 4, 5};
const int counts_false[] = {0, 0, 1, 1, 2, 2, 2, 2};
const auto expected = div(static_cast<int>(length), 8);
const div_t expected = {static_cast<int>(length) / 8, static_cast<int>(length) % 8};
// No offset
{
const auto result_true = static_cast<int>(count(source.cbegin(), next(source.cbegin(), length), true));
Expand All @@ -203,7 +209,7 @@ void test_count_helper(const ptrdiff_t length) {
}
}

bool test_count() {
CONSTEXPR20 bool test_count() {
// Empty range
test_count_helper(0);

Expand Down Expand Up @@ -259,7 +265,7 @@ void test_huge_vector_bool() {
assert(count(v.begin(), v.end(), false) == large_bit_diff - 3);
}

void test_copy_no_offset(const size_t length) {
CONSTEXPR20 void test_copy_no_offset(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -304,6 +310,8 @@ void test_copy_no_offset(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(source.begin(), next(source.begin(), length), dest.begin());
Expand Down Expand Up @@ -341,7 +349,7 @@ void test_copy_no_offset(const size_t length) {
}
}

void test_copy_offset_source(const size_t length) {
CONSTEXPR20 void test_copy_offset_source(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -389,6 +397,8 @@ void test_copy_offset_source(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length + 1), dest.begin());
Expand Down Expand Up @@ -427,7 +437,7 @@ void test_copy_offset_source(const size_t length) {
}
}

void test_copy_offset_dest(const size_t length) {
CONSTEXPR20 void test_copy_offset_dest(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -480,6 +490,8 @@ void test_copy_offset_dest(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length + 1, false);
const auto res_copy = copy(source.begin(), next(source.begin(), length), next(dest.begin()));
Expand Down Expand Up @@ -517,7 +529,7 @@ void test_copy_offset_dest(const size_t length) {
}
}

void test_copy_offset_match(const size_t length) {
CONSTEXPR20 void test_copy_offset_match(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -570,6 +582,8 @@ void test_copy_offset_match(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin()));
Expand Down Expand Up @@ -608,7 +622,7 @@ void test_copy_offset_match(const size_t length) {
}
}

void test_copy_offset_mismatch_leftshift(const size_t length) {
CONSTEXPR20 void test_copy_offset_mismatch_leftshift(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -661,6 +675,8 @@ void test_copy_offset_mismatch_leftshift(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length + 1, false);
const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin(), 2));
Expand Down Expand Up @@ -699,7 +715,7 @@ void test_copy_offset_mismatch_leftshift(const size_t length) {
}
}

void test_copy_offset_mismatch_rightshift(const size_t length) {
CONSTEXPR20 void test_copy_offset_mismatch_rightshift(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -754,6 +770,8 @@ void test_copy_offset_mismatch_rightshift(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin(), 2), next(source.begin(), length + 1), next(dest.begin()));
Expand Down Expand Up @@ -792,7 +810,7 @@ void test_copy_offset_mismatch_rightshift(const size_t length) {
}
}

void test_copy_offset_aligned(const size_t length) {
CONSTEXPR20 void test_copy_offset_aligned(const size_t length) {
vector<bool> result;
switch (length) {
case 3:
Expand Down Expand Up @@ -845,6 +863,8 @@ void test_copy_offset_aligned(const size_t length) {
assert(false);
}

const vector<bool> source(begin(source_raw), end(source_raw));

{
vector<bool> dest(length, false);
const auto res_copy = copy(next(source.begin(), 9), next(source.begin(), length + 8), next(dest.begin()));
Expand Down Expand Up @@ -883,7 +903,9 @@ void test_copy_offset_aligned(const size_t length) {
}
}

void test_copy_sub_char() {
CONSTEXPR20 void test_copy_sub_char() {
const vector<bool> source(begin(source_raw), end(source_raw));

{ // sub char copy unaligned
const vector<bool> result = {false, false, true, false, true, false, false, false};

Expand Down Expand Up @@ -1092,7 +1114,7 @@ void test_copy_sub_char() {
}
}

void test_copy_regression() {
CONSTEXPR20 void test_copy_regression() {
// This specific case was found by the randomized coverage below.
const vector<bool> src = {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0,
1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
Expand All @@ -1115,7 +1137,8 @@ void test_copy_regression() {
assert(dst == correct);
}

bool test_copy() {
// Test copy() in multiple parts to stay within constexpr step limits.
CONSTEXPR20 bool test_copy_part_1() {
test_copy_no_offset(3);
test_copy_no_offset(8);
test_copy_no_offset(22);
Expand Down Expand Up @@ -1144,6 +1167,10 @@ bool test_copy() {
test_copy_offset_match(32);
test_copy_offset_match(67);

return true;
}

CONSTEXPR20 bool test_copy_part_2() {
test_copy_offset_mismatch_leftshift(3);
test_copy_offset_mismatch_leftshift(8);
test_copy_offset_mismatch_leftshift(22);
Expand Down Expand Up @@ -1354,13 +1381,23 @@ static_assert(test_gh_5345<64>());
static_assert(test_gh_5345<64, 16>());
static_assert(test_gh_5345<120>());
static_assert(test_gh_5345<120, 31>());

static_assert(test_fill());
static_assert(test_find());
static_assert(test_count());

#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2574489
static_assert(test_copy_part_1());
static_assert(test_copy_part_2());
#endif // ^^^ no workaround ^^^
#endif // _HAS_CXX20

int main() {
test_fill();
test_find();
test_count();
test_copy();
test_copy_part_1();
test_copy_part_2();

test_huge_vector_bool();

Expand Down