Add BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS option

This commit is contained in:
Ion Gaztañaga
2026-05-05 10:19:30 +02:00
parent adefd94a9d
commit 48a6bf4c85
3 changed files with 73 additions and 1 deletions
@@ -45,6 +45,16 @@ segmented_count_dispatch
difference_type n = last - first;
difference_type count = 0;
while(n >= difference_type(4)) {
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(*first == value);
++first;
count += static_cast<difference_type>(*first == value);
++first;
count += static_cast<difference_type>(*first == value);
++first;
count += static_cast<difference_type>(*first == value);
++first;
#else
if(*first == value) ++count;
++first;
if(*first == value) ++count;
@@ -53,20 +63,33 @@ segmented_count_dispatch
++first;
if(*first == value) ++count;
++first;
#endif
n -= 4;
}
switch(n) {
case 3:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(*first == value);
#else
if(*first == value) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
case 2:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(*first == value);
#else
if(*first == value) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
case 1:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(*first == value);
#else
if(*first == value) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
default:
@@ -89,7 +112,11 @@ segmented_count_dispatch
diff_t n = 0;
for (; first != last; ++first)
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
n += static_cast<diff_t>(*first == value);
#else
if (*first == value) ++n;
#endif
return n;
}
@@ -44,6 +44,16 @@ segmented_count_if_dispatch
difference_type n = last - first;
difference_type count = 0;
while(n >= difference_type(4)) {
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(pred(*first));
++first;
count += static_cast<difference_type>(pred(*first));
++first;
count += static_cast<difference_type>(pred(*first));
++first;
count += static_cast<difference_type>(pred(*first));
++first;
#else
if(pred(*first)) ++count;
++first;
if(pred(*first)) ++count;
@@ -52,20 +62,33 @@ segmented_count_if_dispatch
++first;
if(pred(*first)) ++count;
++first;
#endif
n -= 4;
}
switch(n) {
case 3:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(pred(*first));
#else
if(pred(*first)) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
case 2:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(pred(*first));
#else
if(pred(*first)) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
case 1:
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
count += static_cast<difference_type>(pred(*first));
#else
if(pred(*first)) ++count;
#endif
++first;
BOOST_FALLTHROUGH;
default:
@@ -87,7 +110,11 @@ segmented_count_if_dispatch
diff_t n = 0;
for (; first != last; ++first)
#if defined(BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS)
n += static_cast<diff_t>(pred(*first));
#else
if (pred(*first)) ++n;
#endif
return n;
}
@@ -381,10 +381,28 @@ struct deepest_local_iterator
//#define BOOST_CONTAINER_DISABLE_MULTI_SEGMENTED_ALGO
// When defined, segmented algorithms that have a dual random-access fast path
// (e.g. segmented_copy_if_dst_bounded) will not attempt to detect whether the
// remaining source range fits the destination capacity and will always take the
// fast path when both iterators are random-access. This is useful for benchmarking
// the advantage of the dual-RA optimisation in isolation.
//
//#define BOOST_CONTAINER_SEGMENTED_DISABLE_DUAL_RA_OPTIMIZATION
#if !defined(BOOST_CONTAINER_SEGMENTED_DISABLE_DUAL_RA_OPTIMIZATION)
#define BOOST_CONTAINER_SEGMENTED_ENABLE_DUAL_RA_OPTIMIZATION
#endif
// When defined, segmented algorithms that count elements (e.g. segmented_count,
// segmented_count_if) will use a branchless counting strategy in their
// innermost loops, incrementing the count by the boolean result of the
// predicate rather than testing the predicate result in a branch and conditionally
// incrementing. This can improve performance on some platforms by avoiding branch mispredictions,
// at the cost of potentially increased instruction count and/or reduced vectorization opportunities.
//
// However, the optimal strategy is highly platform- and algorithm-specific, so this is disabled by default.
// There are regressions on some algorithms and platforms when this is enabled, and the performance impact
// varies widely across different scenarios.
//
//#define BOOST_CONTAINER_SEGMENTED_COUNT_BRANCHLESS
#endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_ITERATOR_TRAITS_HPP