summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2025-02-13 15:28:09 -0500
committerTavian Barnes <tavianator@tavianator.com>2025-02-13 15:28:09 -0500
commit3515a4b00013d71863eb4d5769c640f12bec6ebe (patch)
treefe58e040369855f75dbc44255e7907f8da3a5aa1
parentbaa45ab5393b780939de6721a88962fd2293b121 (diff)
downloadbfs-3515a4b00013d71863eb4d5769c640f12bec6ebe.tar.xz
trie: Use load8_beu*() for trie_mismatch()HEADmain
-rw-r--r--src/trie.c52
1 files changed, 23 insertions, 29 deletions
diff --git a/src/trie.c b/src/trie.c
index 68e3948..c4bf4ba 100644
--- a/src/trie.c
+++ b/src/trie.c
@@ -391,12 +391,6 @@ static void trie_node_free(struct trie *trie, struct trie_node *node, size_t siz
varena_free(&trie->nodes, node, size);
}
-#if ENDIAN_NATIVE == ENDIAN_LITTLE
-# define TRIE_BSWAP(n) bswap(n)
-#elif ENDIAN_NATIVE == ENDIAN_BIG
-# define TRIE_BSWAP(n) (n)
-#endif
-
/** Find the offset of the first nibble that differs between two keys. */
static size_t trie_mismatch(const struct trie_leaf *rep, const void *key, size_t length) {
if (!rep) {
@@ -410,32 +404,32 @@ static size_t trie_mismatch(const struct trie_leaf *rep, const void *key, size_t
const char *rep_bytes = rep->key;
const char *key_bytes = key;
- size_t i = 0;
- for (size_t chunk = sizeof(chunk); i + chunk <= length; i += chunk) {
- size_t rep_chunk, key_chunk;
- memcpy(&rep_chunk, rep_bytes + i, sizeof(rep_chunk));
- memcpy(&key_chunk, key_bytes + i, sizeof(key_chunk));
-
- if (rep_chunk != key_chunk) {
-#ifdef TRIE_BSWAP
- size_t diff = TRIE_BSWAP(rep_chunk ^ key_chunk);
- i *= 2;
- i += leading_zeros(diff) / 4;
- return i;
-#else
- break;
-#endif
- }
- }
+ size_t ret = 0, i = 0;
- for (; i < length; ++i) {
- unsigned char diff = rep_bytes[i] ^ key_bytes[i];
- if (diff) {
- return 2 * i + !(diff >> 4);
- }
+#define CHUNK(n) CHUNK_(uint##n##_t, load8_beu##n)
+#define CHUNK_(type, load8) \
+ while (length - i >= sizeof(type)) { \
+ type rep_chunk = load8(rep_bytes + i); \
+ type key_chunk = load8(key_bytes + i); \
+ type diff = rep_chunk ^ key_chunk; \
+ ret += leading_zeros(diff) / 4; \
+ if (diff) { \
+ return ret; \
+ } \
+ i += sizeof(type); \
}
- return 2 * i;
+#if SIZE_WIDTH >= 64
+ CHUNK(64);
+#endif
+ CHUNK(32);
+ CHUNK(16);
+ CHUNK(8);
+
+#undef CHUNK_
+#undef CHUNK
+
+ return ret;
}
/**