11#include <daw/daw_cpp_feature_check.h>
12#include <daw/daw_is_constant_evaluated.h>
13#include <daw/daw_span.h>
22#if defined( __BMI2__ ) and ( defined( __x86_64__ ) or defined( _M_X64 ) )
26#if __has_include( <simd> )
30#if defined( __cpp_lib_simd ) or defined( __glibcxx_simd )
32#define DAW_JSON_HAS_STD_SIMD 1
36#if ( defined( __ARM_NEON ) or defined( __ARM_NEON__ ) )
40#if defined( __AVX2__ ) or defined( _M_AVX2 )
42#elif defined( __SSE4_2__ ) or defined( __AVX__ ) or defined( _M_X64 ) or \
43 ( defined( _M_IX86_FP ) and _M_IX86_FP >= 2 )
47#if defined( DAW_JSON_HAS_STD_SIMD )
49#define DAW_JSON_HAS_SIMD 1
50#define DAW_JSON_SIMD_CONSTEXPR constexpr
52#if defined( DAW_JSON_SIMD_MAX_256 )
58 using namespace std::simd;
61 inline constexpr int max_256_size_v =
62 static_cast<int>( std::simd::vec<T>::size( ) ) <
63 static_cast<int>( 32 /
sizeof( T ) )
64 ?
static_cast<int>( std::simd::vec<T>::size( ) )
65 : static_cast<int>( 32 / sizeof( T ) );
67 template<
typename T,
int N = max_256_size_v<T>>
68 using vec = std::simd::vec<T, N>;
72 namespace simd = std::simd;
76#elif defined( DAW_JSON_HAS_NEON_SIMD )
78#define DAW_JSON_HAS_SIMD 1
79#define DAW_JSON_SIMD_CONSTEXPR inline
82 namespace simd = simd_impl::neon;
85#elif defined( DAW_JSON_HAS_AVX2_SIMD )
87#define DAW_JSON_HAS_SIMD 1
88#define DAW_JSON_SIMD_CONSTEXPR inline
91 namespace simd = simd_impl::avx2;
94#elif defined( DAW_JSON_HAS_SSE42_SIMD )
96#define DAW_JSON_HAS_SIMD 1
97#define DAW_JSON_SIMD_CONSTEXPR inline
100 namespace simd = simd_impl::sse42;
105#if defined( DAW_JSON_HAS_SIMD )
107namespace daw::simd_impl {
113 [[nodiscard]]
constexpr std::uint64_t
114 compress_bits( std::uint64_t values, std::uint64_t selection )
noexcept {
115#if defined( __BMI2__ ) and ( defined( __x86_64__ ) or defined( _M_X64 ) )
116 if( not DAW_IS_CONSTANT_EVALUATED_COMPAT( ) ) {
117 return _pext_u64( values, selection );
120 auto result = std::uint64_t{ 0 };
121 auto output_bit = std::uint64_t{ 1 };
122 while( selection != 0 ) {
123 auto const selected_bit = selection & ( ~selection + 1U );
124 if( ( values & selected_bit ) != 0 ) {
125 result |= output_bit;
127 selection &= selection - 1U;
139 template<
typename Mask,
140 std::enable_if_t<not std::is_integral_v<Mask>,
int> = 0>
141 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR std::uint64_t
142 compress_bits( Mask values, std::uint64_t selection )
noexcept {
143 return compress_bits( values.to_ullong( ), selection );
146 template<
typename Mask,
147 std::enable_if_t<not std::is_integral_v<Mask>,
int> = 0>
148 [[nodiscard]] DAW_JSON_SIMD_CONSTEXPR std::uint64_t
149 compress_bits( Mask values, Mask selection )
noexcept {
150 return compress_bits( values.to_ullong( ), selection.to_ullong( ) );
159#if defined( __SANITIZE_ADDRESS__ ) or defined( __SANITIZE_HWADDRESS__ )
160#define DAW_JSON_SIMD_SAFE_ALIGNED_LOADS 1
161#elif defined( __has_feature )
162#if __has_feature( address_sanitizer ) or \
163 __has_feature( hwaddress_sanitizer ) or __has_feature( memory_sanitizer )
164#define DAW_JSON_SIMD_SAFE_ALIGNED_LOADS 1
170 namespace json_details {
174 template<
typename Simd>
175 [[nodiscard]]
inline Simd
176 load_aligned_block( std::uintptr_t block_addr,
177 [[maybe_unused]] std::uintptr_t first_addr,
178 [[maybe_unused]] std::uintptr_t last_addr ) {
179 using value_t =
typename Simd::value_type;
180 static_assert(
sizeof( value_t ) == 1 );
181 constexpr std::size_t block_size = Simd::size( );
182#if defined( DAW_JSON_SIMD_SAFE_ALIGNED_LOADS )
183 alignas( block_size ) value_t buff[block_size] = { };
184 auto const lo = block_addr < first_addr ? first_addr : block_addr;
185 auto const hi = last_addr < block_addr + block_size
187 : block_addr + block_size;
188 std::memcpy( buff + ( lo - block_addr ),
189 reinterpret_cast<void const *
>( lo ), hi - lo );
190 value_t
const *
const ptr = buff;
192 auto const *
const ptr =
reinterpret_cast<value_t
const *
>( block_addr );
194 return daw::simd::unchecked_load<Simd>( daw::span( ptr, block_size ),
195 daw::simd::flag_aligned );
201#if defined( DAW_JSON_SIMD_SAFE_ALIGNED_LOADS )
202#undef DAW_JSON_SIMD_SAFE_ALIGNED_LOADS
207 namespace json_details {
209 char const *first =
nullptr;
210 char const *last =
nullptr;
211 char const *decimal_point =
nullptr;
212 char const *exponent_marker =
nullptr;
215 struct pending_number_span {
216 char const *first =
nullptr;
217 char const *decimal_point =
nullptr;
218 char const *exponent_marker =
nullptr;
221 struct integer_span {
222 char const *first =
nullptr;
223 char const *last =
nullptr;
226 struct pending_integer_span {
227 char const *first =
nullptr;
@ simd
testing Allow code paths that use SIMD intrinsics
string_writer grows its string with resize_and_overwrite, leaving the new bytes uninitialized,...
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.