diff --git a/art_internal_impl.hpp b/art_internal_impl.hpp index 2617cd16..6417fca2 100644 --- a/art_internal_impl.hpp +++ b/art_internal_impl.hpp @@ -1507,28 +1507,27 @@ class basic_inode_4 : public basic_inode_4_parent { i, static_cast *>(&children[i])); #else // #ifdef UNODB_DETAIL_X86_64 // Bit twiddling: - // contains_byte: __builtin_ffs: for key index: - // 0x80000000 0x20 3 - // 0x800000 0x18 2 - // 0x808000 0x10 1 - // 0x80 0x8 0 - // 0x0 0x0 not found + // contains_byte: std::countr_zero: for key index: + // 0x80000000 0x1F 3 + // 0x800000 0x17 2 + // 0x8000 0x0F 1 + // 0x80 0x07 0 + // 0x0 UB (check!) not found + const auto match = contains_byte(keys.integer, key_byte); + if (match == 0) return parent_class::child_not_found; + const auto result = static_cast( - // __builtin_ffs takes signed argument: - // NOLINTNEXTLINE(hicpp-signed-bitwise) - __builtin_ffs(static_cast( - contains_byte(keys.integer, key_byte))) >> - 3); - - // The second condition could be replaced with masking, but this seems to - // result in a benchmark regression - if ((result == 0) || (result > this->children_count.load())) + std::countr_zero(match) >> 3U); + + // The condition could be replaced with masking, but this seems to result + // in a benchmark regression + if (result >= this->children_count.load()) return parent_class::child_not_found; - return std::make_pair(result - 1, - static_cast *>( - &children[result - 1])); + return std::make_pair( + result, + static_cast *>(&children[result])); #endif // #ifdef UNODB_DETAIL_X86_64 }