DAW JSON Link
Loading...
Searching...
No Matches
daw_json_simd_avx2.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
11#include <daw/daw_cpp_feature_check.h>
12
13#define DAW_JSON_HAS_AVX2_SIMD 1
14
15#include <immintrin.h>
16
17#include <cstddef>
18#include <cstdint>
19#include <cstring>
20#include <type_traits>
21
22namespace daw::simd_impl::avx2 {
23 class mask {
24 __m256i m_value;
25
26 public:
27 explicit mask( __m256i value ) noexcept
28 : m_value( value ) {}
29
30 [[nodiscard]] std::uint64_t to_ullong( ) const noexcept {
31 return static_cast<std::uint32_t>( _mm256_movemask_epi8( m_value ) );
32 }
33
34 [[nodiscard]] friend mask operator|( mask lhs, mask rhs ) noexcept {
35 return mask( _mm256_or_si256( lhs.m_value, rhs.m_value ) );
36 }
37
38 [[nodiscard]] friend mask operator&( mask lhs, mask rhs ) noexcept {
39 return mask( _mm256_and_si256( lhs.m_value, rhs.m_value ) );
40 }
41
42 [[nodiscard]] friend mask operator!( mask value ) noexcept {
43 return mask( _mm256_xor_si256(
44 value.m_value, _mm256_set1_epi8( static_cast<char>( 0xFF ) ) ) );
45 }
46 };
47
48 template<typename T, std::size_t /*MaximumSize*/ = 32U>
49 class vec {
50 static_assert( sizeof( T ) == 1,
51 "The AVX2 JSON SIMD implementation supports byte types" );
52 static_assert(
53 std::is_integral_v<T>,
54 "The AVX2 JSON SIMD implementation requires an integral type" );
55
56 __m256i m_value;
57
58 template<typename U, std::size_t MaximumSize>
59 friend class vec;
60
61 template<typename Simd, typename Range, typename Flag>
62 friend Simd unchecked_load( Range values, Flag );
63
64 template<typename Simd, typename Range, typename Flag>
65 friend Simd partial_load( Range values, Flag );
66
67 explicit vec( __m256i value ) noexcept
68 : m_value( value ) {}
69
70 [[nodiscard]] static __m256i order_bytes( __m256i value ) noexcept {
71 return _mm256_xor_si256(
72 value, _mm256_set1_epi8( static_cast<char>( 0x80 ) ) );
73 }
74
75 public:
76 using value_type = T;
77 using mask_type = mask;
78
79 explicit vec( value_type value ) noexcept
80 : m_value( _mm256_set1_epi8( static_cast<char>( value ) ) ) {}
81
82 [[nodiscard]] static constexpr std::size_t size( ) noexcept {
83 return 32;
84 }
85
86 [[nodiscard]] friend mask operator==( vec lhs, vec rhs ) noexcept {
87 return mask( _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) );
88 }
89
90 [[nodiscard]] friend mask operator>=( vec lhs, vec rhs ) noexcept {
91 auto const ordered_lhs = order_bytes( lhs.m_value );
92 auto const ordered_rhs = order_bytes( rhs.m_value );
93 return mask( _mm256_or_si256(
94 _mm256_cmpgt_epi8( ordered_lhs, ordered_rhs ),
95 _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
96 }
97
98 [[nodiscard]] friend mask operator<=( vec lhs, vec rhs ) noexcept {
99 auto const ordered_lhs = order_bytes( lhs.m_value );
100 auto const ordered_rhs = order_bytes( rhs.m_value );
101 return mask( _mm256_or_si256(
102 _mm256_cmpgt_epi8( ordered_rhs, ordered_lhs ),
103 _mm256_cmpeq_epi8( lhs.m_value, rhs.m_value ) ) );
104 }
105 };
106
107 struct flag_default_t {};
108 struct flag_convert_t {};
109
110 inline constexpr flag_default_t flag_default = { };
111 inline constexpr flag_convert_t flag_convert = { };
112
113 template<typename Simd, typename Range, typename Flag = flag_default_t>
114 [[nodiscard]] inline Simd unchecked_load( Range values,
115 Flag = flag_default ) {
116 static_assert( Simd::size( ) == 32 );
117 return Simd( _mm256_loadu_si256(
118 reinterpret_cast<__m256i const *>( values.data( ) ) ) );
119 }
120
121 template<typename Simd, typename Range, typename Flag = flag_default_t>
122 [[nodiscard]] inline Simd partial_load( Range values, Flag = flag_default ) {
123 static_assert( Simd::size( ) == 32 );
124 auto result = _mm256_setzero_si256( );
125 std::memcpy( &result, values.data( ), values.size( ) );
126 return Simd( result );
127 }
128} // namespace daw::simd_impl::avx2