Move SIMD operations on potentially-indeterminate Node16::index bytes into file-level assembly, where loading and operating on indeterminate values is well-defined (unlike C++). Restructure scalar fallback loops to iterate [0, numChildren) instead of [0, kMaxNodes). Fix TrivialSpan construction from indeterminate pointers in check::Job::init and insertPointWritesOrSorted to only construct when end.len > 0. Add MSan toolchain to the debug CI build to catch these issues going forward.
25 lines
903 B
C++
25 lines
903 B
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
#if defined(__x86_64__) && !defined(USE_SIMD_FALLBACK)
|
|
|
|
// SIMD operations on potentially-indeterminate Node16::index[16] bytes.
|
|
// Implemented in file-level assembly (simd_x86_64.S) because loading and
|
|
// operating on indeterminate values is UB in C++ but well-defined in
|
|
// assembly. The caller must mask the returned bitfield to
|
|
// [0, numChildren) before using it.
|
|
//
|
|
// Each function returns a 16-bit bitmask in the low 16 bits of a uint32_t
|
|
// (upper 16 bits are zero). Bit i is set iff the condition holds at index i.
|
|
|
|
extern "C" {
|
|
// Returns bit i set iff idx[i] == key
|
|
uint32_t find_eq_16(const uint8_t idx[16], uint8_t key);
|
|
// Returns bit i set iff idx[i] >= child
|
|
uint32_t find_ge_16(const uint8_t idx[16], uint8_t child);
|
|
// Returns bit i set iff begin <= idx[i] < end
|
|
uint32_t mask_in_range_16(const uint8_t idx[16], uint8_t begin, uint8_t end);
|
|
}
|
|
|
|
#endif |