X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FBits.cpp;h=5b61d470434ee85a65a39269bfd3dc810f482381;hb=314c43c4f95dc51f2c97d00216be062eebbd5454;hp=9513cd33c84df0c325558faf3aaf22925a4f8b00;hpb=267e38a8cee0569f04baa0b649c0f65ad29b0440;p=folly.git diff --git a/folly/Bits.cpp b/folly/Bits.cpp index 9513cd33..5b61d470 100644 --- a/folly/Bits.cpp +++ b/folly/Bits.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2013 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,41 +14,44 @@ * limitations under the License. */ -#include "folly/Bits.h" +#include -#include "folly/CpuId.h" +#include +#include // None of this is necessary if we're compiling for a target that supports -// popcnt -#ifndef __POPCNT__ - +// popcnt, which includes MSVC +#if !defined(__POPCNT__) && !defined(_MSC_VER) namespace { +int popcount_builtin(unsigned int x) { + return __builtin_popcount(x); +} + +int popcountll_builtin(unsigned long long x) { + return __builtin_popcountll(x); +} + +#if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS) + +// Strictly speaking, these versions of popcount are usable without ifunc +// support. However, we would have to check, via CpuId, if the processor +// implements the popcnt instruction first, which is what we use ifunc for. int popcount_inst(unsigned int x) { int n; asm ("popcntl %1, %0" : "=r" (n) : "r" (x)); return n; } -int popcount_builtin(unsigned int x) { - return __builtin_popcount(x); -} - int popcountll_inst(unsigned long long x) { unsigned long long n; asm ("popcntq %1, %0" : "=r" (n) : "r" (x)); return n; } -int popcountll_builtin(unsigned long long x) { - return __builtin_popcountll(x); -} - typedef decltype(popcount_builtin) Type_popcount; typedef decltype(popcountll_builtin) Type_popcountll; -} // namespace - // This function is called on startup to resolve folly::detail::popcount extern "C" Type_popcount* folly_popcount_ifunc() { return folly::CpuId().popcnt() ? popcount_inst : popcount_builtin; @@ -59,31 +62,32 @@ extern "C" Type_popcountll* folly_popcountll_ifunc() { return folly::CpuId().popcnt() ? popcountll_inst : popcountll_builtin; } +#endif // FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS) + +} // namespace + namespace folly { namespace detail { // Call folly_popcount_ifunc on startup to resolve to either popcount_inst // or popcount_builtin int popcount(unsigned int x) -// Clang does not support ifuncs, so we call directly for now -#ifdef __clang__ -{ return popcount_builtin(x); } +#if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS) + __attribute__((__ifunc__("folly_popcount_ifunc"))); #else - __attribute__((ifunc("folly_popcount_ifunc"))); +{ return popcount_builtin(x); } #endif // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst // or popcountll_builtin int popcountll(unsigned long long x) -// Clang does not support ifuncs, so we call directly for now -#ifdef __clang__ -{ return popcount_builtin(x); } +#if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS) + __attribute__((__ifunc__("folly_popcountll_ifunc"))); #else - __attribute__((ifunc("folly_popcountll_ifunc"))); +{ return popcountll_builtin(x); } #endif } // namespace detail } // namespace folly #endif /* !__POPCNT__ */ -