[llvm] [llvm] Improve implementation of StringRef::find_last_of and cie (PR #71865)

Alexandre Ganea via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 16 16:06:57 PST 2023


================
@@ -268,17 +268,47 @@ StringRef::size_type StringRef::find_first_not_of(StringRef Chars,
   return npos;
 }
 
+// See https://graphics.stanford.edu/~seander/bithacks.html#ValueInWord
+static inline uint64_t haszero(uint64_t v) {
+  return ((v)-0x0101010101010101UL) & ~(v) & 0x8080808080808080UL;
+}
+static inline uint64_t hasvalue(uint64_t x, char n) {
+  return haszero((x) ^ (~0UL / 255 * (n)));
+}
+
+/// This is a hot spot for some clangd operations, enough to be eligible to
+/// a vectorized implementation.
+static StringRef::size_type
+vectorized_find_last_of_specialized(const char *Data, size_t Sz, char C0,
+                                    char C1) {
+  do {
+    Sz = Sz < 8 ? 0 : Sz - 8;
+    uint64_t Buffer = 0;
+    std::memcpy((void *)&Buffer, (void *)(Data + Sz), sizeof(Buffer));
+    uint64_t Check0 = hasvalue(Buffer, C0);
+    uint64_t Check = Check0 ? Check0 : hasvalue(Buffer, C1);
+    if (Check)
+      return Sz + 7 - llvm::countl_zero(Check) / 8;
+  } while (Sz);
+  return -1;
+}
+
 /// find_last_of - Find the last character in the string that is in \arg C,
 /// or npos if not found.
 ///
 /// Note: O(size() + Chars.size())
 StringRef::size_type StringRef::find_last_of(StringRef Chars,
                                              size_t From) const {
+  size_type Sz = std::min(From, Length);
+
+  if (Chars.size() == 2)
----------------
aganea wrote:

Could you please elaborate a bit more on the specific use cases that you hit in _clangd_ that justify this `if (Chars.size() == 2)`? At least a unit test along with a little comment about the "why" will help future readers of this patch.

https://github.com/llvm/llvm-project/pull/71865


More information about the llvm-commits mailing list