Skip to content

Commit 78ad3d8

Browse files
committed
Add loop unrolling to segmented_find_last_if
1 parent 692358b commit 78ad3d8

1 file changed

Lines changed: 54 additions & 12 deletions

File tree

include/boost/container/experimental/segmented_find_last_if.hpp

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,57 @@ BidirIt find_last_if_scan(BidirIt first, BidirIt last, Pred pred,
5959
return last;
6060
}
6161

62+
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
63+
64+
template <class RAIter, class Pred>
65+
RAIter find_last_if_scan(RAIter first, RAIter last, Pred pred,
66+
non_segmented_iterator_tag, const std::random_access_iterator_tag&)
67+
{
68+
typedef typename iterator_traits<RAIter>::difference_type difference_type;
69+
70+
const RAIter not_found = last;
71+
RAIter cur = last;
72+
difference_type n = cur - first;
73+
while (n >= difference_type(4)) {
74+
--cur;
75+
if (pred(*cur))
76+
return cur;
77+
--cur;
78+
if (pred(*cur))
79+
return cur;
80+
--cur;
81+
if (pred(*cur))
82+
return cur;
83+
--cur;
84+
if (pred(*cur))
85+
return cur;
86+
n -= 4;
87+
}
88+
89+
switch (n % 4) {
90+
case 3:
91+
--cur;
92+
if (pred(*cur))
93+
return cur;
94+
BOOST_FALLTHROUGH;
95+
case 2:
96+
--cur;
97+
if (pred(*cur))
98+
return cur;
99+
BOOST_FALLTHROUGH;
100+
case 1:
101+
--cur;
102+
if (pred(*cur))
103+
return cur;
104+
BOOST_FALLTHROUGH;
105+
default:
106+
break;
107+
}
108+
return not_found;
109+
}
110+
111+
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
112+
62113
//////////////////////////////////////////////
63114
// Segmented forward scan
64115
//////////////////////////////////////////////
@@ -78,10 +129,7 @@ SegIt find_last_if_scan(SegIt first, SegIt last, Pred pred,
78129
const segment_iterator slast = traits::segment(last);
79130

80131
if (sfirst == slast) {
81-
const local_iterator lf = traits::local(first);
82-
const local_iterator ll = traits::local(last);
83-
const local_iterator r = find_last_if_scan(lf, ll, pred, is_local_seg_t(), local_cat_t());
84-
return traits::compose(sfirst, r);
132+
return traits::compose(sfirst, find_last_if_scan(traits::local(first), traits::local(last), pred, is_local_seg_t(), local_cat_t()));
85133
}
86134
else {
87135
{ // First segment
@@ -97,14 +145,8 @@ SegIt find_last_if_scan(SegIt first, SegIt last, Pred pred,
97145
if (r != le)
98146
result = traits::compose(sfirst, r);
99147
}
100-
{ // Last segment
101-
const local_iterator ll = traits::local(last);
102-
const local_iterator r = find_last_if_scan(traits::begin(sfirst), ll, pred, is_local_seg_t(), local_cat_t());
103-
if (r != ll)
104-
result = traits::compose(sfirst, r);
105-
}
106-
107-
return result;
148+
// Last segment
149+
return traits::compose(sfirst, find_last_if_scan(traits::begin(slast), traits::local(last), pred, is_local_seg_t(), local_cat_t()));
108150
}
109151
}
110152

0 commit comments

Comments
 (0)