diff --git a/hll/include/Hll8Array-internal.hpp b/hll/include/Hll8Array-internal.hpp
index 5e4239ec..8c008d0f 100644
--- a/hll/include/Hll8Array-internal.hpp
+++ b/hll/include/Hll8Array-internal.hpp
@@ -120,30 +120,29 @@ void Hll8Array::mergeHll(const HllArray& src) {
// we can optimize further when the k values are equal
if (this->getLgConfigK() == src.getLgConfigK()) {
if (src.getTgtHllType() == target_hll_type::HLL_8) {
- uint32_t i = 0;
- for (const auto value: src.getHllArray()) {
- this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
- ++i;
+ // Hoist the data pointer out of the loop to encourage vectorization
+ const uint8_t* src_data = src.getHllArray().data();
+ uint8_t* data = this->hllByteArr_.data();
+ const size_t n = src.getHllArray().size();
+ for (size_t i = 0; i < n; ++i) {
+ data[i] = std::max(data[i], src_data[i]);
}
} else if (src.getTgtHllType() == target_hll_type::HLL_6) {
- const uint32_t src_k = 1 << src.getLgConfigK();
- uint32_t i = 0;
- const uint8_t* ptr = src.getHllArray().data();
- while (i < src_k) {
- uint8_t value = *ptr & 0x3f;
- this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
- ++i;
- value = *ptr++ >> 6;
- value |= (*ptr & 0x0f) << 2;
- this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
- ++i;
- value = *ptr++ >> 4;
- value |= (*ptr & 3) << 4;
- this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
- ++i;
- value = *ptr++ >> 2;
- this->hllByteArr_[i] = std::max(this->hllByteArr_[i], value);
- ++i;
+ const uint8_t* src_data = src.getHllArray().data();
+ uint8_t* data = this->hllByteArr_.data();
+ const size_t src_k = 1 << src.getLgConfigK();
+ const size_t num_groups = src_k / 4;
+ for (size_t g = 0; g < num_groups; ++g) {
+ const size_t i = 4 * g;
+ const size_t j = 3 * g;
+ // Read into locals so that stores don't force reloads
+ const uint8_t b0 = src_data[j];
+ const uint8_t b1 = src_data[j + 1];
+ const uint8_t b2 = src_data[j + 2];
+ data[i] = std::max(data[i], b0 & 0x3f);
+ data[i + 1] = std::max(data[i + 1], (b0 >> 6) | ((b1 & 0x0f) << 2));
+ data[i + 2] = std::max(data[i + 2], (b1 >> 4) | ((b2 & 3) << 4));
+ data[i + 3] = std::max(data[i + 3], b2 >> 2);
}
} else { // HLL_4
const auto& src4 = static_cast&>(src);