Skip to content

Commit

Permalink
Make undefined sanitizer work on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
jedelbo committed Oct 27, 2023
1 parent d4c8576 commit 4200f2b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 117 deletions.
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

0 comments on commit 4200f2b

Please sign in to comment.