Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make undefined sanitizer work on Linux #7082

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 0 additions & 86 deletions src/realm/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,92 +550,6 @@ void Array::do_ensure_minimum_width(int_fast64_t value)
}
}

namespace {

template <size_t width>
inline int64_t lower_bits()
{
if (width == 1)
return 0xFFFFFFFFFFFFFFFFULL;
else if (width == 2)
return 0x5555555555555555ULL;
else if (width == 4)
return 0x1111111111111111ULL;
else if (width == 8)
return 0x0101010101010101ULL;
else if (width == 16)
return 0x0001000100010001ULL;
else if (width == 32)
return 0x0000000100000001ULL;
else if (width == 64)
return 0x0000000000000001ULL;
else {
REALM_ASSERT_DEBUG(false);
return int64_t(-1);
}
}

// Return true if 'value' has an element (of bit-width 'width') which is 0
template <size_t width>
inline bool has_zero_element(uint64_t value)
{
uint64_t hasZeroByte;
uint64_t lower = lower_bits<width>();
uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL));
hasZeroByte = (value - lower) & ~value & upper;
return hasZeroByte != 0;
}


// Finds zero element of bit width 'width'
template <bool eq, size_t width>
size_t find_zero(uint64_t v)
{
size_t start = 0;
uint64_t hasZeroByte;

// Bisection optimization, speeds up small bitwidths with high match frequency. More partions than 2 do NOT pay
// off because the work done by test_zero() is wasted for the cases where the value exists in first half, but
// useful if it exists in last half. Sweet spot turns out to be the widths and partitions below.
if (width <= 8) {
hasZeroByte = has_zero_element<width>(v | 0xffffffff00000000ULL);
if (eq ? !hasZeroByte : (v & 0x00000000ffffffffULL) == 0) {
// 00?? -> increasing
start += 64 / no0(width) / 2;
if (width <= 4) {
hasZeroByte = has_zero_element<width>(v | 0xffff000000000000ULL);
if (eq ? !hasZeroByte : (v & 0x0000ffffffffffffULL) == 0) {
// 000?
start += 64 / no0(width) / 4;
}
}
}
else {
if (width <= 4) {
// ??00
hasZeroByte = has_zero_element<width>(v | 0xffffffffffff0000ULL);
if (eq ? !hasZeroByte : (v & 0x000000000000ffffULL) == 0) {
// 0?00
start += 64 / no0(width) / 4;
}
}
}
}

uint64_t mask =
(width == 64
? ~0ULL
: ((1ULL << (width == 64 ? 0 : width)) - 1ULL)); // Warning free way of computing (1ULL << width) - 1
while (eq == (((v >> (width * start)) & mask) != 0)) {
start++;
}

return start;
}

} // namespace


int64_t Array::sum(size_t start, size_t end) const
{
REALM_TEMPEX(return sum, m_width, (start, end));
Expand Down
58 changes: 28 additions & 30 deletions src/realm/array_with_find.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,36 @@ Searching: The main finding function is:

namespace realm {

namespace {
template <class T>
inline T no0(T v)
inline constexpr T no0(T v)
{
return v == 0 ? 1 : v;
}

template <size_t width>
inline constexpr uint64_t lower_bits()
{
if (width == 1)
return 0xFFFFFFFFFFFFFFFFULL;
else if (width == 2)
return 0x5555555555555555ULL;
else if (width == 4)
return 0x1111111111111111ULL;
else if (width == 8)
return 0x0101010101010101ULL;
else if (width == 16)
return 0x0001000100010001ULL;
else if (width == 32)
return 0x0000000100000001ULL;
else if (width == 64)
return 0x0000000000000001ULL;
else {
return uint64_t(-1);
}
}
} // namespace

class ArrayWithFind {
public:
ArrayWithFind(const Array& array) noexcept
Expand Down Expand Up @@ -133,9 +157,6 @@ class ArrayWithFind {
int64_t
find_gtlt_magic(int64_t v) const; // Compute magic constant needed for searching for value 'v' using bit hacks

template <size_t width>
inline int64_t lower_bits() const; // Return chunk with lower bit set in each element

size_t first_set_bit(uint32_t v) const;
size_t first_set_bit64(int64_t v) const;

Expand Down Expand Up @@ -419,36 +440,13 @@ bool ArrayWithFind::find_optimized(int64_t value, size_t start, size_t end, size
#endif
}

template <size_t width>
inline int64_t ArrayWithFind::lower_bits() const
{
if (width == 1)
return 0xFFFFFFFFFFFFFFFFULL;
else if (width == 2)
return 0x5555555555555555ULL;
else if (width == 4)
return 0x1111111111111111ULL;
else if (width == 8)
return 0x0101010101010101ULL;
else if (width == 16)
return 0x0001000100010001ULL;
else if (width == 32)
return 0x0000000100000001ULL;
else if (width == 64)
return 0x0000000000000001ULL;
else {
REALM_ASSERT_DEBUG(false);
return int64_t(-1);
}
}

// Tests if any chunk in 'value' is 0
template <size_t width>
inline bool ArrayWithFind::test_zero(uint64_t value) const
{
uint64_t hasZeroByte;
uint64_t lower = lower_bits<width>();
uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL));
constexpr uint64_t lower = lower_bits<width>();
constexpr uint64_t upper = lower_bits<width>() * 1ULL << (width == 0 ? 0 : (width - 1ULL));
hasZeroByte = (value - lower) & ~value & upper;
return hasZeroByte != 0;
}
Expand Down Expand Up @@ -804,7 +802,7 @@ REALM_FORCEINLINE bool ArrayWithFind::find_sse_intern(__m128i* action_data, __m1
size_t s = i * sizeof(__m128i) * 8 / no0(width);

while (resmask != 0) {
uint64_t upper = lower_bits<width / 8>() << (no0(width / 8) - 1);
constexpr uint64_t upper = lower_bits<width / 8>() << (no0(width / 8) - 1);
uint64_t pattern =
resmask &
upper; // fixme, bits at wrong offsets. Only OK because we only use them in 'count' aggregate
Expand Down
1 change: 0 additions & 1 deletion src/realm/query_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ TConditionValue: Type of values in condition column. That is, int64_t, float,
#include <realm/array_key.hpp>
#include <realm/array_string.hpp>
#include <realm/array_binary.hpp>
#include <realm/array_integer_tpl.hpp>
#include <realm/array_timestamp.hpp>
#include <realm/array_decimal128.hpp>
#include <realm/array_fixed_bytes.hpp>
Expand Down