Share "scan16" between Node16 and Node48
Some checks failed
Tests / Clang total: 1130, passed: 1130
Clang |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / SIMD fallback total: 1130, passed: 1130
Tests / Release [gcc] total: 1130, passed: 1130
GNU C Compiler (gcc) |Total|New|Outstanding|Fixed|Trend |:-:|:-:|:-:|:-:|:-: |0|0|0|0|:clap:
Tests / Release [gcc,aarch64] total: 844, passed: 844
Tests / Coverage total: 848, passed: 848
weaselab/conflict-set/pipeline/head There was a failure building this commit

This commit is contained in:
2024-06-27 13:22:51 -07:00
parent 7de983cc15
commit 639518bed4

View File

@@ -293,7 +293,7 @@ struct Node48 : Node {
Node *children[kMaxNodes]; Node *children[kMaxNodes];
int64_t childMaxVersion[kMaxNodes]; int64_t childMaxVersion[kMaxNodes];
uint8_t reverseIndex[kMaxNodes]; uint8_t reverseIndex[kMaxNodes];
constexpr static int kMaxOfMaxPageSize = 8; constexpr static int kMaxOfMaxPageSize = 16;
constexpr static int kMaxOfMaxShift = constexpr static int kMaxOfMaxShift =
std::countr_zero(uint32_t(kMaxOfMaxPageSize)); std::countr_zero(uint32_t(kMaxOfMaxPageSize));
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize; constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
@@ -1709,6 +1709,47 @@ downLeftSpine:
} }
} }
// Returns true if all in-bounds vs are <= readVersion
bool scan16(const int64_t *vs, const uint8_t *is, int begin, int end,
int64_t readVersion) {
#ifdef HAS_ARM_NEON
assert(end - begin < 256);
uint8x16_t indices;
memcpy(&indices, is, 16);
// 0xff for each in bounds
auto results =
vcltq_u8(vsubq_u8(indices, vdupq_n_u8(begin)), vdupq_n_u8(end - begin));
// 0xf for each 0xff
uint64_t mask = vget_lane_u64(
vreinterpret_u64_u8(vshrn_n_u16(vreinterpretq_u16_u8(results), 4)), 0);
uint64_t compared = 0;
for (int i = 0; i < 16; ++i) {
compared |= (uint64_t(vs[i] > readVersion) << (i << 2));
}
return !(compared & mask);
#else
const unsigned shiftUpperBound = end - begin;
const unsigned shiftAmount = begin;
auto inBounds = [&](unsigned c) { return c - shiftAmount < shiftUpperBound; };
uint32_t compared = 0;
for (int i = 0; i < 16; ++i) {
compared |= ((vs[i] > readVersion) << i);
}
uint32_t mask = 0;
for (int i = 0; i < 16; ++i) {
mask |= inBounds(is[i]) << i;
}
return !(compared & mask);
#endif
}
// Return whether or not the max version among all keys starting with the search // Return whether or not the max version among all keys starting with the search
// path of n + [child], where child in (begin, end) is <= readVersion. Does not // path of n + [child], where child in (begin, end) is <= readVersion. Does not
// account for the range version of firstGt(searchpath(n) + [end - 1]) // account for the range version of firstGt(searchpath(n) + [end - 1])
@@ -1759,49 +1800,23 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end,
case Type_Node16: { case Type_Node16: {
auto *self = static_cast<Node16 *>(n); auto *self = static_cast<Node16 *>(n);
#ifdef HAS_ARM_NEON return scan16(self->childMaxVersion, self->index, begin, end, readVersion);
assert(end - begin < 256);
uint8x16_t indices;
memcpy(&indices, self->index, sizeof(self->index));
// 0xff for each in bounds
auto results =
vcltq_u8(vsubq_u8(indices, vdupq_n_u8(begin)), vdupq_n_u8(end - begin));
// 0xf for each 0xff
uint64_t mask = vget_lane_u64(
vreinterpret_u64_u8(vshrn_n_u16(vreinterpretq_u16_u8(results), 4)), 0);
uint64_t compared = 0;
for (int i = 0; i < 16; ++i) {
compared |=
(uint64_t(self->childMaxVersion[i] > readVersion) << (i << 2));
}
return !(compared & mask);
#else
uint32_t compared = 0;
for (int i = 0; i < 16; ++i) {
compared |= ((self->childMaxVersion[i] > readVersion) << i);
}
uint32_t mask = 0;
for (int i = 0; i < 16; ++i) {
mask |= inBounds(self->index[i]) << i;
}
return !(compared & mask);
#endif
} break; } break;
case Type_Node48: { case Type_Node48: {
auto *self = static_cast<Node48 *>(n); auto *self = static_cast<Node48 *>(n);
// Check all pages // Check all pages
bool result = true; static_assert(Node48::kMaxOfMaxPageSize == 16);
for (int i = 0; i < Node48::kMaxOfMaxTotalPages; ++i) { for (int i = 0; i < Node48::kMaxOfMaxTotalPages; ++i) {
if (self->maxOfMax[i] > readVersion) { if (self->maxOfMax[i] > readVersion) {
for (int j = 0; j < Node48::kMaxOfMaxPageSize; ++j) { if (!scan16(self->childMaxVersion + (i << Node48::kMaxOfMaxShift),
int k = (i << Node48::kMaxOfMaxShift) + j; self->reverseIndex + (i << Node48::kMaxOfMaxShift), begin,
result &= !((self->childMaxVersion[k] > readVersion) & end, readVersion)) {
inBounds(self->reverseIndex[k])); return false;
} }
} }
} }
return result; return true;
} }
case Type_Node256: { case Type_Node256: {
auto *self = static_cast<Node256 *>(n); auto *self = static_cast<Node256 *>(n);