summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2025-10-24 22:05:37 -0700
committerVitaly Buka <vitalybuka@google.com>2025-10-24 22:05:37 -0700
commit4204d078f9c839f42a67ef4a4ded416f2c75a7fa (patch)
tree4b847c135fe6dd7d25ab7e127d62955501c12937
parentc9a45d3fd777997f669ff6af9c1f27e60a0fa23f (diff)
[𝘀𝗽𝗿] changes to main this commit is based onusers/vitalybuka/spr/main.adtnfc-add-missing-include-vector-165068
Created using spr 1.3.7 [skip ci]
-rw-r--r--llvm/include/llvm/Support/SpecialCaseList.h12
-rw-r--r--llvm/lib/Support/SpecialCaseList.cpp60
2 files changed, 68 insertions, 4 deletions
diff --git a/llvm/include/llvm/Support/SpecialCaseList.h b/llvm/include/llvm/Support/SpecialCaseList.h
index ead765562504..3e7592f153c2 100644
--- a/llvm/include/llvm/Support/SpecialCaseList.h
+++ b/llvm/include/llvm/Support/SpecialCaseList.h
@@ -13,7 +13,10 @@
#define LLVM_SUPPORT_SPECIALCASELIST_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/RadixTree.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/GlobPattern.h"
@@ -162,6 +165,15 @@ private:
};
std::vector<GlobMatcher::Glob> Globs;
+
+ RadixTree<iterator_range<StringRef::const_reverse_iterator>,
+ RadixTree<iterator_range<StringRef::const_iterator>,
+ SmallVector<const GlobMatcher::Glob *, 1>>>
+ SuffixPrefixToGlob;
+
+ RadixTree<iterator_range<StringRef::const_iterator>,
+ SmallVector<const GlobMatcher::Glob *, 1>>
+ SubstrToGlob;
};
/// Represents a set of patterns and their line numbers
diff --git a/llvm/lib/Support/SpecialCaseList.cpp b/llvm/lib/Support/SpecialCaseList.cpp
index f74e52a3a7fa..944f59f245be 100644
--- a/llvm/lib/Support/SpecialCaseList.cpp
+++ b/llvm/lib/Support/SpecialCaseList.cpp
@@ -89,17 +89,69 @@ void SpecialCaseList::GlobMatcher::preprocess(bool BySize) {
return A.Name.size() < B.Name.size();
});
}
+
+ for (const auto &G : Globs) {
+ StringRef Prefix = G.Pattern.prefix();
+ StringRef Suffix = G.Pattern.suffix();
+
+ if (Suffix.empty() && Prefix.empty()) {
+ // If both prefix and suffix are empty put into special tree to search by
+ // substring in a middle.
+ StringRef Substr = G.Pattern.longest_substr();
+ if (!Substr.empty()) {
+ // But only if substring is not empty. Searching this tree is more
+ // expensive.
+ auto &V = SubstrToGlob.emplace(Substr).first->second;
+ V.emplace_back(&G);
+ continue;
+ }
+ }
+
+ auto &PToGlob = SuffixPrefixToGlob.emplace(reverse(Suffix)).first->second;
+ auto &V = PToGlob.emplace(Prefix).first->second;
+ V.emplace_back(&G);
+ }
}
void SpecialCaseList::GlobMatcher::match(
StringRef Query,
llvm::function_ref<void(StringRef Rule, unsigned LineNo)> Cb) const {
- for (const auto &G : reverse(Globs))
- if (G.Pattern.match(Query))
- return Cb(G.Name, G.LineNo);
+ if (!SuffixPrefixToGlob.empty()) {
+ for (const auto &[_, PToGlob] :
+ SuffixPrefixToGlob.find_prefixes(reverse(Query))) {
+ for (const auto &[_, V] : PToGlob.find_prefixes(Query)) {
+ for (const auto *G : V) {
+ // Each value of the map is a vector of globs sorted as from best to
+ // worst.
+ if (G->Pattern.match(Query)) {
+ Cb(G->Name, G->LineNo);
+ // As soon as we find a match in the vector we can break for the vector,
+ // vector, but we still need to continue for other values in the
+ // map, as they may contain a better match.
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!SubstrToGlob.empty()) {
+ // As we don't know when substring exactly starts, we will try all
+ // possibilities. In most cases search will fail on first characters.
+ for (StringRef Q = Query; !Q.empty(); Q = Q.drop_front()) {
+ for (const auto &[_, V] : SubstrToGlob.find_prefixes(Q)) {
+ for (const auto *G : reverse(V)) {
+ if (G->Pattern.match(Query)) {
+ Cb(G->Name, G->LineNo);
+ break;
+ }
+ }
+ }
+ }
+ }
}
-SpecialCaseList::Matcher::Matcher(bool UseGlobs, bool RemoveDotSlash)
+ SpecialCaseList::Matcher::Matcher(bool UseGlobs, bool RemoveDotSlash)
: RemoveDotSlash(RemoveDotSlash) {
if (UseGlobs)
M.emplace<GlobMatcher>();