+ static FOLLY_ALWAYS_INLINE uint64_t
+ bextr(uint64_t value, uint32_t start, uint32_t length) {
+#if defined(__GNUC__) || defined(__clang__)
+ // GCC and Clang won't inline the intrinsics.
+ // Encode parameters in `pattern` where `pattern[0:7]` is `start` and
+ // `pattern[8:15]` is `length`.
+ // Ref: Intel Advanced Vector Extensions Programming Reference
+ 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__) || defined(__clang__)
+ // GCC and Clang won't inline the intrinsics.
+ 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
+ }
+};
+} // namespace instructions
+} // namespace compression
+} // namespace folly