From 9046dc5a8fddfa3367f40617ec689fb86b9c417e Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Sun, 7 Jul 2024 17:28:45 -0700 Subject: [PATCH] Only switch on type once in checkMaxBetweenExclusive --- ConflictSet.cpp | 97 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 21 deletions(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 8588061..31b7eb6 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -2001,31 +2001,30 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, assert(!(begin == -1 && end == 256)); - { - int c = getChildGeq(n, begin + 1); - if (c >= 0 && c < end) { - auto *child = getChildExists(n, c); - if (child->entryPresent) { - if (!(child->entry.rangeVersion <= readVersion)) { - return false; - }; - } - begin = c; - } else { - return true; - } - } - - // [begin, end) is now the half-open interval of children we're interested in. - assert(begin < end); - switch (n->getType()) { - case Type_Node0: // GCOVR_EXCL_LINE - // We would have returned above, after not finding a child - __builtin_unreachable(); // GCOVR_EXCL_LINE + case Type_Node0: + return true; case Type_Node3: { auto *self = static_cast(n); + { + int c = begin == 255 ? -1 : getChildGeqSimd(self, begin + 1); + if (c >= 0 && c < end) { + auto *child = self->children[getNodeIndex(self, c)]; + if (child->entryPresent) { + if (!(child->entry.rangeVersion <= readVersion)) { + return false; + }; + } + begin = c; + } else { + return true; + } + // [begin, end) is now the half-open interval of children we're interested + // in. + assert(begin < end); + } + const unsigned shiftUpperBound = end - begin; const unsigned shiftAmount = begin; auto inBounds = [&](unsigned c) { @@ -2045,11 +2044,48 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, case Type_Node16: { auto *self = static_cast(n); + { + int c = begin == 255 ? -1 : getChildGeqSimd(self, begin + 1); + if (c >= 0 && c < end) { + auto *child = self->children[getNodeIndex(self, c)]; + if (child->entryPresent) { + if (!(child->entry.rangeVersion <= readVersion)) { + return false; + }; + } + begin = c; + } else { + return true; + } + // [begin, end) is now the half-open interval of children we're interested + // in. + assert(begin < end); + } + return scan16(self->childMaxVersion, self->index, begin, end, readVersion); } case Type_Node48: { auto *self = static_cast(n); + + { + int c = self->bitSet.firstSetGeq(begin + 1); + if (c >= 0 && c < end) { + auto *child = self->children[self->index[c]]; + if (child->entryPresent) { + if (!(child->entry.rangeVersion <= readVersion)) { + return false; + }; + } + begin = c; + } else { + return true; + } + // [begin, end) is now the half-open interval of children we're interested + // in. + assert(begin < end); + } + // Check all pages static_assert(Node48::kMaxOfMaxPageSize == 16); for (int i = 0; i < Node48::kMaxOfMaxTotalPages; ++i) { @@ -2067,6 +2103,25 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, case Type_Node256: { static_assert(Node256::kMaxOfMaxTotalPages == 16); auto *self = static_cast(n); + + { + int c = self->bitSet.firstSetGeq(begin + 1); + if (c >= 0 && c < end) { + auto *child = self->children[c]; + if (child->entryPresent) { + if (!(child->entry.rangeVersion <= readVersion)) { + return false; + }; + } + begin = c; + } else { + return true; + } + // [begin, end) is now the half-open interval of children we're interested + // in. + assert(begin < end); + } + const int firstPage = begin >> Node256::kMaxOfMaxShift; const int lastPage = (end - 1) >> Node256::kMaxOfMaxShift; // Check the only page if there's only one