From c67029c92ac6f602fc4894eb8eae4111183ef189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Thu, 21 May 2026 14:45:27 +0200 Subject: [PATCH] Optimize for fixed size range_sz --- .../experimental/segmented_fill_n.hpp | 86 ++++++++++++------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/include/boost/container/experimental/segmented_fill_n.hpp b/include/boost/container/experimental/segmented_fill_n.hpp index 6c6855c..0bf7cb6 100644 --- a/include/boost/container/experimental/segmented_fill_n.hpp +++ b/include/boost/container/experimental/segmented_fill_n.hpp @@ -34,14 +34,14 @@ namespace detail_algo { template BOOST_CONTAINER_FORCEINLINE -OutIter fill_n_scan - ( OutIter first, OutIter last, Size& BOOST_RESTRICT count +segduo fill_n_scan + ( OutIter first, OutIter last, Size count , const T& value, non_segmented_iterator_tag, const std::random_access_iterator_tag &) { - std::size_t range_sz = static_cast(last - first); + Size range_sz = static_cast(last - first); +#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) const Size local_count = (std::size_t)count < range_sz ? count : (Size)range_sz; -#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING) Size cnt = local_count; while(cnt >= Size(4)) { *first = value; ++first; @@ -64,34 +64,42 @@ OutIter fill_n_scan default: break; } + return segduo(first, count - local_count); #else - BOOST_CONTAINER_SEGMENTED_UNROLL(4) - for(Size cnt = local_count; cnt; ++first, --cnt) - *first = value; + //If the whole range is fixed at compile time (e.g. deque) + //some compilers (e.g. MSVC 2026) can use SIMD more efficiently + //than when using count. + if (count >= range_sz) { + count -= range_sz; + BOOST_CONTAINER_SEGMENTED_UNROLL(4) + for (Size cnt = 0; cnt != range_sz; ++first, ++cnt){ + *first = value; + } + return segduo(first, count); + } + else { + BOOST_CONTAINER_SEGMENTED_UNROLL(4) + for (Size cnt = 0; cnt != count; ++first, ++cnt) + *first = value; + return segduo(first, Size(0)); + } #endif - - count -= local_count; - return first; } template BOOST_CONTAINER_FORCEINLINE -OutIter fill_n_scan - (OutIter first, OutIter last, Size& BOOST_RESTRICT count, const T& value, non_segmented_iterator_tag, const Cat &) +segduo fill_n_scan + (OutIter first, OutIter last, Size count, const T& value, non_segmented_iterator_tag, const Cat &) { - Size local_count = count; - BOOST_CONTAINER_SEGMENTED_UNROLL(4) - for (; local_count > 0 && first != last; ++first, --local_count) + for (; count > 0 && first != last; ++first, --count) *first = value; - count = local_count; - - return first; + return segduo(first, count); } template -SegIt fill_n_scan(SegIt first, SegIt last, Size& BOOST_RESTRICT count, const T& value, segmented_iterator_tag, const Cat &) +segduo fill_n_scan(SegIt first, SegIt last, Size count, const T& value, segmented_iterator_tag, const Cat &) { typedef segmented_iterator_traits traits; typedef typename traits::local_iterator local_iterator; @@ -104,22 +112,24 @@ SegIt fill_n_scan(SegIt first, SegIt last, Size& BOOST_RESTRICT count, const T& if(scur == slast) { const local_iterator ll = traits::local(last); - const local_iterator r = (fill_n_scan)(traits::local(first), ll, count, value, is_local_seg_t(), local_cat_t()); - return (r != ll) ? traits::compose(scur, r) : last; + const segduo r = (fill_n_scan)(traits::local(first), ll, count, value, is_local_seg_t(), local_cat_t()); + return segduo((r.first != ll) ? traits::compose(scur, r.first) : last, r.second); } else { - local_iterator r = fill_n_scan(traits::local(first), traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); + segduo r = fill_n_scan(traits::local(first), traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); + count = r.second; if (!count) - return traits::compose(scur, r); + return segduo(traits::compose(scur, r.first), count); for (++scur; scur != slast; ++scur) { r = fill_n_scan(traits::begin(scur), traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); + count = r.second; if (!count) - return traits::compose(scur, r); + return segduo(traits::compose(scur, r.first), count); } const local_iterator ll = traits::local(last); r = fill_n_scan(traits::begin(slast), ll, count, value, is_local_seg_t(), local_cat_t()); - return (r != ll) ? traits::compose(scur, r) : last; + return segduo((r.first != ll) ? traits::compose(scur, r.first) : last, r.second); } } @@ -134,16 +144,26 @@ SegIter segmented_fill_n_ref typedef typename iterator_traits::iterator_category local_cat_t; segment_iterator scur = traits::segment(first); - local_iterator lcur = traits::local(first); + local_iterator lcur; - while(1) { - lcur = fill_n_scan(lcur, traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); - - if(count == 0) - break; - ++scur; - lcur = traits::begin(scur); + { + const segduo r = fill_n_scan(traits::local(first), traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); + lcur = r.first; + count = r.second; } + + if (count) { + ++scur; + while (1) { + const segduo r = fill_n_scan(traits::begin(scur), traits::end(scur), count, value, is_local_seg_t(), local_cat_t()); + lcur = r.first; + count = r.second; + if (count == 0) + break; + ++scur; + } + } + return traits::compose(scur, lcur); }