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 correct_zero(T val,int bits)22template <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 safe_ctz(T val)52template <typename T> static inline int safe_ctz(T val) { 53 return __internal::correct_zero(val, __internal::ctz(val)); 54 } 55 unsafe_ctz(T val)56template <typename T> static inline int unsafe_ctz(T val) { 57 return __internal::ctz(val); 58 } 59 safe_clz(T val)60template <typename T> static inline int safe_clz(T val) { 61 return __internal::correct_zero(val, __internal::clz(val)); 62 } 63 unsafe_clz(T val)64template <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