1 // Copyright 2015, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 28 #ifndef VIXL_COMPILER_INTRINSICS_H 29 #define VIXL_COMPILER_INTRINSICS_H 30 31 #include "globals-vixl.h" 32 33 namespace vixl { 34 35 // Helper to check whether the version of GCC used is greater than the specified 36 // requirement. 37 #define MAJOR 1000000 38 #define MINOR 1000 39 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 40 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \ 41 ((__GNUC__ * (MAJOR) + __GNUC_MINOR__ * (MINOR) + __GNUC_PATCHLEVEL__) >= \ 42 ((major) * (MAJOR) + ((minor)) * (MINOR) + (patchlevel))) 43 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) 44 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \ 45 ((__GNUC__ * (MAJOR) + __GNUC_MINOR__ * (MINOR)) >= \ 46 ((major) * (MAJOR) + ((minor)) * (MINOR) + (patchlevel))) 47 #else 48 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) 0 49 #endif 50 51 52 #if defined(__clang__) && !defined(VIXL_NO_COMPILER_BUILTINS) 53 54 // clang-format off 55 #define COMPILER_HAS_BUILTIN_CLRSB (__has_builtin(__builtin_clrsb)) 56 #define COMPILER_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz)) 57 #define COMPILER_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz)) 58 #define COMPILER_HAS_BUILTIN_FFS (__has_builtin(__builtin_ffs)) 59 #define COMPILER_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount)) 60 // clang-format on 61 62 #elif defined(__GNUC__) && !defined(VIXL_NO_COMPILER_BUILTINS) 63 // The documentation for these builtins is available at: 64 // https://gcc.gnu.org/onlinedocs/gcc-$MAJOR.$MINOR.$PATCHLEVEL/gcc//Other-Builtins.html 65 66 // clang-format off 67 # define COMPILER_HAS_BUILTIN_CLRSB (GCC_VERSION_OR_NEWER(4, 7, 0)) 68 # define COMPILER_HAS_BUILTIN_CLZ (GCC_VERSION_OR_NEWER(3, 4, 0)) 69 # define COMPILER_HAS_BUILTIN_CTZ (GCC_VERSION_OR_NEWER(3, 4, 0)) 70 # define COMPILER_HAS_BUILTIN_FFS (GCC_VERSION_OR_NEWER(3, 4, 0)) 71 # define COMPILER_HAS_BUILTIN_POPCOUNT (GCC_VERSION_OR_NEWER(3, 4, 0)) 72 // clang-format on 73 74 #else 75 // One can define VIXL_NO_COMPILER_BUILTINS to force using the manually 76 // implemented C++ methods. 77 78 // clang-format off 79 #define COMPILER_HAS_BUILTIN_BSWAP false 80 #define COMPILER_HAS_BUILTIN_CLRSB false 81 #define COMPILER_HAS_BUILTIN_CLZ false 82 #define COMPILER_HAS_BUILTIN_CTZ false 83 #define COMPILER_HAS_BUILTIN_FFS false 84 #define COMPILER_HAS_BUILTIN_POPCOUNT false 85 // clang-format on 86 87 #endif 88 89 90 template <typename V> 91 inline bool IsPowerOf2(V value) { 92 return (value != 0) && ((value & (value - 1)) == 0); 93 } 94 95 96 // Declaration of fallback functions. 97 int CountLeadingSignBitsFallBack(int64_t value, int width); 98 int CountLeadingZerosFallBack(uint64_t value, int width); 99 int CountSetBitsFallBack(uint64_t value, int width); 100 int CountTrailingZerosFallBack(uint64_t value, int width); 101 102 103 // Implementation of intrinsics functions. 104 // TODO: The implementations could be improved for sizes different from 32bit 105 // and 64bit: we could mask the values and call the appropriate builtin. 106 107 template <typename V> 108 inline int CountLeadingSignBits(V value, int width = (sizeof(V) * 8)) { 109 #if COMPILER_HAS_BUILTIN_CLRSB 110 if (width == 32) { 111 return __builtin_clrsb(value); 112 } else if (width == 64) { 113 return __builtin_clrsbll(value); 114 } 115 #endif 116 return CountLeadingSignBitsFallBack(value, width); 117 } 118 119 120 template <typename V> 121 inline int CountLeadingZeros(V value, int width = (sizeof(V) * 8)) { 122 #if COMPILER_HAS_BUILTIN_CLZ 123 if (width == 32) { 124 return (value == 0) ? 32 : __builtin_clz(static_cast<unsigned>(value)); 125 } else if (width == 64) { 126 return (value == 0) ? 64 : __builtin_clzll(value); 127 } 128 #endif 129 return CountLeadingZerosFallBack(value, width); 130 } 131 132 133 template <typename V> 134 inline int CountSetBits(V value, int width = (sizeof(V) * 8)) { 135 #if COMPILER_HAS_BUILTIN_POPCOUNT 136 if (width == 32) { 137 return __builtin_popcount(static_cast<unsigned>(value)); 138 } else if (width == 64) { 139 return __builtin_popcountll(value); 140 } 141 #endif 142 return CountSetBitsFallBack(value, width); 143 } 144 145 146 template <typename V> 147 inline int CountTrailingZeros(V value, int width = (sizeof(V) * 8)) { 148 #if COMPILER_HAS_BUILTIN_CTZ 149 if (width == 32) { 150 return (value == 0) ? 32 : __builtin_ctz(static_cast<unsigned>(value)); 151 } else if (width == 64) { 152 return (value == 0) ? 64 : __builtin_ctzll(value); 153 } 154 #endif 155 return CountTrailingZerosFallBack(value, width); 156 } 157 158 } // namespace vixl 159 160 #endif // VIXL_COMPILER_INTRINSICS_H 161