Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
| 279 | #ifdef RAPIDJSON_SSE42 |
| 280 | //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. |
| 281 | inline const char *SkipWhitespace_SIMD(const char* p) { |
| 282 | // Fast return for single non-whitespace |
| 283 | if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') |
| 284 | ++p; |
| 285 | else |
| 286 | return p; |
| 287 | |
| 288 | // 16-byte align to the next boundary |
| 289 | const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); |
| 290 | while (p != nextAligned) |
| 291 | if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') |
| 292 | ++p; |
| 293 | else |
| 294 | return p; |
| 295 | |
| 296 | // The rest of string using SIMD |
| 297 | static const char whitespace[16] = " \n\r\t"; |
| 298 | const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0])); |
| 299 | |
| 300 | for (;; p += 16) { |
| 301 | const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); |
| 302 | const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); |
| 303 | if (r != 0) { // some of characters is non-whitespace |
| 304 | #ifdef _MSC_VER // Find the index of first non-whitespace |
| 305 | unsigned long offset; |
| 306 | _BitScanForward(&offset, r); |
| 307 | return p + offset; |
| 308 | #else |
| 309 | return p + __builtin_ffs(r) - 1; |
| 310 | #endif |
| 311 | } |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { |
| 316 | // Fast return for single non-whitespace |
no test coverage detected