Skip to content

Commit e6b85df

Browse files
Implement P3349R1 Converting Contiguous Iterators To Pointers (#5683)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 67dbf14 commit e6b85df

File tree

12 files changed

+691
-77
lines changed

12 files changed

+691
-77
lines changed

stl/inc/__msvc_ranges_tuple_formatter.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,13 +1086,15 @@ struct _Range_default_formatter<_Kind, _Rng, _CharT> {
10861086
template <class _FormatContext>
10871087
_FormatContext::iterator format(_Range_type& _Rx, _FormatContext& _Ctx) const {
10881088
if constexpr (_RANGES contiguous_range<_Range_type>) {
1089-
const auto _Size = _STD _To_unsigned_like(_RANGES distance(_Rx));
1089+
const auto _Dist = _RANGES distance(_Rx);
1090+
const auto _Size = _STD _To_unsigned_like(_Dist);
10901091

10911092
if (!_STD in_range<size_t>(_Size)) {
10921093
_Throw_format_error("Formatted range is too long.");
10931094
}
10941095

1095-
const basic_string_view<_CharT> _Str(_STD to_address(_RANGES begin(_Rx)), static_cast<size_t>(_Size));
1096+
const auto _First = _RANGES begin(_Rx);
1097+
const basic_string_view<_CharT> _Str(_STD to_address(_First), _STD to_address(_First + _Dist));
10961098
return _Underlying.format(_Str, _Ctx);
10971099
} else {
10981100
return _Underlying.format(basic_string<_CharT>{from_range, _Rx}, _Ctx);

stl/inc/algorithm

Lines changed: 50 additions & 29 deletions
Large diffs are not rendered by default.

stl/inc/format

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,9 +3367,10 @@ void _Range_formatter_format_as_sequence(const formatter<_Ty, _CharT>& _Underlyi
33673367
template <class _CharT, _RANGES input_range _Range, class _FormatContext>
33683368
void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, const bool _Debug) {
33693369
if constexpr (_RANGES contiguous_range<_Range>) {
3370-
const auto _Size = _STD _To_unsigned_like(_RANGES distance(_Rng));
3370+
const auto _Dist = _RANGES distance(_Rng);
33713371

33723372
#ifdef _DEBUG
3373+
const auto _Size = _STD _To_unsigned_like(_Dist);
33733374
if constexpr (sizeof(_Size) > sizeof(size_t)) {
33743375
_STL_VERIFY(_Size <= size_t{PTRDIFF_MAX}, "contiguous range has impossible size.");
33753376
}
@@ -3380,7 +3381,8 @@ void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, cons
33803381
_String_view_formatter.set_debug_format();
33813382
}
33823383

3383-
const basic_string_view<_CharT> _Str(_STD to_address(_RANGES begin(_Rng)), static_cast<size_t>(_Size));
3384+
const auto _First = _RANGES begin(_Rng);
3385+
const basic_string_view<_CharT> _Str(_STD to_address(_First), _STD to_address(_First + _Dist));
33843386
_String_view_formatter.format(_Str, _Ctx);
33853387
} else {
33863388
using _String = basic_string<_CharT>;

stl/inc/functional

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,7 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked(
25272527
if constexpr (_Vector_alg_in_search_is_safe<_FwdItHaystack, _FwdItPat, _Pred_eq>) {
25282528
if (!_STD _Is_constant_evaluated()) {
25292529
const auto _Ptr1 = _STD _To_address(_First1);
2530+
(void) _STD _To_address(_Last2);
25302531

25312532
const auto _Ptr_res1 = _STD _Search_vectorized(
25322533
_Ptr1, _STD _To_address(_Last1), _STD _To_address(_First2), static_cast<size_t>(_Count2));

stl/inc/memory

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,14 @@ namespace ranges {
102102
return _RANGES _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst,
103103
_RANGES next(_OFirst, _STD move(_OLast)));
104104
} else if constexpr (_Is_sized1) {
105-
return _RANGES _Copy_memcpy_distance(
106-
_IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast)));
105+
const auto _Dist = _ILast - _IFirst;
106+
_STD _Contiguous_iter_verify(_OFirst, static_cast<iter_difference_t<_Out>>(_Dist));
107+
return _RANGES _Copy_memcpy_distance(_IFirst, _OFirst, _IFirst, _IFirst + _Dist);
107108
} else {
108109
_STL_INTERNAL_STATIC_ASSERT(_Is_sized2);
109-
return _RANGES _Copy_memcpy_distance(
110-
_IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast)));
110+
const auto _Dist = _OLast - _OFirst;
111+
_STD _Contiguous_iter_verify(_IFirst, static_cast<iter_difference_t<_It>>(_Dist));
112+
return _RANGES _Copy_memcpy_distance(_IFirst, _OFirst, _OFirst, _OFirst + _Dist);
111113
}
112114
} else {
113115
if constexpr (_Can_memcpy) {
@@ -200,6 +202,8 @@ namespace ranges {
200202
_IFirst = _STD move(_UResult.in);
201203
_OFirst = _STD move(_UResult.out);
202204
} else {
205+
_STD _Contiguous_iter_verify(_IFirst, _Count);
206+
_STD _Contiguous_iter_verify(_OFirst, static_cast<iter_difference_t<_Out>>(_Count));
203207
auto _UResult = _RANGES _Copy_memcpy_count(_IFirst, _OFirst, static_cast<size_t>(_Count));
204208
_IFirst = _STD move(_UResult.in);
205209
_OFirst = _STD move(_UResult.out);
@@ -363,6 +367,8 @@ namespace ranges {
363367
_IFirst = _STD move(_UResult.in);
364368
_OFirst = _STD move(_UResult.out);
365369
} else {
370+
_STD _Contiguous_iter_verify(_IFirst, _Count);
371+
_STD _Contiguous_iter_verify(_OFirst, static_cast<iter_difference_t<_Out>>(_Count));
366372
auto _UResult = _RANGES _Copy_memcpy_count(_IFirst, _OFirst, static_cast<size_t>(_Count));
367373
_IFirst = _STD move(_UResult.in);
368374
_OFirst = _STD move(_UResult.out);

stl/inc/numeric

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -489,21 +489,25 @@ _CONSTEXPR20 _OutIt adjacent_difference(const _InIt _First, const _InIt _Last, _
489489
if (!_STD is_constant_evaluated())
490490
#endif
491491
{
492+
const auto _Dest_dist = static_cast<_Iter_diff_t<decltype(_UDest)>>(_ULast - _UFirst);
493+
_STD _Contiguous_iter_verify(_UDest, _Dest_dist);
494+
492495
// Go with pointers and without loop-carried dependency to enable vectorization
493496
const auto _First_ptr = _STD _To_address(_UFirst);
494497
const auto _Last_ptr = _STD _To_address(_ULast);
495498
const auto _Dest_ptr = _STD _To_address(_UDest);
496-
const auto _Count = _Last_ptr - _First_ptr;
497499

498500
// Need to perform aliasing analysis.
499501
// The vectorizer is generally able to do that on its own, and would guard the vectorized code with
500502
// that, but when we eliminate the loop-carried dependency we change the semantics of the unvectorized
501503
// code too. So we need to perform this check manually, and after that we can tell the compiler that
502504
// there's no aliasing, to avoid it checking for that again.
503-
if (reinterpret_cast<uintptr_t>(_Dest_ptr + _Count) <= reinterpret_cast<uintptr_t>(_First_ptr)
505+
if (reinterpret_cast<uintptr_t>(_Dest_ptr + static_cast<ptrdiff_t>(_Dest_dist))
506+
<= reinterpret_cast<uintptr_t>(_First_ptr)
504507
|| reinterpret_cast<uintptr_t>(_Last_ptr) <= reinterpret_cast<uintptr_t>(_Dest_ptr)) {
505-
_STD _Adjacent_difference_no_overlap(_Dest_ptr, _First_ptr, _Count, _STD _Pass_fn(_Func));
506-
_STD _Seek_wrapped(_Dest, _UDest + _Count);
508+
_STD _Adjacent_difference_no_overlap(
509+
_Dest_ptr, _First_ptr, static_cast<ptrdiff_t>(_Dest_dist), _STD _Pass_fn(_Func));
510+
_STD _Seek_wrapped(_Dest, _UDest + _Dest_dist);
507511
return _Dest;
508512
}
509513
}
@@ -556,7 +560,8 @@ _CONSTEXPR20 void iota(_FwdIt _First, _FwdIt _Last, _Ty _Val) {
556560

557561
if constexpr (_Iterator_is_contiguous<decltype(_UFirst)> && is_integral_v<_Ty> && sizeof(_Ty) >= 4) {
558562
// TRANSITION, DevCom-10593477: help the compiler vectorize
559-
const auto _Ptr = _To_address(_UFirst);
563+
const auto _Ptr = _To_address(_UFirst);
564+
(void) _STD _To_address(_ULast);
560565
const auto _Size = static_cast<size_t>(_ULast - _UFirst);
561566

562567
if (_STD _In_range<_Ty>(_Size)) {
@@ -611,7 +616,8 @@ namespace ranges {
611616
&& sizeof(_Ty) >= 4) {
612617
// TRANSITION, DevCom-10593477: help the compiler vectorize
613618
const auto _Ptr = _To_address(_First);
614-
const auto _Size = static_cast<size_t>(_Last - _First);
619+
const auto _Dist = _STD _Contiguous_iter_distance(_First, _Last);
620+
const auto _Size = static_cast<size_t>(_Dist);
615621

616622
if (_STD _In_range<_Ty>(_Size)) {
617623
const auto _Size_typed = static_cast<_Ty>(_Size);
@@ -621,7 +627,7 @@ namespace ranges {
621627
}
622628

623629
_Val += _Size_typed;
624-
return _First + _Size;
630+
return _First + _Dist;
625631
}
626632
}
627633

stl/inc/xmemory

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,7 @@ namespace ranges {
17201720

17211721
template <class _InIt, class _OutIt>
17221722
in_out_result<_InIt, _OutIt> _Copy_memcpy_count(_InIt _IFirst, _OutIt _OFirst, const size_t _Count) noexcept {
1723+
// (pre-verified contiguous iterator)
17231724
const auto _IFirstPtr = _STD _To_address(_IFirst);
17241725
const auto _OFirstPtr = _STD _To_address(_OFirst);
17251726
const auto _IFirst_ch = const_cast<char*>(reinterpret_cast<const volatile char*>(_IFirstPtr));
@@ -1743,6 +1744,7 @@ namespace ranges {
17431744
template <class _InIt, class _OutIt, class _DistIt>
17441745
in_out_result<_InIt, _OutIt> _Copy_memcpy_distance(
17451746
_InIt _IFirst, _OutIt _OFirst, const _DistIt _DFirst, const _DistIt _DLast) noexcept {
1747+
// (pre-verified contiguous iterator)
17461748
// equivalent to _Copy_memcpy_count(_IFirst, _OFirst, _DLast - _DFirst) but computes distance more efficiently
17471749
const auto _IFirstPtr = _STD _To_address(_IFirst);
17481750
const auto _OFirstPtr = _STD _To_address(_OFirst);
@@ -1757,13 +1759,13 @@ namespace ranges {
17571759
if constexpr (is_pointer_v<_InIt>) {
17581760
_IFirst = reinterpret_cast<_InIt>(_IFirst_ch + _Count_bytes);
17591761
} else {
1760-
_IFirst += _Count_bytes / sizeof(iter_value_t<_InIt>);
1762+
_IFirst += static_cast<iter_difference_t<_InIt>>(_Count_bytes / sizeof(iter_value_t<_InIt>));
17611763
}
17621764

17631765
if constexpr (is_pointer_v<_OutIt>) {
17641766
_OFirst = reinterpret_cast<_OutIt>(_OFirst_ch + _Count_bytes);
17651767
} else {
1766-
_OFirst += _Count_bytes / sizeof(iter_value_t<_OutIt>);
1768+
_OFirst += static_cast<iter_difference_t<_OutIt>>(_Count_bytes / sizeof(iter_value_t<_OutIt>));
17671769
}
17681770
return {_STD move(_IFirst), _STD move(_OFirst)};
17691771
}
@@ -1813,12 +1815,14 @@ namespace ranges {
18131815
return _RANGES _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst,
18141816
_RANGES next(_OFirst, _STD move(_OLast)));
18151817
} else if constexpr (_Is_sized1) {
1816-
return _RANGES _Copy_memcpy_distance(
1817-
_IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast)));
1818+
const auto _Dist = _ILast - _IFirst;
1819+
_STD _Contiguous_iter_verify(_OFirst, static_cast<iter_difference_t<_Out>>(_Dist));
1820+
return _RANGES _Copy_memcpy_distance(_IFirst, _OFirst, _IFirst, _IFirst + _Dist);
18181821
} else {
18191822
_STL_INTERNAL_STATIC_ASSERT(_Is_sized2);
1820-
return _RANGES _Copy_memcpy_distance(
1821-
_IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast)));
1823+
const auto _Dist = _OLast - _OFirst;
1824+
_STD _Contiguous_iter_verify(_IFirst, static_cast<iter_difference_t<_It>>(_Dist));
1825+
return _RANGES _Copy_memcpy_distance(_IFirst, _OFirst, _OFirst, _OFirst + _Dist);
18221826
}
18231827
} else {
18241828
if constexpr (_Can_memcpy) {
@@ -1906,7 +1910,7 @@ _CONSTEXPR20 _Alloc_ptr_t<_Alloc> _Uninitialized_copy(
19061910
_STD _Copy_memmove(_STD _To_address(_UFirst), _STD _To_address(_ULast), _STD _Unfancy(_Dest));
19071911
_Dest += _ULast - _UFirst;
19081912
} else {
1909-
const auto _Count = static_cast<size_t>(_ULast - _UFirst);
1913+
const auto _Count = static_cast<size_t>(_STD _Contiguous_iter_distance(_UFirst, _ULast));
19101914
_STD _Copy_memmove_n(_STD _To_address(_UFirst), _Count, _STD _Unfancy(_Dest));
19111915
_Dest += _Count;
19121916
}

0 commit comments

Comments
 (0)