#pragma once
#include <glog/logging.h>
#ifdef _MSC_VER
#include <immintrin.h>
#endif
#include <string_view>
#include <folly/CpuId.h>
#include <folly/Portability.h>
#include <folly/lang/Assume.h>
#include <folly/portability/Builtins.h>
namespace folly {
namespace compression {
namespace instructions {
struct Default { … };
#if FOLLY_X64 || defined(__i386__)
struct Nehalem : public Default {
static std::string_view name() noexcept { return "Nehalem"; }
static bool supported(const folly::CpuId& cpuId = {}) {
return cpuId.popcnt();
}
static FOLLY_ALWAYS_INLINE uint64_t popcount(uint64_t value) {
#if defined(__GNUC__)
uint64_t result;
asm("popcntq %1, %0" : "=r"(result) : "r"(value));
return result;
#else
return uint64_t(_mm_popcnt_u64(value));
#endif
}
};
struct Haswell : public Nehalem {
static std::string_view name() noexcept { return "Haswell"; }
static bool supported(const folly::CpuId& cpuId = {}) {
return Nehalem::supported(cpuId) && cpuId.bmi1() && cpuId.bmi2();
}
static FOLLY_ALWAYS_INLINE uint64_t blsr(uint64_t value) {
#if defined(__GNUC__)
uint64_t result;
asm("blsrq %1, %0" : "=r"(result) : "r"(value));
return result;
#else
return _blsr_u64(value);
#endif
}
static FOLLY_ALWAYS_INLINE uint64_t
bextr(uint64_t value, uint32_t start, uint32_t length) {
#if defined(__GNUC__)
uint64_t pattern = start & 0xFF;
pattern = pattern | ((length & 0xFF) << 8);
uint64_t result;
asm("bextrq %2, %1, %0" : "=r"(result) : "r"(value), "r"(pattern));
return result;
#else
return _bextr_u64(value, start, length);
#endif
}
static FOLLY_ALWAYS_INLINE uint64_t bzhi(uint64_t value, uint32_t index) {
#if defined(__GNUC__)
const uint64_t index64 = index;
uint64_t result;
asm("bzhiq %2, %1, %0" : "=r"(result) : "r"(value), "r"(index64));
return result;
#else
return _bzhi_u64(value, index);
#endif
}
};
#endif
enum class Type { … };
inline Type detect() { … }
template <class F>
auto dispatch(Type type, F&& f) -> decltype(f(std::declval<Default>())) { … }
template <class F>
auto dispatch(F&& f) -> decltype(f(std::declval<Default>())) { … }
}
}
}