From 86e0057c168a70f5cbe8a1d5397ee7bd0beb16d8 Mon Sep 17 00:00:00 2001 From: Vignesh Gowda Date: Thu, 18 Jun 2015 10:00:51 -0700 Subject: [PATCH] Move folly::compression::Instructions to a separate file Summary: Moved abstraction layer for platform-specific bit-manipulation instructions from the EliasFanoCoding.h to Instructions.h since we will need to use it also for BitVectors: Reviewed By: @ot Differential Revision: D2165314 --- folly/Makefile.am | 1 + folly/experimental/EliasFanoCoding.h | 58 +-------------------- folly/experimental/Instructions.h | 77 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 57 deletions(-) create mode 100644 folly/experimental/Instructions.h diff --git a/folly/Makefile.am b/folly/Makefile.am index bdfbe6d5..9b1c9e0a 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -77,6 +77,7 @@ nobase_follyinclude_HEADERS = \ experimental/ExecutionObserver.h \ experimental/EliasFanoCoding.h \ experimental/EventCount.h \ + experimental/Instructions.h \ experimental/fibers/AddTasks.h \ experimental/fibers/AddTasks-inl.h \ experimental/fibers/Baton.h \ diff --git a/folly/experimental/EliasFanoCoding.h b/folly/experimental/EliasFanoCoding.h index 3d85bf3d..f5fcfe86 100644 --- a/folly/experimental/EliasFanoCoding.h +++ b/folly/experimental/EliasFanoCoding.h @@ -34,8 +34,8 @@ #include #include #include +#include #include - #ifndef __GNUC__ #error EliasFanoCoding.h requires GCC #endif @@ -329,62 +329,6 @@ struct EliasFanoEncoderV2 in realtime (client should -// implement this switching logic itself) by specifying instruction set to -// use explicitly. -namespace instructions { - -struct Default { - static bool supported(const folly::CpuId& cpuId = {}) { - return true; - } - static inline uint64_t popcount(uint64_t value) { - return __builtin_popcountll(value); - } - static inline int ctz(uint64_t value) { - DCHECK_GT(value, 0); - return __builtin_ctzll(value); - } - static inline int clz(uint64_t value) { - DCHECK_GT(value, 0); - return __builtin_clzll(value); - } - static inline uint64_t blsr(uint64_t value) { - return value & (value - 1); - } -}; - -struct Nehalem : public Default { - static bool supported(const folly::CpuId& cpuId = {}) { - return cpuId.popcnt(); - } - static inline uint64_t popcount(uint64_t value) { - // POPCNT is supported starting with Intel Nehalem, AMD K10. - uint64_t result; - asm ("popcntq %1, %0" : "=r" (result) : "r" (value)); - return result; - } -}; - -struct Haswell : public Nehalem { - static bool supported(const folly::CpuId& cpuId = {}) { - return Nehalem::supported(cpuId) && cpuId.bmi1(); - } - static inline uint64_t blsr(uint64_t value) { - // BMI1 is supported starting with Intel Haswell, AMD Piledriver. - // BLSR combines two instuctions into one and reduces register pressure. - uint64_t result; - asm ("blsrq %1, %0" : "=r" (result) : "r" (value)); - return result; - } -}; - -} // namespace instructions - namespace detail { template diff --git a/folly/experimental/Instructions.h b/folly/experimental/Instructions.h new file mode 100644 index 00000000..694e1f50 --- /dev/null +++ b/folly/experimental/Instructions.h @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOLLY_EXPERIMENTAL_INSTRUCTIONS_H +#define FOLLY_EXPERIMENTAL_INSTRUCTIONS_H + +namespace folly { namespace compression { namespace instructions { + +// NOTE: It's recommended to compile EF coding with -msse4.2, starting +// with Nehalem, Intel CPUs support POPCNT instruction and gcc will emit +// it for __builtin_popcountll intrinsic. +// But we provide an alternative way for the client code: it can switch to +// the appropriate version of EliasFanoReader<> in realtime (client should +// implement this switching logic itself) by specifying instruction set to +// use explicitly. + +struct Default { + static bool supported(const folly::CpuId& cpuId = {}) { + return true; + } + static inline uint64_t popcount(uint64_t value) { + return __builtin_popcountll(value); + } + static inline int ctz(uint64_t value) { + DCHECK_GT(value, 0); + return __builtin_ctzll(value); + } + static inline int clz(uint64_t value) { + DCHECK_GT(value, 0); + return __builtin_clzll(value); + } + static inline uint64_t blsr(uint64_t value) { + return value & (value - 1); + } +}; + +struct Nehalem : public Default { + static bool supported(const folly::CpuId& cpuId = {}) { + return cpuId.popcnt(); + } + static inline uint64_t popcount(uint64_t value) { + // POPCNT is supported starting with Intel Nehalem, AMD K10. + uint64_t result; + asm ("popcntq %1, %0" : "=r" (result) : "r" (value)); + return result; + } +}; + +struct Haswell : public Nehalem { + static bool supported(const folly::CpuId& cpuId = {}) { + return Nehalem::supported(cpuId) && cpuId.bmi1(); + } + static inline uint64_t blsr(uint64_t value) { + // BMI1 is supported starting with Intel Haswell, AMD Piledriver. + // BLSR combines two instuctions into one and reduces register pressure. + uint64_t result; + asm ("blsrq %1, %0" : "=r" (result) : "r" (value)); + return result; + } +}; + +}}} // namespaces + +#endif // FOLLY_EXPERIMENTAL_INSTRUCTIONS_H -- 2.34.1