Path: blob/master/src/hotspot/share/utilities/count_leading_zeros.hpp
40949 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_UTILITIES_COUNT_LEADING_ZEROS_HPP25#define SHARE_UTILITIES_COUNT_LEADING_ZEROS_HPP2627#include "utilities/debug.hpp"28#include "utilities/globalDefinitions.hpp"2930// uint32_t count_leading_zeros(T x)3132// Return the number of leading zeros in x, e.g. the zero-based index33// of the most significant set bit in x. Undefined for 0.3435// We implement and support variants for 8, 16, 32 and 64 bit integral types.36template <typename T, size_t n> struct CountLeadingZerosImpl;3738template <typename T> unsigned count_leading_zeros(T v) {39assert(v != 0, "precondition");40return CountLeadingZerosImpl<T, sizeof(T)>::doit(v);41}4243/*****************************************************************************44* GCC and compatible (including Clang)45*****************************************************************************/46#if defined(TARGET_COMPILER_gcc)4748template <typename T> struct CountLeadingZerosImpl<T, 1> {49static unsigned doit(T v) {50return __builtin_clz((uint32_t)v & 0xFF) - 24u;51}52};5354template <typename T> struct CountLeadingZerosImpl<T, 2> {55static unsigned doit(T v) {56return __builtin_clz((uint32_t)v & 0xFFFF) - 16u;57}58};5960template <typename T> struct CountLeadingZerosImpl<T, 4> {61static unsigned doit(T v) {62return __builtin_clz(v);63}64};6566template <typename T> struct CountLeadingZerosImpl<T, 8> {67static unsigned doit(T v) {68return __builtin_clzll(v);69}70};7172/*****************************************************************************73* Microsoft Visual Studio74*****************************************************************************/75#elif defined(TARGET_COMPILER_visCPP)7677#include <intrin.h>78#pragma intrinsic(_BitScanReverse)7980#ifdef _LP6481#pragma intrinsic(_BitScanReverse64)82#endif8384template <typename T> struct CountLeadingZerosImpl<T, 1> {85static unsigned doit(T v) {86unsigned long index;87_BitScanReverse(&index, (uint32_t)v & 0xFF);88return 7u - index;89}90};9192template <typename T> struct CountLeadingZerosImpl<T, 2> {93static unsigned doit(T v) {94unsigned long index;95_BitScanReverse(&index, (uint32_t)v & 0xFFFF);96return 15u - index;97}98};99100template <typename T> struct CountLeadingZerosImpl<T, 4> {101static unsigned doit(T v) {102unsigned long index;103_BitScanReverse(&index, v);104return 31u - index;105}106};107108template <typename T> struct CountLeadingZerosImpl<T, 8> {109static unsigned doit(T v) {110#ifdef _LP64111unsigned long index;112_BitScanReverse64(&index, v);113return 63u - index;114#else115uint64_t high = ((uint64_t)v) >> 32ULL;116if (high != 0) {117return count_leading_zeros((uint32_t)high);118} else {119return count_leading_zeros((uint32_t)v) + 32;120}121#endif122}123};124125/*****************************************************************************126* IBM XL C/C++127*****************************************************************************/128#elif defined(TARGET_COMPILER_xlc)129130#include <builtins.h>131132template <typename T> struct CountLeadingZerosImpl<T, 1> {133static unsigned doit(T v) {134return __cntlz4((uint32_t)v & 0xFF) - 24u;135}136};137138template <typename T> struct CountLeadingZerosImpl<T, 2> {139static unsigned doit(T v) {140return __cntlz4((uint32_t)v & 0xFFFF) - 16u;141}142};143144template <typename T> struct CountLeadingZerosImpl<T, 4> {145static unsigned doit(T v) {146return __cntlz4(v);147}148};149150template <typename T> struct CountLeadingZerosImpl<T, 8> {151static unsigned doit(T v) {152return __cntlz8(v);153}154};155156/*****************************************************************************157* Fallback158*****************************************************************************/159#else160161inline uint32_t count_leading_zeros_32(uint32_t x) {162assert(x != 0, "precondition");163164// Efficient and portable fallback implementation:165// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn166// - with positions xor'd by 31 to get number of leading zeros167// rather than position of highest bit.168static const uint32_t MultiplyDeBruijnBitPosition[32] = {16931, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,17023, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0171};172173// First round down to one less than a power of 2174x |= x >> 1;175x |= x >> 2;176x |= x >> 4;177x |= x >> 8;178x |= x >> 16;179// Multiply by a magic constant which ensure the highest 5 bits point to180// the right index in the lookup table181return MultiplyDeBruijnBitPosition[(x * 0x07c4acddu) >> 27u];182}183184template <typename T> struct CountLeadingZerosImpl<T, 1> {185static unsigned doit(T v) {186return count_leading_zeros_32((uint32_t)v & 0xFF) - 24u;187}188};189190template <typename T> struct CountLeadingZerosImpl<T, 2> {191static unsigned doit(T v) {192return count_leading_zeros_32((uint32_t)v & 0xFFFF) - 16u;193}194};195196template <typename T> struct CountLeadingZerosImpl<T, 4> {197static unsigned doit(T v) {198return count_leading_zeros_32(v);199}200};201202template <typename T> struct CountLeadingZerosImpl<T, 8> {203static unsigned doit(T v) {204uint64_t high = ((uint64_t)v) >> 32ULL;205if (high != 0) {206return count_leading_zeros_32((uint32_t)high);207} else {208return count_leading_zeros_32((uint32_t)v) + 32u;209}210}211};212213#endif214215#endif // SHARE_UTILITIES_COUNT_LEADING_ZEROS_HPP216217218