| Index: base/bits.h
|
| diff --git a/base/bits.h b/base/bits.h
|
| index a3a59d1dfad0d4c2992b1a6d0abd9a0c4fc2b1aa..d101cb731a7da764150ff567777a1c232c4f522f 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 there's clearly a return value that makes sense, and even
|
| +// though some processor clz instructions have defined behaviour for 0. 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
|
|
|
|
|