diff options
author | Cassio Neri <cassio.neri@gmail.com> | 2021-06-23 15:32:16 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2021-06-23 18:28:08 +0100 |
commit | b92d12d3fe3f1aa56d190d960e40c62869a6cfbb (patch) | |
tree | e27d94f4883acb7bcf3346f6a2e7b8b8a316d921 | |
parent | 53330b7d6848209d658c02be76c36aa5475a88c9 (diff) | |
download | gcc-b92d12d3fe3f1aa56d190d960e40c62869a6cfbb.zip gcc-b92d12d3fe3f1aa56d190d960e40c62869a6cfbb.tar.gz gcc-b92d12d3fe3f1aa56d190d960e40c62869a6cfbb.tar.bz2 |
libstdc++: More efficient std::chrono::year::leap
Simple change to std::chrono::year::is_leap. If a year is multiple of 100,
then it's divisible by 400 if and only if it's divisible by 16. The latter
allows for better code generation.
The expression is then either y%16 or y%4 which are both powers of two
and so it can be rearranged to use simple bitmask operations.
Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
Co-authored-by: Ulrich Drepper <drepper@redhat.com>
libstdc++-v3/ChangeLog:
* include/std/chrono (chrono::year::is_leap()): Optimize.
-rw-r--r-- | libstdc++-v3/include/std/chrono | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index 4631a72..863b6a2 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -1606,13 +1606,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [1] https://github.com/cassioneri/calendar // [2] https://accu.org/journals/overload/28/155/overload155.pdf#page=16 + // Furthermore, if y%100 != 0, then y%400==0 is equivalent to y%16==0, + // so we can rearrange the expression to (mult_100 ? y % 4 : y % 16)==0 + // which is equivalent to (y & (mult_100 ? 15 : 3)) == 0. + // See https://gcc.gnu.org/pipermail/libstdc++/2021-June/052815.html + constexpr uint32_t __multiplier = 42949673; constexpr uint32_t __bound = 42949669; constexpr uint32_t __max_dividend = 1073741799; constexpr uint32_t __offset = __max_dividend / 2 / 100 * 100; const bool __is_multiple_of_100 = __multiplier * (_M_y + __offset) < __bound; - return (!__is_multiple_of_100 || _M_y % 400 == 0) && _M_y % 4 == 0; + return (_M_y & (__is_multiple_of_100 ? 15 : 3)) == 0; } explicit constexpr |