[PATCH] D133658: [Support] Use find() for faster StringRef::count.
Tatsuyuki Ishi via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 11 00:19:31 PDT 2022
ishitatsuyuki created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
ishitatsuyuki requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
While profiling InclusionRewriter, it was found that counting lines was
so slow that it took up 20% of the processing time. Surely, calling
memcmp() of size 1 on every substring in the window isn't a good idea.
Use StringRef::find() instead; in the case of N=1 it will forward to
memcmp which is much more optimal. For 2<=N<256 it will run the same
memcmp loop as we have now, which is still suboptimal but at least does
not regress anything.
[Support] Add fast path for StringRef::find with needle of length 2.
InclusionRewriter on Windows (CRLF line endings) will exercise this in a
hot path. Calling memcmp repeatedly would be highly suboptimal for that
use case, so give it a specialized path.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D133658
Files:
llvm/lib/Support/StringRef.cpp
Index: llvm/lib/Support/StringRef.cpp
===================================================================
--- llvm/lib/Support/StringRef.cpp
+++ llvm/lib/Support/StringRef.cpp
@@ -148,6 +148,23 @@
const char *Stop = Start + (Size - N + 1);
+ if (N == 2) {
+ // Provide a fast path for newline finding (CRLF case) in InclusionRewriter.
+ // This is basically a naive search with a little bit twiddling.
+
+ // In theory we could use uint16_t, but some architectures don't support
+ // 16-bit arithmetic and will require a (& 65535) after the bit operations.
+ // Using 32-bit arithmetic with a shift of 16 would be more efficient for
+ // those cases.
+ uint32_t NeedleWord =
+ (uint32_t)(uint8_t)Needle[0] << 16 | (uint8_t)Needle[1];
+ uint32_t HaystackWord =
+ (uint32_t)(uint8_t)Start[0] << 16 | (uint8_t)Start[1];
+ for (Start++; Start < Stop && NeedleWord != HaystackWord;)
+ HaystackWord = HaystackWord << 16 | (uint8_t) * ++Start;
+ return NeedleWord == HaystackWord ? Start - Data - 1 : npos;
+ }
+
// For short haystacks or unsupported needles fall back to the naive algorithm
if (Size < 16 || N > 255) {
do {
@@ -370,16 +387,11 @@
/// the string.
size_t StringRef::count(StringRef Str) const {
size_t Count = 0;
+ size_t Pos = 0;
size_t N = Str.size();
- if (!N || N > Length)
- return 0;
- for (size_t i = 0, e = Length - N + 1; i < e;) {
- if (substr(i, N).equals(Str)) {
- ++Count;
- i += N;
- }
- else
- ++i;
+ while ((Pos = find(Str, Pos)) != npos) {
+ ++Count;
+ Pos += N;
}
return Count;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D133658.459328.patch
Type: text/x-patch
Size: 1627 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220911/ec76082f/attachment.bin>
More information about the llvm-commits
mailing list