| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #ifndef V8_COMPILER_INTRINSICS_H_ | 28 #ifndef V8_COMPILER_INTRINSICS_H_ |
| 29 #define V8_COMPILER_INTRINSICS_H_ | 29 #define V8_COMPILER_INTRINSICS_H_ |
| 30 | 30 |
| 31 #include "globals.h" |
| 32 #include "checks.h" |
| 33 |
| 34 |
| 31 namespace v8 { | 35 namespace v8 { |
| 32 namespace internal { | 36 namespace internal { |
| 33 | 37 |
| 38 // C++ fallback implementations when builtins are not availble. |
| 39 int C_CountRedundantLeadingSignBits(int64_t value, int width); |
| 40 int C_CountSetBits(uint64_t value, int width); |
| 41 |
| 34 class CompilerIntrinsics { | 42 class CompilerIntrinsics { |
| 35 public: | 43 public: |
| 36 // Returns number of zero bits preceding least significant 1 bit. | 44 // Returns number of zero bits preceding least significant 1 bit. |
| 37 // Undefined for zero value. | 45 // Undefined for zero value. |
| 38 INLINE(static int CountTrailingZeros(uint32_t value)); | 46 INLINE(static int CountTrailingZeros(uint32_t value)); |
| 47 INLINE(static int CountTrailingZeros(uint64_t value)); |
| 39 | 48 |
| 40 // Returns number of zero bits following most significant 1 bit. | 49 // Returns number of zero bits following most significant 1 bit. |
| 41 // Undefined for zero value. | 50 // Undefined for zero value. |
| 42 INLINE(static int CountLeadingZeros(uint32_t value)); | 51 INLINE(static int CountLeadingZeros(uint32_t value)); |
| 52 INLINE(static int CountLeadingZeros(uint64_t value)); |
| 53 |
| 54 // Returns the number of redundant leading sign bits. |
| 55 INLINE(static int CountRedundantLeadingSignBits(int32_t value)); |
| 56 INLINE(static int CountRedundantLeadingSignBits(int64_t value)); |
| 43 | 57 |
| 44 // Returns the number of bits set. | 58 // Returns the number of bits set. |
| 45 INLINE(static int CountSetBits(uint32_t value)); | 59 INLINE(static int CountSetBits(uint32_t value)); |
| 60 INLINE(static int CountSetBits(uint64_t value)); |
| 46 }; | 61 }; |
| 47 | 62 |
| 48 #ifdef __GNUC__ | 63 #ifdef __GNUC__ |
| 49 int CompilerIntrinsics::CountTrailingZeros(uint32_t value) { | 64 int CompilerIntrinsics::CountTrailingZeros(uint32_t value) { |
| 50 return __builtin_ctz(value); | 65 return __builtin_ctz(value); |
| 51 } | 66 } |
| 52 | 67 |
| 68 int CompilerIntrinsics::CountTrailingZeros(uint64_t value) { |
| 69 return __builtin_ctzll(value); |
| 70 } |
| 71 |
| 53 int CompilerIntrinsics::CountLeadingZeros(uint32_t value) { | 72 int CompilerIntrinsics::CountLeadingZeros(uint32_t value) { |
| 54 return __builtin_clz(value); | 73 return __builtin_clz(value); |
| 55 } | 74 } |
| 56 | 75 |
| 76 int CompilerIntrinsics::CountLeadingZeros(uint64_t value) { |
| 77 return __builtin_clzll(value); |
| 78 } |
| 79 |
| 80 // __builtin_clrsb and derivatives are only availble since GCC4.7.0. |
| 81 #define GNUC_AVAILABLE_BUILTIN_CLRSB ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 7)) |
| 82 int CompilerIntrinsics::CountRedundantLeadingSignBits(int32_t value) { |
| 83 #if GNUC_AVAILABLE_BUILTIN_CLRSB |
| 84 return __builtin_clrsb(value); |
| 85 #else |
| 86 return C_CountRedundantLeadingSignBits(value, 32); |
| 87 #endif |
| 88 } |
| 89 |
| 90 int CompilerIntrinsics::CountRedundantLeadingSignBits(int64_t value) { |
| 91 #if GNUC_AVAILABLE_BUILTIN_CLRSB |
| 92 return __builtin_clrsbll(value); |
| 93 #else |
| 94 return C_CountRedundantLeadingSignBits(value, 64); |
| 95 #endif |
| 96 } |
| 97 #undef GNUC_AVAILABLE_BUILTIN_CLRSB |
| 98 |
| 57 int CompilerIntrinsics::CountSetBits(uint32_t value) { | 99 int CompilerIntrinsics::CountSetBits(uint32_t value) { |
| 58 return __builtin_popcount(value); | 100 return __builtin_popcount(value); |
| 59 } | 101 } |
| 60 | 102 |
| 103 int CompilerIntrinsics::CountSetBits(uint64_t value) { |
| 104 return __builtin_popcountll(value); |
| 105 } |
| 106 |
| 61 #elif defined(_MSC_VER) | 107 #elif defined(_MSC_VER) |
| 62 | 108 |
| 63 #pragma intrinsic(_BitScanForward) | 109 #pragma intrinsic(_BitScanForward) |
| 64 #pragma intrinsic(_BitScanReverse) | 110 #pragma intrinsic(_BitScanReverse) |
| 111 #if V8_TARGET_ARCH_X64 |
| 112 #pragma intrinsic(_BitScanForward64) |
| 113 #pragma intrinsic(_BitScanReverse64) |
| 114 #endif |
| 65 | 115 |
| 66 int CompilerIntrinsics::CountTrailingZeros(uint32_t value) { | 116 int CompilerIntrinsics::CountTrailingZeros(uint32_t value) { |
| 67 unsigned long result; //NOLINT | 117 unsigned long result; //NOLINT |
| 68 _BitScanForward(&result, static_cast<long>(value)); //NOLINT | 118 _BitScanForward(&result, static_cast<long>(value)); //NOLINT |
| 69 return static_cast<int>(result); | 119 return static_cast<int>(result); |
| 70 } | 120 } |
| 71 | 121 |
| 122 int CompilerIntrinsics::CountTrailingZeros(uint64_t value) { |
| 123 #if V8_TARGET_ARCH_X64 |
| 124 unsigned long result; //NOLINT |
| 125 _BitScanForward64(&result, static_cast<__int64>(value)); //NOLINT |
| 126 return static_cast<int>(result); |
| 127 #else |
| 128 uint32_t low = value & kMaxUInt32; |
| 129 uint32_t high = value >> 32; |
| 130 if (low == 0) { |
| 131 return 32 + CountTrailingZeros(high); |
| 132 } else { |
| 133 return CountTrailingZeros(low); |
| 134 } |
| 135 #endif |
| 136 } |
| 137 |
| 72 int CompilerIntrinsics::CountLeadingZeros(uint32_t value) { | 138 int CompilerIntrinsics::CountLeadingZeros(uint32_t value) { |
| 73 unsigned long result; //NOLINT | 139 unsigned long result; //NOLINT |
| 74 _BitScanReverse(&result, static_cast<long>(value)); //NOLINT | 140 _BitScanReverse(&result, static_cast<long>(value)); //NOLINT |
| 75 return 31 - static_cast<int>(result); | 141 return 31 - static_cast<int>(result); |
| 76 } | 142 } |
| 77 | 143 |
| 144 int CompilerIntrinsics::CountLeadingZeros(uint64_t value) { |
| 145 #if V8_TARGET_ARCH_X64 |
| 146 unsigned long result; //NOLINT |
| 147 _BitScanReverse64(&result, static_cast<__int64>(value)); //NOLINT |
| 148 return 63 - static_cast<int>(result); |
| 149 #else |
| 150 uint32_t low = value & kMaxUInt32; |
| 151 uint32_t high = value >> 32; |
| 152 if (high == 0) { |
| 153 return 32 + CountLeadingZeros(low); |
| 154 } else { |
| 155 return CountLeadingZeros(high); |
| 156 } |
| 157 #endif |
| 158 } |
| 159 |
| 160 int CompilerIntrinsics::CountRedundantLeadingSignBits(int32_t value) { |
| 161 uint32_t val = static_cast<uint32_t>((value >= 0) ? value : ~value); |
| 162 return CountLeadingZeros(val, width) - 1; |
| 163 } |
| 164 |
| 165 int CompilerIntrinsics::CountRedundantLeadingSignBits(int64_t value) { |
| 166 uint64_t val = static_cast<uint64_t>((value >= 0) ? value : ~value); |
| 167 return CountLeadingZeros(val, width) - 1; |
| 168 } |
| 169 |
| 78 int CompilerIntrinsics::CountSetBits(uint32_t value) { | 170 int CompilerIntrinsics::CountSetBits(uint32_t value) { |
| 79 // Manually count set bits. | 171 return C_CountSetBits(value, 32); |
| 80 value = ((value >> 1) & 0x55555555) + (value & 0x55555555); | 172 } |
| 81 value = ((value >> 2) & 0x33333333) + (value & 0x33333333); | 173 |
| 82 value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f); | 174 int CompilerIntrinsics::CountSetBits(uint64_t value) { |
| 83 value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff); | 175 return C_CountSetBits(value, 64); |
| 84 value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff); | |
| 85 return value; | |
| 86 } | 176 } |
| 87 | 177 |
| 88 #else | 178 #else |
| 89 #error Unsupported compiler | 179 #error Unsupported compiler |
| 90 #endif | 180 #endif |
| 91 | 181 |
| 182 |
| 183 // Inline function helpers use the intrinsics and disambiguate undefined |
| 184 // situations. |
| 185 |
| 186 inline int CountTrailingZeros(uint32_t value) { |
| 187 if (value == 0) { |
| 188 // The result of the intrinsics is undefined for 0. |
| 189 return 32; |
| 190 } |
| 191 return CompilerIntrinsics::CountTrailingZeros(value); |
| 192 } |
| 193 inline int CountTrailingZeros(uint64_t value) { |
| 194 if (value == 0) { |
| 195 // The result of the intrinsics is undefined for 0. |
| 196 return 64; |
| 197 } |
| 198 return CompilerIntrinsics::CountTrailingZeros(value); |
| 199 } |
| 200 inline int CountTrailingZeros(uint64_t value, int width) { |
| 201 ASSERT((width == 32) || (width == 64)); |
| 202 if (width == 32) { |
| 203 return CountTrailingZeros(static_cast<uint32_t>(value)); |
| 204 } else { |
| 205 return CountTrailingZeros(static_cast<uint64_t>(value)); |
| 206 } |
| 207 } |
| 208 |
| 209 inline int CountLeadingZeros(uint32_t value) { |
| 210 if (value == 0) { |
| 211 // The result of the intrinsics is undefined for 0. |
| 212 return 32; |
| 213 } |
| 214 return CompilerIntrinsics::CountLeadingZeros(value); |
| 215 } |
| 216 inline int CountLeadingZeros(uint64_t value) { |
| 217 if (value == 0) { |
| 218 // The result of the intrinsics is undefined for 0. |
| 219 return 64; |
| 220 } |
| 221 return CompilerIntrinsics::CountLeadingZeros(value); |
| 222 } |
| 223 inline int CountLeadingZeros(uint64_t value, int width) { |
| 224 ASSERT((width == 32) || (width == 64)); |
| 225 if (width == 32) { |
| 226 return CountLeadingZeros(static_cast<uint32_t>(value)); |
| 227 } else { |
| 228 return CountLeadingZeros(static_cast<uint64_t>(value)); |
| 229 } |
| 230 } |
| 231 |
| 232 inline int CountRedundantLeadingSignBits(int32_t value) { |
| 233 return CompilerIntrinsics::CountRedundantLeadingSignBits(value); |
| 234 } |
| 235 inline int CountRedundantLeadingSignBits(int64_t value) { |
| 236 return CompilerIntrinsics::CountRedundantLeadingSignBits(value); |
| 237 } |
| 238 inline int CountRedundantLeadingSignBits(int64_t value, int width) { |
| 239 ASSERT((width == 32) || (width == 64)); |
| 240 if (width == 32) { |
| 241 return CountRedundantLeadingSignBits(static_cast<int32_t>(value)); |
| 242 } else { |
| 243 return CountRedundantLeadingSignBits(static_cast<int64_t>(value)); |
| 244 } |
| 245 } |
| 246 |
| 247 inline int CountSetBits(uint32_t value) { |
| 248 return CompilerIntrinsics::CountSetBits(value); |
| 249 } |
| 250 inline int CountSetBits(uint64_t value) { |
| 251 return CompilerIntrinsics::CountSetBits(value); |
| 252 } |
| 253 inline int CountSetBits(uint64_t value, int width) { |
| 254 ASSERT((width == 32) || (width == 64)); |
| 255 if (width == 32) { |
| 256 return CountSetBits(static_cast<uint32_t>(value)); |
| 257 } else { |
| 258 return CountSetBits(static_cast<uint64_t>(value)); |
| 259 } |
| 260 } |
| 261 |
| 262 |
| 92 } } // namespace v8::internal | 263 } } // namespace v8::internal |
| 93 | 264 |
| 94 #endif // V8_COMPILER_INTRINSICS_H_ | 265 #endif // V8_COMPILER_INTRINSICS_H_ |
| OLD | NEW |