Skip to content

Commit 692358b

Browse files
committed
Add loop unrolling to partition point
1 parent b785bcb commit 692358b

1 file changed

Lines changed: 60 additions & 9 deletions

File tree

include/boost/container/experimental/segmented_partition_point.hpp

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <boost/container/detail/config_begin.hpp>
2222
#include <boost/container/detail/workaround.hpp>
2323
#include <boost/container/experimental/segmented_iterator_traits.hpp>
24+
#include <boost/container/detail/iterators.hpp>
2425

2526
namespace boost {
2627
namespace container {
@@ -30,21 +31,71 @@ FwdIt segmented_partition_point(FwdIt first, Sent last, Predicate pred);
3031

3132
namespace detail_algo {
3233

33-
template <class FwdIt, class Sent, class Predicate, class Tag>
34+
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
35+
36+
template <class RAIter, class Predicate>
37+
RAIter segmented_partition_point_dispatch
38+
(RAIter first, RAIter last, Predicate pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
39+
{
40+
typedef typename iterator_traits<RAIter>::difference_type difference_type;
41+
42+
difference_type n = last - first;
43+
while(n >= difference_type(4)) {
44+
if(!pred(*first))
45+
goto final_result;
46+
++first;
47+
if(!pred(*first))
48+
goto final_result;
49+
++first;
50+
if(!pred(*first))
51+
goto final_result;
52+
++first;
53+
if(!pred(*first))
54+
goto final_result;
55+
++first;
56+
n -= 4;
57+
}
58+
59+
switch (n % 4) {
60+
case 3:
61+
if(!pred(*first))
62+
break;
63+
++first;
64+
BOOST_FALLTHROUGH;
65+
case 2:
66+
if(!pred(*first))
67+
break;
68+
++first;
69+
BOOST_FALLTHROUGH;
70+
case 1:
71+
if(!pred(*first))
72+
break;
73+
++first;
74+
BOOST_FALLTHROUGH;
75+
default:
76+
break;
77+
}
78+
final_result:
79+
return first;
80+
}
81+
82+
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
83+
84+
template <class FwdIt, class Sent, class Predicate, class Tag, class Cat>
3485
typename algo_enable_if_c<
3586
!Tag::value || is_sentinel<Sent, FwdIt>::value, FwdIt>::type
3687
segmented_partition_point_dispatch
37-
(FwdIt first, Sent last, Predicate pred, Tag)
88+
(FwdIt first, Sent last, Predicate pred, Tag, Cat)
3889
{
3990
for(; first != last; ++first)
4091
if(!pred(*first))
4192
return first;
4293
return last;
4394
}
4495

45-
template <class SegIter, class Predicate>
96+
template <class SegIter, class Predicate, class Cat>
4697
SegIter segmented_partition_point_dispatch
47-
(SegIter first, SegIter last, Predicate pred, segmented_iterator_tag)
98+
(SegIter first, SegIter last, Predicate pred, segmented_iterator_tag, Cat)
4899
{
49100
typedef segmented_iterator_traits<SegIter> traits;
50101
typedef typename traits::local_iterator local_iterator;
@@ -57,24 +108,24 @@ SegIter segmented_partition_point_dispatch
57108

58109
if(scur == slast) {
59110
return traits::compose(scur,
60-
(segmented_partition_point_dispatch)(traits::local(first), traits::local(last), pred, is_local_seg_t()));
111+
(segmented_partition_point_dispatch)(traits::local(first), traits::local(last), pred, is_local_seg_t(), Cat()));
61112
}
62113
else {
63114
{
64115
local_iterator lcur =
65-
(segmented_partition_point_dispatch)(traits::local(first), traits::end(scur), pred, is_local_seg_t());
116+
(segmented_partition_point_dispatch)(traits::local(first), traits::end(scur), pred, is_local_seg_t(), Cat());
66117
if (lcur != traits::end(scur))
67118
return traits::compose(scur, lcur);
68119
}
69120

70121
for(++scur; scur != slast; ++scur) {
71122
local_iterator lcur =
72-
(segmented_partition_point_dispatch)(traits::begin(scur), traits::end(scur), pred, is_local_seg_t());
123+
(segmented_partition_point_dispatch)(traits::begin(scur), traits::end(scur), pred, is_local_seg_t(), Cat());
73124
if(lcur != traits::end(scur))
74125
return traits::compose(scur, lcur);
75126
}
76127
return traits::compose(slast,
77-
(segmented_partition_point_dispatch)(traits::begin(scur), traits::local(last), pred, is_local_seg_t()));
128+
(segmented_partition_point_dispatch)(traits::begin(scur), traits::local(last), pred, is_local_seg_t(), Cat()));
78129
}
79130
return last;
80131
}
@@ -92,7 +143,7 @@ FwdIt segmented_partition_point(FwdIt first, Sent last, Predicate pred)
92143
{
93144
typedef segmented_iterator_traits<FwdIt> traits;
94145
return detail_algo::segmented_partition_point_dispatch
95-
(first, last, pred, typename traits::is_segmented_iterator());
146+
(first, last, pred, typename traits::is_segmented_iterator(), typename iterator_traits<FwdIt>::iterator_category());
96147
}
97148

98149
} // namespace container

0 commit comments

Comments
 (0)