xref: /llvm-project/flang/include/flang/Common/bit-population-count.h (revision 3aee64a9e038814a6d4c64d37d35e5ccf27e4934)
164ab3302SCarolineConcatto //===-- include/flang/Common/bit-population-count.h -------------*- C++ -*-===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto #ifndef FORTRAN_COMMON_BIT_POPULATION_COUNT_H_
1064ab3302SCarolineConcatto #define FORTRAN_COMMON_BIT_POPULATION_COUNT_H_
1164ab3302SCarolineConcatto 
1264ab3302SCarolineConcatto // Fast and portable functions that implement Fortran's POPCNT and POPPAR
1364ab3302SCarolineConcatto // intrinsic functions.  POPCNT returns the number of bits that are set (1)
1464ab3302SCarolineConcatto // in its argument.  POPPAR is a parity function that returns true
1564ab3302SCarolineConcatto // when POPCNT is odd.
1664ab3302SCarolineConcatto 
17*3aee64a9Speter klausler #include <climits>
18*3aee64a9Speter klausler #include <type_traits>
1964ab3302SCarolineConcatto 
2064ab3302SCarolineConcatto namespace Fortran::common {
2164ab3302SCarolineConcatto 
22*3aee64a9Speter klausler template <typename INT,
23*3aee64a9Speter klausler     std::enable_if_t<(sizeof(INT) > 4 && sizeof(INT) <= 8), int> = 0>
BitPopulationCount(INT x)24*3aee64a9Speter klausler inline constexpr int BitPopulationCount(INT x) {
2564ab3302SCarolineConcatto   // In each of the 32 2-bit fields, count the bits that were present.
2664ab3302SCarolineConcatto   // This leaves a value [0..2] in each of these 2-bit fields.
2764ab3302SCarolineConcatto   x = (x & 0x5555555555555555) + ((x >> 1) & 0x5555555555555555);
2864ab3302SCarolineConcatto   // Combine into 16 4-bit fields, each holding [0..4]
2964ab3302SCarolineConcatto   x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
3064ab3302SCarolineConcatto   // Now 8 8-bit fields, each with [0..8] in their lower 4 bits.
3164ab3302SCarolineConcatto   x = (x & 0x0f0f0f0f0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f0f0f0f0f);
3264ab3302SCarolineConcatto   // Now 4 16-bit fields, each with [0..16] in their lower 5 bits.
3364ab3302SCarolineConcatto   x = (x & 0x001f001f001f001f) + ((x >> 8) & 0x001f001f001f001f);
3464ab3302SCarolineConcatto   // Now 2 32-bit fields, each with [0..32] in their lower 6 bits.
3564ab3302SCarolineConcatto   x = (x & 0x0000003f0000003f) + ((x >> 16) & 0x0000003f0000003f);
3664ab3302SCarolineConcatto   // Last step: 1 64-bit field, with [0..64]
3764ab3302SCarolineConcatto   return (x & 0x7f) + (x >> 32);
3864ab3302SCarolineConcatto }
3964ab3302SCarolineConcatto 
40*3aee64a9Speter klausler template <typename INT,
41*3aee64a9Speter klausler     std::enable_if_t<(sizeof(INT) > 2 && sizeof(INT) <= 4), int> = 0>
BitPopulationCount(INT x)42*3aee64a9Speter klausler inline constexpr int BitPopulationCount(INT x) {
4364ab3302SCarolineConcatto   // In each of the 16 2-bit fields, count the bits that were present.
4464ab3302SCarolineConcatto   // This leaves a value [0..2] in each of these 2-bit fields.
4564ab3302SCarolineConcatto   x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
4664ab3302SCarolineConcatto   // Combine into 8 4-bit fields, each holding [0..4]
4764ab3302SCarolineConcatto   x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
4864ab3302SCarolineConcatto   // Now 4 8-bit fields, each with [0..8] in their lower 4 bits.
4964ab3302SCarolineConcatto   x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f);
5064ab3302SCarolineConcatto   // Now 2 16-bit fields, each with [0..16] in their lower 5 bits.
5164ab3302SCarolineConcatto   x = (x & 0x001f001f) + ((x >> 8) & 0x001f001f);
5264ab3302SCarolineConcatto   // Last step: 1 32-bit field, with [0..32]
5364ab3302SCarolineConcatto   return (x & 0x3f) + (x >> 16);
5464ab3302SCarolineConcatto }
5564ab3302SCarolineConcatto 
56*3aee64a9Speter klausler template <typename INT, std::enable_if_t<sizeof(INT) == 2, int> = 0>
BitPopulationCount(INT x)57*3aee64a9Speter klausler inline constexpr int BitPopulationCount(INT x) {
5864ab3302SCarolineConcatto   // In each of the 8 2-bit fields, count the bits that were present.
5964ab3302SCarolineConcatto   // This leaves a value [0..2] in each of these 2-bit fields.
6064ab3302SCarolineConcatto   x = (x & 0x5555) + ((x >> 1) & 0x5555);
6164ab3302SCarolineConcatto   // Combine into 4 4-bit fields, each holding [0..4]
6264ab3302SCarolineConcatto   x = (x & 0x3333) + ((x >> 2) & 0x3333);
6364ab3302SCarolineConcatto   // Now 2 8-bit fields, each with [0..8] in their lower 4 bits.
6464ab3302SCarolineConcatto   x = (x & 0x0f0f) + ((x >> 4) & 0x0f0f);
6564ab3302SCarolineConcatto   // Last step: 1 16-bit field, with [0..16]
6664ab3302SCarolineConcatto   return (x & 0x1f) + (x >> 8);
6764ab3302SCarolineConcatto }
6864ab3302SCarolineConcatto 
69*3aee64a9Speter klausler template <typename INT, std::enable_if_t<sizeof(INT) == 1, int> = 0>
BitPopulationCount(INT x)70*3aee64a9Speter klausler inline constexpr int BitPopulationCount(INT x) {
7164ab3302SCarolineConcatto   // In each of the 4 2-bit fields, count the bits that were present.
7264ab3302SCarolineConcatto   // This leaves a value [0..2] in each of these 2-bit fields.
7364ab3302SCarolineConcatto   x = (x & 0x55) + ((x >> 1) & 0x55);
7464ab3302SCarolineConcatto   // Combine into 2 4-bit fields, each holding [0..4]
7564ab3302SCarolineConcatto   x = (x & 0x33) + ((x >> 2) & 0x33);
7664ab3302SCarolineConcatto   // Last step: 1 8-bit field, with [0..8]
7764ab3302SCarolineConcatto   return (x & 0xf) + (x >> 4);
7864ab3302SCarolineConcatto }
7964ab3302SCarolineConcatto 
Parity(INT x)80*3aee64a9Speter klausler template <typename INT> inline constexpr bool Parity(INT x) {
8164ab3302SCarolineConcatto   return BitPopulationCount(x) & 1;
8264ab3302SCarolineConcatto }
8364ab3302SCarolineConcatto 
8464ab3302SCarolineConcatto // "Parity is for farmers." -- Seymour R. Cray
8564ab3302SCarolineConcatto 
TrailingZeroBitCount(INT x)86*3aee64a9Speter klausler template <typename INT> inline constexpr int TrailingZeroBitCount(INT x) {
8764ab3302SCarolineConcatto   if ((x & 1) != 0) {
8864ab3302SCarolineConcatto     return 0; // fast path for odd values
89*3aee64a9Speter klausler   } else if (x == 0) {
90*3aee64a9Speter klausler     return CHAR_BIT * sizeof x;
9164ab3302SCarolineConcatto   } else {
92*3aee64a9Speter klausler     return BitPopulationCount(static_cast<INT>(x ^ (x - 1))) - 1;
9364ab3302SCarolineConcatto   }
9464ab3302SCarolineConcatto }
951f879005STim Keith } // namespace Fortran::common
9664ab3302SCarolineConcatto #endif // FORTRAN_COMMON_BIT_POPULATION_COUNT_H_
97