From 344510086be1d48ad32191b6a1f5380372c0ba1b Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 14 Mar 2020 17:20:12 -0700 Subject: [PATCH] ircd: Add vectorized multi-string match tool. --- include/ircd/stringops.h | 4 +-- ircd/stringops.cc | 69 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/include/ircd/stringops.h b/include/ircd/stringops.h index e91448640..e5427f7dc 100644 --- a/include/ircd/stringops.h +++ b/include/ircd/stringops.h @@ -22,8 +22,8 @@ namespace ircd inline size_t ifind(const string_view &s, const string_view &t); // Multi-string table suite; returns index past the end on no-match - using string_table = vector_view; - size_t indexof(const string_view &, const string_table &); + using string_views = vector_view; + size_t indexof(const string_view &, const string_views &); // return view without any trailing characters contained in c string_view rstripa(const string_view &str, const string_view &c); diff --git a/ircd/stringops.cc b/ircd/stringops.cc index a98a792c2..3fb9b3842 100644 --- a/ircd/stringops.cc +++ b/ircd/stringops.cc @@ -10,15 +10,74 @@ #include +namespace ircd +{ + template + static size_t indexof(const string_view &, const std::array &); +} + size_t ircd::indexof(const string_view &s, - const string_table &tab) + const string_views &tab) { - size_t i(0); - for(; i < tab.size(); ++i) - if(s == tab[i]) - break; + #if defined(__AVX__) + static const size_t N {32}; + using i8xN = i8x32; + #elif defined(__SSE__) + static const size_t N {16}; + using i8xN = i8x16; + #else + static const size_t N {1}; + using i8xN = char __attribute__((vector_size(1))); + #endif + size_t i, j, ret; + std::array a; + for(i = 0; i < tab.size() / N; ++i) + { + for(j = 0; j < N; ++j) + a[j] = tab[i * N + j]; + + if((ret = indexof(s, a)) != N) + return i * N + ret; + } + + #pragma clang loop unroll (disable) + for(j = 0; j < N; ++j) + a[j] = i * N + j < tab.size()? + tab[i * N + j]: + string_view{}; + + return i * N + indexof(s, a); +} + +template +size_t +ircd::indexof(const string_view &s, + const std::array &st) +{ + i8xN ct, res; + size_t i, j, k; + for(i = 0; i < N; ++i) + res[i] = true; + + const size_t max(s.size()); + for(i = 0, j = 0; i < max; i = (j < N)? i + 1 : max) + { + #pragma clang loop unroll (disable) + for(k = 0; k < N; ++k) + { + res[k] &= size(st[k]) > i; + ct[k] = res[k]? st[k][i]: 0; + } + + res &= ct == s[i]; + for(; j < N && !res[j]; ++j); + } + + for(i = 0; i < N && !res[i]; ++i); return i; }