• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Auto-generated file. Do not edit!
2 //   Template: src/f32-velu/avx-rr2-lut16-p3.c.in
3 //   Generator: tools/xngen
4 //
5 // Copyright 2020 Google LLC
6 //
7 // This source code is licensed under the BSD-style license found in the
8 // LICENSE file in the root directory of this source tree.
9 
10 #include <assert.h>
11 
12 #include <immintrin.h>
13 
14 #include <xnnpack/common.h>
15 #include <xnnpack/intrinsics-polyfill.h>
16 #include <xnnpack/vunary.h>
17 
18 
19 extern XNN_INTERNAL const int xnn_table_exp2minus_k_over_16[16];
20 
21 static const int32_t mask_table[14] = {-1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0};
22 
xnn_f32_velu_ukernel__avx_rr2_lut16_p3_x32(size_t n,const float * x,float * y,const union xnn_f32_elu_params params[restrict XNN_MIN_ELEMENTS (1)])23 void xnn_f32_velu_ukernel__avx_rr2_lut16_p3_x32(
24     size_t n,
25     const float* x,
26     float* y,
27     const union xnn_f32_elu_params params[restrict XNN_MIN_ELEMENTS(1)])
28 {
29   assert(n % sizeof(float) == 0);
30 
31   const __m256 vprescale = _mm256_broadcast_ps((const __m128*) params->sse.prescale);
32   const __m256 valpha = _mm256_broadcast_ps((const __m128*) params->sse.alpha);
33   const __m256 vbeta = _mm256_broadcast_ps((const __m128*) params->sse.beta);
34 
35   const __m256 vsat_cutoff = _mm256_set1_ps(-0x1.154246p+4f);
36   const __m256 vmagic_bias = _mm256_set1_ps(0x1.800000p19f);
37   const __m256 vlog2e = _mm256_set1_ps(0x1.715476p+0f);
38   const __m256 vindex_mask = _mm256_castsi256_ps(_mm256_set1_epi32(0xF));
39   const __m256 vminus_ln2_hi = _mm256_set1_ps(-0x1.62E400p-1f);
40   const __m256 vminus_ln2_lo = _mm256_set1_ps(-0x1.7F7D1Cp-20f);
41   const __m256 vc3 = _mm256_set1_ps(0x1.55561Cp-3f);
42   const __m256 vc2 = _mm256_set1_ps(0x1.0001ECp-1f);
43   const __m256 vone = _mm256_set1_ps(1.0f);
44 
45   for (; n >= 32 * sizeof(float); n -= 32 * sizeof(float)) {
46     __m256 vx0 = _mm256_loadu_ps(x);
47     __m256 vx1 = _mm256_loadu_ps(x + 8);
48     __m256 vx2 = _mm256_loadu_ps(x + 16);
49     __m256 vx3 = _mm256_loadu_ps(x + 24);
50     x += 32;
51 
52     const __m256 vz0 = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx0, vprescale));
53     const __m256 vz1 = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx1, vprescale));
54     const __m256 vz2 = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx2, vprescale));
55     const __m256 vz3 = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx3, vprescale));
56 
57     __m256 vn0 = _mm256_add_ps(_mm256_mul_ps(vz0, vlog2e), vmagic_bias);
58     __m256 vn1 = _mm256_add_ps(_mm256_mul_ps(vz1, vlog2e), vmagic_bias);
59     __m256 vn2 = _mm256_add_ps(_mm256_mul_ps(vz2, vlog2e), vmagic_bias);
60     __m256 vn3 = _mm256_add_ps(_mm256_mul_ps(vz3, vlog2e), vmagic_bias);
61 
62     const __m256 vidx0 = _mm256_and_ps(vn0, vindex_mask);
63 
64     const __m128i vidx0_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx0)), 2);
65     const __m128i vidx0_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx0, 1)), 2);
66     #if XNN_ARCH_X86_64
67       const uint64_t vidx0_ll = (uint64_t) _mm_cvtsi128_si64(vidx0_lo);
68       const uint64_t vidx0_lh = (uint64_t) _mm_extract_epi64(vidx0_lo, 1);
69       const uint64_t vidx0_hl = (uint64_t) _mm_cvtsi128_si64(vidx0_hi);
70       const uint64_t vidx0_hh = (uint64_t) _mm_extract_epi64(vidx0_hi, 1);
71       __m128i vl0_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx0_ll));
72       __m128i vl0_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx0_lh));
73       __m128i vl0_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx0_hl));
74       __m128i vl0_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx0_hh));
75       vl0_ll = _mm_insert_epi32(vl0_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx0_ll >> 32))), 1);
76       vl0_lh = _mm_insert_epi32(vl0_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx0_lh >> 32))), 1);
77       vl0_hl = _mm_insert_epi32(vl0_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx0_hl >> 32))), 1);
78       vl0_hh = _mm_insert_epi32(vl0_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx0_hh >> 32))), 1);
79     #else
80       __m128i vl0_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx0_lo)));
81       __m128i vl0_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_lo, 2)));
82       __m128i vl0_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx0_hi)));
83       __m128i vl0_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_hi, 2)));
84       vl0_ll = _mm_insert_epi32(vl0_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_lo, 1))), 1);
85       vl0_lh = _mm_insert_epi32(vl0_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_lo, 3))), 1);
86       vl0_hl = _mm_insert_epi32(vl0_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_hi, 1))), 1);
87       vl0_hh = _mm_insert_epi32(vl0_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx0_hi, 3))), 1);
88     #endif
89     const __m128i vl0_lo = _mm_unpacklo_epi64(vl0_ll, vl0_lh);
90     const __m128i vl0_hi = _mm_unpacklo_epi64(vl0_hl, vl0_hh);
91     const __m256 vidx1 = _mm256_and_ps(vn1, vindex_mask);
92 
93     const __m128i vidx1_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx1)), 2);
94     const __m128i vidx1_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx1, 1)), 2);
95     #if XNN_ARCH_X86_64
96       const uint64_t vidx1_ll = (uint64_t) _mm_cvtsi128_si64(vidx1_lo);
97       const uint64_t vidx1_lh = (uint64_t) _mm_extract_epi64(vidx1_lo, 1);
98       const uint64_t vidx1_hl = (uint64_t) _mm_cvtsi128_si64(vidx1_hi);
99       const uint64_t vidx1_hh = (uint64_t) _mm_extract_epi64(vidx1_hi, 1);
100       __m128i vl1_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx1_ll));
101       __m128i vl1_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx1_lh));
102       __m128i vl1_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx1_hl));
103       __m128i vl1_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx1_hh));
104       vl1_ll = _mm_insert_epi32(vl1_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx1_ll >> 32))), 1);
105       vl1_lh = _mm_insert_epi32(vl1_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx1_lh >> 32))), 1);
106       vl1_hl = _mm_insert_epi32(vl1_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx1_hl >> 32))), 1);
107       vl1_hh = _mm_insert_epi32(vl1_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx1_hh >> 32))), 1);
108     #else
109       __m128i vl1_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx1_lo)));
110       __m128i vl1_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_lo, 2)));
111       __m128i vl1_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx1_hi)));
112       __m128i vl1_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_hi, 2)));
113       vl1_ll = _mm_insert_epi32(vl1_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_lo, 1))), 1);
114       vl1_lh = _mm_insert_epi32(vl1_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_lo, 3))), 1);
115       vl1_hl = _mm_insert_epi32(vl1_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_hi, 1))), 1);
116       vl1_hh = _mm_insert_epi32(vl1_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx1_hi, 3))), 1);
117     #endif
118     const __m128i vl1_lo = _mm_unpacklo_epi64(vl1_ll, vl1_lh);
119     const __m128i vl1_hi = _mm_unpacklo_epi64(vl1_hl, vl1_hh);
120     const __m256 vidx2 = _mm256_and_ps(vn2, vindex_mask);
121 
122     const __m128i vidx2_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx2)), 2);
123     const __m128i vidx2_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx2, 1)), 2);
124     #if XNN_ARCH_X86_64
125       const uint64_t vidx2_ll = (uint64_t) _mm_cvtsi128_si64(vidx2_lo);
126       const uint64_t vidx2_lh = (uint64_t) _mm_extract_epi64(vidx2_lo, 1);
127       const uint64_t vidx2_hl = (uint64_t) _mm_cvtsi128_si64(vidx2_hi);
128       const uint64_t vidx2_hh = (uint64_t) _mm_extract_epi64(vidx2_hi, 1);
129       __m128i vl2_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx2_ll));
130       __m128i vl2_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx2_lh));
131       __m128i vl2_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx2_hl));
132       __m128i vl2_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx2_hh));
133       vl2_ll = _mm_insert_epi32(vl2_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx2_ll >> 32))), 1);
134       vl2_lh = _mm_insert_epi32(vl2_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx2_lh >> 32))), 1);
135       vl2_hl = _mm_insert_epi32(vl2_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx2_hl >> 32))), 1);
136       vl2_hh = _mm_insert_epi32(vl2_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx2_hh >> 32))), 1);
137     #else
138       __m128i vl2_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx2_lo)));
139       __m128i vl2_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_lo, 2)));
140       __m128i vl2_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx2_hi)));
141       __m128i vl2_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_hi, 2)));
142       vl2_ll = _mm_insert_epi32(vl2_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_lo, 1))), 1);
143       vl2_lh = _mm_insert_epi32(vl2_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_lo, 3))), 1);
144       vl2_hl = _mm_insert_epi32(vl2_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_hi, 1))), 1);
145       vl2_hh = _mm_insert_epi32(vl2_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx2_hi, 3))), 1);
146     #endif
147     const __m128i vl2_lo = _mm_unpacklo_epi64(vl2_ll, vl2_lh);
148     const __m128i vl2_hi = _mm_unpacklo_epi64(vl2_hl, vl2_hh);
149     const __m256 vidx3 = _mm256_and_ps(vn3, vindex_mask);
150 
151     const __m128i vidx3_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx3)), 2);
152     const __m128i vidx3_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx3, 1)), 2);
153     #if XNN_ARCH_X86_64
154       const uint64_t vidx3_ll = (uint64_t) _mm_cvtsi128_si64(vidx3_lo);
155       const uint64_t vidx3_lh = (uint64_t) _mm_extract_epi64(vidx3_lo, 1);
156       const uint64_t vidx3_hl = (uint64_t) _mm_cvtsi128_si64(vidx3_hi);
157       const uint64_t vidx3_hh = (uint64_t) _mm_extract_epi64(vidx3_hi, 1);
158       __m128i vl3_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx3_ll));
159       __m128i vl3_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx3_lh));
160       __m128i vl3_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx3_hl));
161       __m128i vl3_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx3_hh));
162       vl3_ll = _mm_insert_epi32(vl3_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx3_ll >> 32))), 1);
163       vl3_lh = _mm_insert_epi32(vl3_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx3_lh >> 32))), 1);
164       vl3_hl = _mm_insert_epi32(vl3_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx3_hl >> 32))), 1);
165       vl3_hh = _mm_insert_epi32(vl3_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx3_hh >> 32))), 1);
166     #else
167       __m128i vl3_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx3_lo)));
168       __m128i vl3_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_lo, 2)));
169       __m128i vl3_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx3_hi)));
170       __m128i vl3_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_hi, 2)));
171       vl3_ll = _mm_insert_epi32(vl3_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_lo, 1))), 1);
172       vl3_lh = _mm_insert_epi32(vl3_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_lo, 3))), 1);
173       vl3_hl = _mm_insert_epi32(vl3_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_hi, 1))), 1);
174       vl3_hh = _mm_insert_epi32(vl3_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx3_hi, 3))), 1);
175     #endif
176     const __m128i vl3_lo = _mm_unpacklo_epi64(vl3_ll, vl3_lh);
177     const __m128i vl3_hi = _mm_unpacklo_epi64(vl3_hl, vl3_hh);
178 
179     const __m128i ven0_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn0)), 19);
180     const __m128i ven0_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn0, 1)), 19);
181     vn0 = _mm256_sub_ps(vn0, vmagic_bias);
182     const __m128 vs0_lo = _mm_castsi128_ps(_mm_add_epi32(vl0_lo, ven0_lo));
183     const __m128 vs0_hi = _mm_castsi128_ps(_mm_add_epi32(vl0_hi, ven0_hi));
184     const __m128i ven1_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn1)), 19);
185     const __m128i ven1_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn1, 1)), 19);
186     vn1 = _mm256_sub_ps(vn1, vmagic_bias);
187     const __m128 vs1_lo = _mm_castsi128_ps(_mm_add_epi32(vl1_lo, ven1_lo));
188     const __m128 vs1_hi = _mm_castsi128_ps(_mm_add_epi32(vl1_hi, ven1_hi));
189     const __m128i ven2_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn2)), 19);
190     const __m128i ven2_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn2, 1)), 19);
191     vn2 = _mm256_sub_ps(vn2, vmagic_bias);
192     const __m128 vs2_lo = _mm_castsi128_ps(_mm_add_epi32(vl2_lo, ven2_lo));
193     const __m128 vs2_hi = _mm_castsi128_ps(_mm_add_epi32(vl2_hi, ven2_hi));
194     const __m128i ven3_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn3)), 19);
195     const __m128i ven3_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn3, 1)), 19);
196     vn3 = _mm256_sub_ps(vn3, vmagic_bias);
197     const __m128 vs3_lo = _mm_castsi128_ps(_mm_add_epi32(vl3_lo, ven3_lo));
198     const __m128 vs3_hi = _mm_castsi128_ps(_mm_add_epi32(vl3_hi, ven3_hi));
199 
200     __m256 vt0 = _mm256_add_ps(_mm256_mul_ps(vn0, vminus_ln2_hi), vz0);
201     __m256 vt1 = _mm256_add_ps(_mm256_mul_ps(vn1, vminus_ln2_hi), vz1);
202     __m256 vt2 = _mm256_add_ps(_mm256_mul_ps(vn2, vminus_ln2_hi), vz2);
203     __m256 vt3 = _mm256_add_ps(_mm256_mul_ps(vn3, vminus_ln2_hi), vz3);
204 
205     vt0 = _mm256_add_ps(_mm256_mul_ps(vn0, vminus_ln2_lo), vt0);
206     __m256 vs0 = _mm256_insertf128_ps(_mm256_castps128_ps256(vs0_lo), vs0_hi, 1);
207     vt1 = _mm256_add_ps(_mm256_mul_ps(vn1, vminus_ln2_lo), vt1);
208     __m256 vs1 = _mm256_insertf128_ps(_mm256_castps128_ps256(vs1_lo), vs1_hi, 1);
209     vt2 = _mm256_add_ps(_mm256_mul_ps(vn2, vminus_ln2_lo), vt2);
210     __m256 vs2 = _mm256_insertf128_ps(_mm256_castps128_ps256(vs2_lo), vs2_hi, 1);
211     vt3 = _mm256_add_ps(_mm256_mul_ps(vn3, vminus_ln2_lo), vt3);
212     __m256 vs3 = _mm256_insertf128_ps(_mm256_castps128_ps256(vs3_lo), vs3_hi, 1);
213 
214     __m256 vp0 = _mm256_add_ps(_mm256_mul_ps(vc3, vt0), vc2);
215     __m256 vp1 = _mm256_add_ps(_mm256_mul_ps(vc3, vt1), vc2);
216     __m256 vp2 = _mm256_add_ps(_mm256_mul_ps(vc3, vt2), vc2);
217     __m256 vp3 = _mm256_add_ps(_mm256_mul_ps(vc3, vt3), vc2);
218 
219     vp0 = _mm256_mul_ps(vp0, vt0);
220     vp1 = _mm256_mul_ps(vp1, vt1);
221     vp2 = _mm256_mul_ps(vp2, vt2);
222     vp3 = _mm256_mul_ps(vp3, vt3);
223 
224     vt0 = _mm256_mul_ps(vt0, vs0);
225     vs0 = _mm256_sub_ps(vs0, vone);
226     vt1 = _mm256_mul_ps(vt1, vs1);
227     vs1 = _mm256_sub_ps(vs1, vone);
228     vt2 = _mm256_mul_ps(vt2, vs2);
229     vs2 = _mm256_sub_ps(vs2, vone);
230     vt3 = _mm256_mul_ps(vt3, vs3);
231     vs3 = _mm256_sub_ps(vs3, vone);
232 
233     vp0 = _mm256_add_ps(_mm256_mul_ps(vp0, vt0), vt0);
234     vp1 = _mm256_add_ps(_mm256_mul_ps(vp1, vt1), vt1);
235     vp2 = _mm256_add_ps(_mm256_mul_ps(vp2, vt2), vt2);
236     vp3 = _mm256_add_ps(_mm256_mul_ps(vp3, vt3), vt3);
237 
238     const __m256 ve0 = _mm256_mul_ps(_mm256_add_ps(vp0, vs0), valpha);
239     vx0 = _mm256_mul_ps(vx0, vbeta);
240     const __m256 ve1 = _mm256_mul_ps(_mm256_add_ps(vp1, vs1), valpha);
241     vx1 = _mm256_mul_ps(vx1, vbeta);
242     const __m256 ve2 = _mm256_mul_ps(_mm256_add_ps(vp2, vs2), valpha);
243     vx2 = _mm256_mul_ps(vx2, vbeta);
244     const __m256 ve3 = _mm256_mul_ps(_mm256_add_ps(vp3, vs3), valpha);
245     vx3 = _mm256_mul_ps(vx3, vbeta);
246 
247     const __m256 vy0 = _mm256_blendv_ps(vx0, ve0, vx0);
248     const __m256 vy1 = _mm256_blendv_ps(vx1, ve1, vx1);
249     const __m256 vy2 = _mm256_blendv_ps(vx2, ve2, vx2);
250     const __m256 vy3 = _mm256_blendv_ps(vx3, ve3, vx3);
251 
252     _mm256_storeu_ps(y, vy0);
253     _mm256_storeu_ps(y + 8, vy1);
254     _mm256_storeu_ps(y + 16, vy2);
255     _mm256_storeu_ps(y + 24, vy3);
256     y += 32;
257   }
258   for (; n >= 8 * sizeof(float); n -= 8 * sizeof(float)) {
259     __m256 vx = _mm256_loadu_ps(x);
260     x += 8;
261 
262     const __m256 vz = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx, vprescale));
263 
264     __m256 vn = _mm256_add_ps(_mm256_mul_ps(vz, vlog2e), vmagic_bias);
265 
266     const __m256 vidx = _mm256_and_ps(vn, vindex_mask);
267 
268     const __m128i vidx_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx)), 2);
269     const __m128i vidx_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx, 1)), 2);
270     #if XNN_ARCH_X86_64
271       const uint64_t vidx_ll = (uint64_t) _mm_cvtsi128_si64(vidx_lo);
272       const uint64_t vidx_lh = (uint64_t) _mm_extract_epi64(vidx_lo, 1);
273       const uint64_t vidx_hl = (uint64_t) _mm_cvtsi128_si64(vidx_hi);
274       const uint64_t vidx_hh = (uint64_t) _mm_extract_epi64(vidx_hi, 1);
275       __m128i vl_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_ll));
276       __m128i vl_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_lh));
277       __m128i vl_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_hl));
278       __m128i vl_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_hh));
279       vl_ll = _mm_insert_epi32(vl_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_ll >> 32))), 1);
280       vl_lh = _mm_insert_epi32(vl_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_lh >> 32))), 1);
281       vl_hl = _mm_insert_epi32(vl_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_hl >> 32))), 1);
282       vl_hh = _mm_insert_epi32(vl_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_hh >> 32))), 1);
283     #else
284       __m128i vl_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx_lo)));
285       __m128i vl_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 2)));
286       __m128i vl_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx_hi)));
287       __m128i vl_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 2)));
288       vl_ll = _mm_insert_epi32(vl_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 1))), 1);
289       vl_lh = _mm_insert_epi32(vl_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 3))), 1);
290       vl_hl = _mm_insert_epi32(vl_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 1))), 1);
291       vl_hh = _mm_insert_epi32(vl_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 3))), 1);
292     #endif
293     const __m128i ven_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn)), 19);
294     const __m128i ven_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn, 1)), 19);
295 
296     const __m128i vl_lo = _mm_unpacklo_epi64(vl_ll, vl_lh);
297     const __m128i vl_hi = _mm_unpacklo_epi64(vl_hl, vl_hh);
298 
299     vn = _mm256_sub_ps(vn, vmagic_bias);
300     const __m128 vs_lo = _mm_castsi128_ps(_mm_add_epi32(vl_lo, ven_lo));
301     const __m128 vs_hi = _mm_castsi128_ps(_mm_add_epi32(vl_hi, ven_hi));
302 
303     __m256 vt = _mm256_add_ps(_mm256_mul_ps(vn, vminus_ln2_hi), vz);
304     vt = _mm256_add_ps(_mm256_mul_ps(vn, vminus_ln2_lo), vt);
305     __m256 vs = _mm256_insertf128_ps(_mm256_castps128_ps256(vs_lo), vs_hi, 1);
306 
307     __m256 vp = _mm256_add_ps(_mm256_mul_ps(vc3, vt), vc2);
308     vp = _mm256_mul_ps(vp, vt);
309 
310     vt = _mm256_mul_ps(vt, vs);
311     vs = _mm256_sub_ps(vs, vone);
312     vp = _mm256_add_ps(_mm256_mul_ps(vp, vt), vt);
313 
314     const __m256 ve = _mm256_mul_ps(_mm256_add_ps(vp, vs), valpha);
315     vx = _mm256_mul_ps(vx, vbeta);
316     const __m256 vy = _mm256_blendv_ps(vx, ve, vx);
317 
318     _mm256_storeu_ps(y, vy);
319     y += 8;
320   }
321   if XNN_UNLIKELY(n != 0) {
322     assert(n >= 1 * sizeof(float));
323     assert(n <= 7 * sizeof(float));
324     __m256i vmask = _mm256_loadu_si256((const __m256i*) ((uintptr_t) &mask_table[7] - n));
325 
326     __m256 vx = _mm256_maskload_ps(x, vmask);
327 
328     const __m256 vz = _mm256_max_ps(vsat_cutoff, _mm256_mul_ps(vx, vprescale));
329 
330     __m256 vn = _mm256_add_ps(_mm256_mul_ps(vz, vlog2e), vmagic_bias);
331 
332     const __m256 vidx = _mm256_and_ps(vn, vindex_mask);
333 
334     const __m128i vidx_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vidx)), 2);
335     const __m128i vidx_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vidx, 1)), 2);
336     #if XNN_ARCH_X86_64
337       const uint64_t vidx_ll = (uint64_t) _mm_cvtsi128_si64(vidx_lo);
338       const uint64_t vidx_lh = (uint64_t) _mm_extract_epi64(vidx_lo, 1);
339       const uint64_t vidx_hl = (uint64_t) _mm_cvtsi128_si64(vidx_hi);
340       const uint64_t vidx_hh = (uint64_t) _mm_extract_epi64(vidx_hi, 1);
341       __m128i vl_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_ll));
342       __m128i vl_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_lh));
343       __m128i vl_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_hl));
344       __m128i vl_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) vidx_hh));
345       vl_ll = _mm_insert_epi32(vl_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_ll >> 32))), 1);
346       vl_lh = _mm_insert_epi32(vl_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_lh >> 32))), 1);
347       vl_hl = _mm_insert_epi32(vl_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_hl >> 32))), 1);
348       vl_hh = _mm_insert_epi32(vl_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) (vidx_hh >> 32))), 1);
349     #else
350       __m128i vl_ll = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx_lo)));
351       __m128i vl_lh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 2)));
352       __m128i vl_hl = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_cvtsi128_si32(vidx_hi)));
353       __m128i vl_hh = _mm_loadu_si32((const void*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 2)));
354       vl_ll = _mm_insert_epi32(vl_ll, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 1))), 1);
355       vl_lh = _mm_insert_epi32(vl_lh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_lo, 3))), 1);
356       vl_hl = _mm_insert_epi32(vl_hl, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 1))), 1);
357       vl_hh = _mm_insert_epi32(vl_hh, *((const int*) ((uintptr_t) xnn_table_exp2minus_k_over_16 + (uint32_t) _mm_extract_epi32(vidx_hi, 3))), 1);
358     #endif
359     const __m128i ven_lo = _mm_slli_epi32(_mm_castps_si128(_mm256_castps256_ps128(vn)), 19);
360     const __m128i ven_hi = _mm_slli_epi32(_mm_castps_si128(_mm256_extractf128_ps(vn, 1)), 19);
361 
362     const __m128i vl_lo = _mm_unpacklo_epi64(vl_ll, vl_lh);
363     const __m128i vl_hi = _mm_unpacklo_epi64(vl_hl, vl_hh);
364 
365     vn = _mm256_sub_ps(vn, vmagic_bias);
366     const __m128 vs_lo = _mm_castsi128_ps(_mm_add_epi32(vl_lo, ven_lo));
367     const __m128 vs_hi = _mm_castsi128_ps(_mm_add_epi32(vl_hi, ven_hi));
368 
369     __m256 vt = _mm256_add_ps(_mm256_mul_ps(vn, vminus_ln2_hi), vz);
370     vt = _mm256_add_ps(_mm256_mul_ps(vn, vminus_ln2_lo), vt);
371     __m256 vs = _mm256_insertf128_ps(_mm256_castps128_ps256(vs_lo), vs_hi, 1);
372 
373     __m256 vp = _mm256_add_ps(_mm256_mul_ps(vc3, vt), vc2);
374     vp = _mm256_mul_ps(vp, vt);
375 
376     vt = _mm256_mul_ps(vt, vs);
377     vs = _mm256_sub_ps(vs, vone);
378     vp = _mm256_add_ps(_mm256_mul_ps(vp, vt), vt);
379 
380     const __m256 ve = _mm256_mul_ps(_mm256_add_ps(vp, vs), valpha);
381     vx = _mm256_mul_ps(vx, vbeta);
382     const __m256 vy = _mm256_blendv_ps(vx, ve, vx);
383 
384     // _mm256_maskstore_ps(y, vmask, vf) could be used here, but triggers msan failures (probably an msan bug).
385     __m128 vy_lo = _mm256_castps256_ps128(vy);
386     if (n & (4 * sizeof(float))) {
387       _mm_storeu_ps(y, vy_lo);
388       vy_lo = _mm256_extractf128_ps(vy, 1);
389       y += 4;
390     }
391     if (n & (2 * sizeof(float))) {
392       _mm_storel_pi((__m64*) y, vy_lo);
393       vy_lo = _mm_movehl_ps(vy_lo, vy_lo);
394       y += 2;
395     }
396     if (n & (1 * sizeof(float))) {
397       _mm_store_ss(y, vy_lo);
398     }
399   }
400 }
401