CompilerIntrinsics-vixl.h (6300B)
1 // Copyright 2015, ARM Limited 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 "mozilla/MathAlgorithms.h" 32 33 #include "jit/arm64/vixl/Globals-vixl.h" 34 35 namespace vixl { 36 37 // Helper to check whether the version of GCC used is greater than the specified 38 // requirement. 39 #define MAJOR 1000000 40 #define MINOR 1000 41 #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) 42 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \ 43 ((__GNUC__ * MAJOR + __GNUC_MINOR__ * MINOR + __GNUC_PATCHLEVEL__) >= \ 44 ((major) * MAJOR + (minor) * MINOR + (patchlevel))) 45 #elif defined(__GNUC__) && defined(__GNUC_MINOR__) 46 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) \ 47 ((__GNUC__ * MAJOR + __GNUC_MINOR__ * MINOR) >= \ 48 ((major) * MAJOR + (minor) * MINOR + (patchlevel))) 49 #else 50 #define GCC_VERSION_OR_NEWER(major, minor, patchlevel) 0 51 #endif 52 53 54 #if defined(__clang__) && !defined(VIXL_NO_COMPILER_BUILTINS) 55 56 #define COMPILER_HAS_BUILTIN_CLRSB (__has_builtin(__builtin_clrsb)) 57 #define COMPILER_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz)) 58 #define COMPILER_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz)) 59 #define COMPILER_HAS_BUILTIN_FFS (__has_builtin(__builtin_ffs)) 60 #define COMPILER_HAS_BUILTIN_POPCOUNT (__has_builtin(__builtin_popcount)) 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 # define COMPILER_HAS_BUILTIN_CLRSB (GCC_VERSION_OR_NEWER(4, 7, 0)) 67 # define COMPILER_HAS_BUILTIN_CLZ (GCC_VERSION_OR_NEWER(3, 4, 0)) 68 # define COMPILER_HAS_BUILTIN_CTZ (GCC_VERSION_OR_NEWER(3, 4, 0)) 69 # define COMPILER_HAS_BUILTIN_FFS (GCC_VERSION_OR_NEWER(3, 4, 0)) 70 # define COMPILER_HAS_BUILTIN_POPCOUNT (GCC_VERSION_OR_NEWER(3, 4, 0)) 71 72 #else 73 // One can define VIXL_NO_COMPILER_BUILTINS to force using the manually 74 // implemented C++ methods. 75 76 #define COMPILER_HAS_BUILTIN_BSWAP false 77 #define COMPILER_HAS_BUILTIN_CLRSB false 78 #define COMPILER_HAS_BUILTIN_CLZ false 79 #define COMPILER_HAS_BUILTIN_CTZ false 80 #define COMPILER_HAS_BUILTIN_FFS false 81 #define COMPILER_HAS_BUILTIN_POPCOUNT false 82 83 #endif 84 85 86 template<typename V> 87 inline bool IsPowerOf2(V value) { 88 return (value != 0) && ((value & (value - 1)) == 0); 89 } 90 91 92 // Implementation of intrinsics functions. 93 // TODO: The implementations could be improved for sizes different from 32bit 94 // and 64bit: we could mask the values and call the appropriate builtin. 95 96 97 template<typename V> 98 inline int CountLeadingZeros(V value, int width = (sizeof(V) * 8)) { 99 #if COMPILER_HAS_BUILTIN_CLZ 100 if (width == 32) { 101 return (value == 0) ? 32 : __builtin_clz(static_cast<unsigned>(value)); 102 } else if (width == 64) { 103 return (value == 0) ? 64 : __builtin_clzll(value); 104 } 105 MOZ_CRASH("Unhandled width."); 106 #else 107 if (width == 32) { 108 return mozilla::CountLeadingZeroes32(value); 109 } else if (width == 64) { 110 return mozilla::CountLeadingZeroes64(value); 111 } 112 MOZ_CRASH("Unhandled width."); 113 #endif 114 } 115 116 117 template<typename V> 118 inline int CountLeadingSignBits(V value, int width = (sizeof(V) * 8)) { 119 #if COMPILER_HAS_BUILTIN_CLRSB 120 if (width == 32) { 121 return __builtin_clrsb(value); 122 } else if (width == 64) { 123 return __builtin_clrsbll(value); 124 } 125 MOZ_CRASH("Unhandled width."); 126 #else 127 VIXL_ASSERT(IsPowerOf2(width) && (width <= 64)); 128 if (value >= 0) { 129 return CountLeadingZeros(value, width) - 1; 130 } else { 131 return CountLeadingZeros(~value, width) - 1; 132 } 133 #endif 134 } 135 136 137 template<typename V> 138 inline int CountSetBits(V value, int width = (sizeof(V) * 8)) { 139 #if COMPILER_HAS_BUILTIN_POPCOUNT 140 if (width == 32) { 141 return __builtin_popcount(static_cast<unsigned>(value)); 142 } else if (width == 64) { 143 return __builtin_popcountll(value); 144 } 145 MOZ_CRASH("Unhandled width."); 146 #else 147 if (width == 32) { 148 return mozilla::CountPopulation32(value); 149 } else if (width == 64) { 150 return mozilla::CountPopulation64(value); 151 } 152 MOZ_CRASH("Unhandled width."); 153 #endif 154 } 155 156 157 template<typename V> 158 inline int CountTrailingZeros(V value, int width = (sizeof(V) * 8)) { 159 #if COMPILER_HAS_BUILTIN_CTZ 160 if (width == 32) { 161 return (value == 0) ? 32 : __builtin_ctz(static_cast<unsigned>(value)); 162 } else if (width == 64) { 163 return (value == 0) ? 64 : __builtin_ctzll(value); 164 } 165 MOZ_CRASH("Unhandled width."); 166 #else 167 if (width == 32) { 168 return mozilla::CountTrailingZeroes32(value); 169 } else if (width == 64) { 170 return mozilla::CountTrailingZeroes64(value); 171 } 172 MOZ_CRASH("Unhandled width."); 173 #endif 174 } 175 176 } // namespace vixl 177 178 #endif // VIXL_COMPILER_INTRINSICS_H