[libcxx-commits] [PATCH] D70640: Optimize std::midpoint for signed integers

Andrej Korman via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sat Nov 23 18:58:58 PST 2019


Aj0SK created this revision.
Herald added subscribers: libcxx-commits, christof.
Herald added a project: libc++.

Idea of algorithm is based on finding floored "average" of numbers using bit hack.
Then we want to add -1/+1 only if the numbers have different parity.
We can make this decisions only using bit operators.

You can find benchmark of this algorithm against two older here ->
http://quick-bench.com/hqhZWR7IB4IoUj3aLTN28dOUuPY . In this benchmark
you can see that algorithm works faster for signed types and equally
fast for unsigned types. Even if this algorithm uses more instructions it has higher
Block RThroughput as ilustrated here -> https://godbolt.org/z/5TDmr4 .


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70640

Files:
  libcxx/include/numeric


Index: libcxx/include/numeric
===================================================================
--- libcxx/include/numeric
+++ libcxx/include/numeric
@@ -531,15 +531,9 @@
 midpoint(_Tp __a, _Tp __b) noexcept
 _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
 {
-    using _Up = std::make_unsigned_t<_Tp>;
-    constexpr _Up __bitshift = std::numeric_limits<_Up>::digits - 1;
-
-    _Up __diff = _Up(__b) - _Up(__a);
-    _Up __sign_bit = __b < __a;
-
-    _Up __half_diff = (__diff / 2) + (__sign_bit << __bitshift) + (__sign_bit & __diff);
-
-    return __a + __half_diff;
+    _Tp floored_avg = (__a & __b) + ((__a ^ __b) >> 1);
+    _Tp shift =  (__a ^ __b)&(__a >__b);
+    return floored_avg + shift;
 }
 
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70640.230782.patch
Type: text/x-patch
Size: 711 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20191124/688962d7/attachment.bin>


More information about the libcxx-commits mailing list