Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
75474b6
Optimizations for contiguous iterators
AdamBucior Nov 7, 2020
b2d7591
Projections need to be same as identity
AdamBucior Nov 7, 2020
30da25d
clang-format
AdamBucior Nov 7, 2020
b1b6a83
clang-format please cooperate
AdamBucior Nov 7, 2020
6450aaf
Wrong iterators
AdamBucior Nov 7, 2020
e6058d4
remove_const
AdamBucior Nov 7, 2020
2952906
Fix find
AdamBucior Nov 7, 2020
cadd6cc
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Nov 14, 2020
876358d
_Memcmp_ranges
AdamBucior Nov 14, 2020
3fbfec8
_Memchr_in_find_is_safe
AdamBucior Nov 14, 2020
094b2b2
Simplify _Within_limits
AdamBucior Dec 5, 2020
1a1cd0a
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Jan 6, 2021
0d417ea
remove _HAS_IF_CONSTEXPR
AdamBucior Jan 6, 2021
8322e97
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Jan 8, 2021
acd8c3f
Apply suggestions from code review
AdamBucior Jan 9, 2021
23bf922
Code review
AdamBucior Jan 9, 2021
9e83f10
clang-format
AdamBucior Jan 9, 2021
f706346
static_cast
AdamBucior Jan 9, 2021
ed044f3
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Jan 16, 2021
65128e6
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Mar 15, 2021
3e91462
Revert "Merge branch 'master' into contiguous-iterator-optimizations"
AdamBucior Mar 15, 2021
3cdd6f8
Merge branch 'master' into contiguous-iterator-optimizations
AdamBucior Mar 15, 2021
fbc0c56
Merge branch 'main' into contiguous-iterator-optimizations
StephanTLavavej Mar 20, 2021
a1b8227
Move _Find_unchecked down.
StephanTLavavej Mar 21, 2021
ccf9f49
Code review feedback.
StephanTLavavej Mar 21, 2021
7263e21
Refine the condition for calling _Memcmp_ranges.
StephanTLavavej Mar 23, 2021
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
73 changes: 47 additions & 26 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,13 @@ namespace ranges {
template <class _It1, class _It2, class _Size, class _Pr, class _Pj1, class _Pj2>
_NODISCARD static constexpr bool _Equal_count(
_It1 _First1, _It2 _First2, _Size _Count, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
if constexpr (_Equal_memcmp_is_safe<_It1, _It2,
_Pr> && same_as<_Pj1, identity> && same_as<_Pj2, identity>) {
if (!_STD is_constant_evaluated()) {
return _Memcmp_count(_First1, _First2, static_cast<size_t>(_Count)) == 0;
}
}

for (; _Count != 0; ++_First1, (void) ++_First2, --_Count) {
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) {
return false;
Expand Down Expand Up @@ -2000,10 +2007,7 @@ _NODISCARD _CONSTEXPR20 bool _Equal_rev_pred_unchecked(_InIt1 _First1, _InIt2 _F
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
const auto _First1_ch = _To_pointer<const char>(_First1);
const auto _First2_ch = _To_pointer<const char>(_First2);
const auto _Count = static_cast<size_t>(_To_pointer<const char>(_Last2) - _First2_ch);
return _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0;
return _Memcmp_ranges(_First2, _Last2, _First1) == 0;
}
}

Expand Down Expand Up @@ -2095,7 +2099,7 @@ namespace ranges {
// clang-format off
template <class _It1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
concept _Equal_rev_pred_can_memcmp = is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>
&& is_same_v<_Se2, _It2> && _Equal_memcmp_is_safe<_It1, _It2, _Pr>;
&& sized_sentinel_for<_Se2, _It2> && _Equal_memcmp_is_safe<_It1, _It2, _Pr>;

template <input_iterator _It1, input_iterator _It2, sentinel_for<_It2> _Se2, class _Pr, class _Pj1, class _Pj2>
requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
Expand All @@ -2106,12 +2110,14 @@ namespace ranges {
constexpr bool _Optimize = _Equal_rev_pred_can_memcmp<_It1, _It2, _Se2, _Pr, _Pj1, _Pj2>;
if constexpr (_Optimize) {
if (!_STD is_constant_evaluated()) {
const auto _First1_ch = reinterpret_cast<const char*>(_STD to_address(_First1));
const auto _First2_ch = reinterpret_cast<const char*>(_STD to_address(_First2));
const auto _Count =
static_cast<size_t>(reinterpret_cast<const char*>(_STD to_address(_Last2)) - _First2_ch);
const bool _Eq = _CSTD memcmp(_First1_ch, _First2_ch, _Count) == 0;
if (_Eq) {
bool _Ans;
if constexpr (same_as<_It2, _Se2>) {
_Ans = _Memcmp_ranges(_First2, _Last2, _First1) == 0;
} else {
_Ans = _Memcmp_count(_First1, _First2, static_cast<size_t>(_Last2 - _First2)) == 0;
}

if (_Ans) {
_First1 += (_Last2 - _First2);
return {true, _STD move(_First1)};
} else {
Expand Down Expand Up @@ -3469,17 +3475,19 @@ namespace ranges {
auto _UFirst = _Get_unwrapped(_STD move(_First));
const auto _ULast = _Get_unwrapped(_STD move(_Last));
if (!_STD is_constant_evaluated()) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_Fill_memset(_UFirst, _Value, _Distance);
_Seek_wrapped(_First, _UFirst + _Distance);
return _First;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Value)) {
if constexpr (sized_sentinel_for<decltype(_ULast), decltype(_UFirst)>) {
if constexpr (_Fill_memset_is_safe<decltype(_UFirst), _Ty>) {
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_Fill_zero_memset(_UFirst, _Distance);
_Fill_memset(_UFirst, _Value, _Distance);
_Seek_wrapped(_First, _UFirst + _Distance);
return _First;
} else if constexpr (_Fill_zero_memset_is_safe<decltype(_UFirst), _Ty>) {
if (_Is_all_bits_zero(_Value)) {
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_Fill_zero_memset(_UFirst, _Distance);
_Seek_wrapped(_First, _UFirst + _Distance);
return _First;
}
}
}
}
Expand Down Expand Up @@ -4355,10 +4363,11 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) {
auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_BidIt>(_UFirst, _ULast));

#if _USE_STD_VECTOR_ALGORITHMS
using _Elem = remove_pointer_t<decltype(_UFirst)>;
using _DestElem = remove_pointer_t<decltype(_UDest)>;
using _Elem = remove_reference_t<_Iter_ref_t<remove_const_t<decltype(_UFirst)>>>;
using _DestElem = remove_reference_t<_Iter_ref_t<decltype(_UDest)>>;
constexpr bool _Allow_vectorization = conjunction_v<is_same<remove_const_t<_Elem>, _DestElem>,
is_pointer<decltype(_UFirst)>, is_trivially_copyable<_Elem>, negation<is_volatile<_Elem>>>;
bool_constant<_Iterators_are_contiguous<decltype(_UFirst), decltype(_UDest)>>, is_trivially_copyable<_Elem>,
negation<is_volatile<_Elem>>>;
constexpr size_t _Nx = sizeof(_Elem);

#pragma warning(suppress : 6326) // Potential comparison of a constant with another constant
Expand All @@ -4368,13 +4377,13 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) {
#endif // __cpp_lib_is_constant_evaluated
{
if constexpr (_Nx == 1) {
__std_reverse_copy_trivially_copyable_1(_UFirst, _ULast, _UDest);
__std_reverse_copy_trivially_copyable_1(_To_address(_UFirst), _To_address(_ULast), _To_address(_UDest));
} else if constexpr (_Nx == 2) {
__std_reverse_copy_trivially_copyable_2(_UFirst, _ULast, _UDest);
__std_reverse_copy_trivially_copyable_2(_To_address(_UFirst), _To_address(_ULast), _To_address(_UDest));
} else if constexpr (_Nx == 4) {
__std_reverse_copy_trivially_copyable_4(_UFirst, _ULast, _UDest);
__std_reverse_copy_trivially_copyable_4(_To_address(_UFirst), _To_address(_ULast), _To_address(_UDest));
} else {
__std_reverse_copy_trivially_copyable_8(_UFirst, _ULast, _UDest);
__std_reverse_copy_trivially_copyable_8(_To_address(_UFirst), _To_address(_ULast), _To_address(_UDest));
}

_UDest += _ULast - _UFirst;
Expand Down Expand Up @@ -10359,6 +10368,18 @@ namespace ranges {
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>);
_STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It1, _Pj1>, projected<_It2, _Pj2>>);

using _Memcmp_classification_pred =
typename decltype(_Lex_compare_memcmp_classify(_First1, _First2, _Pred))::_Pred;
if constexpr (!is_void_v<_Memcmp_classification_pred> && sized_sentinel_for<_Se1, _It1> //
&& sized_sentinel_for<_Se2, _It2> && same_as<_Pj1, identity> && same_as<_Pj2, identity>) {
if (!_STD is_constant_evaluated()) {
const auto _Num1 = static_cast<size_t>(_Last1 - _First1);
const auto _Num2 = static_cast<size_t>(_Last2 - _First2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: i believe _Num is a bit too generic. Maybe use _Len or _Size instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_Num is already used in the original std::lexicographical_compare and std::lexicographical_compare_three_way (and in lot's of other places) and after all it clearly describes what it is - the number of elements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @miscco's point (_Num\d* is relatively uncommon, and a bit more generic - one could speak of a number of matching elements possibly with gaps, while len/size is more specific), but I also agree with @AdamBucior's point - this is consistent with existing usage and seems to be clear so there is no risk of confusion.

The thing that would tip the scales for me is if we had multiple numbers of stuff involved - then it would be good to give distinct names to each. That isn't the case here, where we just have 1/2 mirroring the ranges named 1/2. Thus I think that the code is fine as-is.

Thanks for bringing this up! Clear naming is indeed important 😸

const int _Ans = _Memcmp_count(_First1, _First2, (_STD min)(_Num1, _Num2));
return _Memcmp_classification_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2);
}
}

for (;; ++_First1, (void) ++_First2) {
if (_First2 == _Last2) {
return false;
Expand Down
14 changes: 0 additions & 14 deletions stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -2229,20 +2229,6 @@ namespace ranges {
using is_transparent = int;
};

// STRUCT ranges::greater
struct greater {
// clang-format off
template <class _Ty1, class _Ty2>
requires totally_ordered_with<_Ty1, _Ty2> // TRANSITION, GH-489
_NODISCARD constexpr bool operator()(_Ty1&& _Left, _Ty2&& _Right) const noexcept(noexcept(
static_cast<bool>(static_cast<_Ty2&&>(_Right) < static_cast<_Ty1&&>(_Left)))) /* strengthened */ {
return static_cast<bool>(static_cast<_Ty2&&>(_Right) < static_cast<_Ty1&&>(_Left));
}
// clang-format on

using is_transparent = int;
};

// STRUCT ranges::greater_equal
struct greater_equal {
// clang-format off
Expand Down
11 changes: 6 additions & 5 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1781,14 +1781,15 @@ void uninitialized_fill(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last, c

// FUNCTION TEMPLATE _Uninitialized_value_construct_n WITH ALLOCATOR
template <class _NoThrowFwdIt>
_INLINE_VAR constexpr bool _Use_memset_value_construct_v = conjunction_v<is_pointer<_NoThrowFwdIt>,
is_scalar<_Iter_value_t<_NoThrowFwdIt>>, negation<is_volatile<remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>>>,
negation<is_member_pointer<_Iter_value_t<_NoThrowFwdIt>>>>;
_INLINE_VAR constexpr bool _Use_memset_value_construct_v =
conjunction_v<bool_constant<_Iterator_is_contiguous<_NoThrowFwdIt>>, is_scalar<_Iter_value_t<_NoThrowFwdIt>>,
negation<is_volatile<remove_reference_t<_Iter_ref_t<_NoThrowFwdIt>>>>,
negation<is_member_pointer<_Iter_value_t<_NoThrowFwdIt>>>>;

template <class _Ptr>
_Ptr _Zero_range(const _Ptr _First, const _Ptr _Last) { // fill [_First, _Last) with zeroes
char* const _First_ch = reinterpret_cast<char*>(_First);
char* const _Last_ch = reinterpret_cast<char*>(_Last);
char* const _First_ch = reinterpret_cast<char*>(_To_address(_First));
char* const _Last_ch = reinterpret_cast<char*>(_To_address(_Last));
_CSTD memset(_First_ch, 0, static_cast<size_t>(_Last_ch - _First_ch));
return _Last;
}
Expand Down
Loading