1 //===--Convenient template for builtins -------------------------*- C++ -*-===//
2 //             (Count Lead Zeroes) and (Count Trailing Zeros)
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H
11 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H
12 
13 namespace __llvm_libc {
14 namespace fputil {
15 
16 // The following overloads are matched based on what is accepted by
17 // __builtin_clz/ctz* rather than using the exactly-sized aliases from stdint.h.
18 // This way, we can avoid making any assumptions about integer sizes and let the
19 // compiler match for us.
20 namespace __internal {
21 
22 template <typename T> static inline int correct_zero(T val, int bits) {
23   if (val == T(0))
24     return sizeof(T(0)) * 8;
25   else
26     return bits;
27 }
28 
29 template <typename T> static inline int clz(T val);
30 template <> inline int clz<unsigned int>(unsigned int val) {
31   return __builtin_clz(val);
32 }
33 template <> inline int clz<unsigned long int>(unsigned long int val) {
34   return __builtin_clzl(val);
35 }
36 template <> inline int clz<unsigned long long int>(unsigned long long int val) {
37   return __builtin_clzll(val);
38 }
39 
40 template <typename T> static inline int ctz(T val);
41 template <> inline int ctz<unsigned int>(unsigned int val) {
42   return __builtin_ctz(val);
43 }
44 template <> inline int ctz<unsigned long int>(unsigned long int val) {
45   return __builtin_ctzl(val);
46 }
47 template <> inline int ctz<unsigned long long int>(unsigned long long int val) {
48   return __builtin_ctzll(val);
49 }
50 } // namespace __internal
51 
52 template <typename T> static inline int safe_ctz(T val) {
53   return __internal::correct_zero(val, __internal::ctz(val));
54 }
55 
56 template <typename T> static inline int unsafe_ctz(T val) {
57   return __internal::ctz(val);
58 }
59 
60 template <typename T> static inline int safe_clz(T val) {
61   return __internal::correct_zero(val, __internal::clz(val));
62 }
63 
64 template <typename T> static inline int unsafe_clz(T val) {
65   return __internal::clz(val);
66 }
67 
68 } // namespace fputil
69 } // namespace __llvm_libc
70 
71 #endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_BUILTIN_WRAPPERS_H
72