Chromium Code Reviews| Index: base/bits.h |
| diff --git a/base/bits.h b/base/bits.h |
| index a3a59d1dfad0d4c2992b1a6d0abd9a0c4fc2b1aa..301a0353f0f3e617e25f61921a31fe4e23a1ab62 100644 |
| --- a/base/bits.h |
| +++ b/base/bits.h |
| @@ -1,4 +1,4 @@ |
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| @@ -10,8 +10,13 @@ |
| #include <stddef.h> |
| #include <stdint.h> |
| +#include "base/compiler_specific.h" |
| #include "base/logging.h" |
| +#if defined(COMPILER_MSVC) |
| +#include <intrin.h> |
| +#endif |
| + |
| namespace base { |
| namespace bits { |
| @@ -49,6 +54,58 @@ inline size_t Align(size_t size, size_t alignment) { |
| return (size + alignment - 1) & ~(alignment - 1); |
| } |
| +// These functions count the number of leading zeros in a binary value, starting |
| +// with the most significant bit. C does not have an operator to do this, but |
| +// fortunately the various compilers have built-ins that map to fast underlying |
| +// processor instructions. |
| +#if defined(COMPILER_MSVC) |
| + |
| +ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { |
| + unsigned long index; |
| + return LIKELY(_BitScanReverse(&index, x)) ? (31 - index) : 32; |
| +} |
| + |
| +#if defined(ARCH_CPU_64_BITS) |
| + |
| +// MSVC only supplies _BitScanForward64 when building for a 64-bit target. |
| +ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { |
| + unsigned long index; |
| + return LIKELY(_BitScanReverse64(&index, x)) ? (63 - index) : 64; |
| +} |
| + |
| +#endif |
| + |
| +#elif defined(COMPILER_GCC) |
| + |
| +// This is very annoying. __builtin_clz has undefined behaviour for an input of |
| +// 0, even though these's clearly a return value that makes sense, and even |
|
dcheng
2016/11/17 20:06:25
these's?
I wonder if this comment meant to write
palmer
2016/11/17 20:18:27
Done.
|
| +// though nascent processor clz instructions have defined behaviour for 0. |
|
dcheng
2016/11/17 20:06:25
Not sure if it's still nascent ;-)
palmer
2016/11/17 20:18:27
Done.
|
| +// We could drop to raw __asm__ to do better, but we'll avoid doing that unless |
| +// we see proof that we need to. |
| +ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) { |
| + return LIKELY(x) ? __builtin_clz(x) : 32; |
| +} |
| + |
| +ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) { |
| + return LIKELY(x) ? __builtin_clzll(x) : 64; |
| +} |
| + |
| +#endif |
| + |
| +#if defined(ARCH_CPU_64_BITS) |
| + |
| +ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { |
| + return CountLeadingZeroBits64(x); |
| +} |
| + |
| +#else |
| + |
| +ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) { |
| + return CountLeadingZeroBits32(x); |
| +} |
| + |
| +#endif |
| + |
| } // namespace bits |
| } // namespace base |