Avoid dispatching on node type twice in nextPhysical

This commit is contained in:
2024-08-01 10:46:08 -07:00
parent 4cdf6deb50
commit 4b3df0a426

View File

@@ -844,28 +844,41 @@ template <class NodeT> int getNodeIndex(NodeT *self, uint8_t index) {
#endif
}
// Precondition - an entry for index must exist in the node
Node *&getChildExists(Node3 *self, uint8_t index) {
return self->children[getNodeIndex(self, index)];
}
// Precondition - an entry for index must exist in the node
Node *&getChildExists(Node16 *self, uint8_t index) {
return self->children[getNodeIndex(self, index)];
}
// Precondition - an entry for index must exist in the node
Node *&getChildExists(Node48 *self, uint8_t index) {
assert(self->bitSet.test(index));
return self->children[self->index[index]];
}
// Precondition - an entry for index must exist in the node
Node *&getChildExists(Node256 *self, uint8_t index) {
assert(self->bitSet.test(index));
return self->children[index];
}
// Precondition - an entry for index must exist in the node
Node *&getChildExists(Node *self, uint8_t index) {
switch (self->getType()) {
case Type_Node0: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
case Type_Node3: {
auto *self3 = static_cast<Node3 *>(self);
return self3->children[getNodeIndex(self3, index)];
return getChildExists(static_cast<Node3 *>(self), index);
}
case Type_Node16: {
auto *self16 = static_cast<Node16 *>(self);
return self16->children[getNodeIndex(self16, index)];
return getChildExists(static_cast<Node16 *>(self), index);
}
case Type_Node48: {
auto *self48 = static_cast<Node48 *>(self);
assert(self48->bitSet.test(index));
return self48->children[self48->index[index]];
return getChildExists(static_cast<Node48 *>(self), index);
}
case Type_Node256: {
auto *self256 = static_cast<Node256 *>(self);
assert(self256->bitSet.test(index));
return self256->children[index];
return getChildExists(static_cast<Node256 *>(self), index);
}
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
@@ -979,24 +992,47 @@ template <class NodeT> int getChildGeqSimd(NodeT *self, int child) {
#endif
}
int getChildGeq(Node *self, int child) {
int getChildGeq(Node0 *, int child) {
if (child > 255) {
return -1;
}
return -1;
}
int getChildGeq(Node3 *self, int child) {
if (child > 255) {
return -1;
}
return getChildGeqSimd(self, child);
}
int getChildGeq(Node16 *self, int child) {
if (child > 255) {
return -1;
}
return getChildGeqSimd(self, child);
}
int getChildGeq(Node48 *self, int child) {
if (child > 255) {
return -1;
}
return self->bitSet.firstSetGeq(child);
}
int getChildGeq(Node256 *self, int child) {
static_assert(offsetof(Node48, bitSet) == offsetof(Node256, bitSet));
return getChildGeq(reinterpret_cast<Node48 *>(self), child);
}
int getChildGeq(Node *self, int child) {
switch (self->getType()) {
case Type_Node0:
return -1;
return getChildGeq(static_cast<Node0 *>(self), child);
case Type_Node3:
return getChildGeqSimd(static_cast<Node3 *>(self), child);
return getChildGeq(static_cast<Node3 *>(self), child);
case Type_Node16:
return getChildGeqSimd(static_cast<Node16 *>(self), child);
return getChildGeq(static_cast<Node16 *>(self), child);
case Type_Node48:
[[fallthrough]];
case Type_Node256: {
static_assert(offsetof(Node48, bitSet) == offsetof(Node256, bitSet));
auto *self48 = static_cast<Node48 *>(self);
return self48->bitSet.firstSetGeq(child);
}
return getChildGeq(static_cast<Node48 *>(self), child);
case Type_Node256:
return getChildGeq(static_cast<Node256 *>(self), child);
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
@@ -1201,9 +1237,44 @@ Node *&getOrCreateChild(Node *&self, uint8_t index, WriteContext *tls) {
Node *nextPhysical(Node *node) {
int index = -1;
for (;;) {
auto nextChild = getChildGeq(node, index + 1);
if (nextChild >= 0) {
return getChildExists(node, nextChild);
switch (node->getType()) {
case Type_Node0: {
auto *n = static_cast<Node0 *>(node);
auto nextChild = getChildGeq(n, index + 1);
if (nextChild >= 0) {
return getChildExists(n, nextChild);
}
} break;
case Type_Node3: {
auto *n = static_cast<Node3 *>(node);
auto nextChild = getChildGeq(n, index + 1);
if (nextChild >= 0) {
return getChildExists(n, nextChild);
}
} break;
case Type_Node16: {
auto *n = static_cast<Node16 *>(node);
auto nextChild = getChildGeq(n, index + 1);
if (nextChild >= 0) {
return getChildExists(n, nextChild);
}
} break;
case Type_Node48: {
auto *n = static_cast<Node48 *>(node);
auto nextChild = getChildGeq(n, index + 1);
if (nextChild >= 0) {
return getChildExists(n, nextChild);
}
} break;
case Type_Node256: {
auto *n = static_cast<Node256 *>(node);
auto nextChild = getChildGeq(n, index + 1);
if (nextChild >= 0) {
return getChildExists(n, nextChild);
}
} break;
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
index = node->parentsIndex;
node = node->parent;