Skip to content

Commit f1d60a0

Browse files
rupprechtvitalybuka
authored andcommitted
[𝘀𝗽𝗿] initial version
Created using spr 1.3.7
2 parents c9a45d3 + 4204d07 commit f1d60a0

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

llvm/include/llvm/ADT/RadixTree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <limits>
2323
#include <list>
2424
#include <utility>
25+
#include <vector>
2526

2627
namespace llvm {
2728

llvm/include/llvm/Support/SpecialCaseList.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
#define LLVM_SUPPORT_SPECIALCASELIST_H
1414

1515
#include "llvm/ADT/ArrayRef.h"
16+
#include "llvm/ADT/RadixTree.h"
17+
#include "llvm/ADT/SmallVector.h"
1618
#include "llvm/ADT/StringMap.h"
19+
#include "llvm/ADT/iterator_range.h"
1720
#include "llvm/Support/Allocator.h"
1821
#include "llvm/Support/Compiler.h"
1922
#include "llvm/Support/GlobPattern.h"
@@ -162,6 +165,15 @@ class SpecialCaseList {
162165
};
163166

164167
std::vector<GlobMatcher::Glob> Globs;
168+
169+
RadixTree<iterator_range<StringRef::const_reverse_iterator>,
170+
RadixTree<iterator_range<StringRef::const_iterator>,
171+
SmallVector<const GlobMatcher::Glob *, 1>>>
172+
SuffixPrefixToGlob;
173+
174+
RadixTree<iterator_range<StringRef::const_iterator>,
175+
SmallVector<const GlobMatcher::Glob *, 1>>
176+
SubstrToGlob;
165177
};
166178

167179
/// Represents a set of patterns and their line numbers

llvm/lib/Support/SpecialCaseList.cpp

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,69 @@ void SpecialCaseList::GlobMatcher::preprocess(bool BySize) {
8989
return A.Name.size() < B.Name.size();
9090
});
9191
}
92+
93+
for (const auto &G : Globs) {
94+
StringRef Prefix = G.Pattern.prefix();
95+
StringRef Suffix = G.Pattern.suffix();
96+
97+
if (Suffix.empty() && Prefix.empty()) {
98+
// If both prefix and suffix are empty put into special tree to search by
99+
// substring in a middle.
100+
StringRef Substr = G.Pattern.longest_substr();
101+
if (!Substr.empty()) {
102+
// But only if substring is not empty. Searching this tree is more
103+
// expensive.
104+
auto &V = SubstrToGlob.emplace(Substr).first->second;
105+
V.emplace_back(&G);
106+
continue;
107+
}
108+
}
109+
110+
auto &PToGlob = SuffixPrefixToGlob.emplace(reverse(Suffix)).first->second;
111+
auto &V = PToGlob.emplace(Prefix).first->second;
112+
V.emplace_back(&G);
113+
}
92114
}
93115

94116
void SpecialCaseList::GlobMatcher::match(
95117
StringRef Query,
96118
llvm::function_ref<void(StringRef Rule, unsigned LineNo)> Cb) const {
97-
for (const auto &G : reverse(Globs))
98-
if (G.Pattern.match(Query))
99-
return Cb(G.Name, G.LineNo);
119+
if (!SuffixPrefixToGlob.empty()) {
120+
for (const auto &[_, PToGlob] :
121+
SuffixPrefixToGlob.find_prefixes(reverse(Query))) {
122+
for (const auto &[_, V] : PToGlob.find_prefixes(Query)) {
123+
for (const auto *G : V) {
124+
// Each value of the map is a vector of globs ordered from the best to
125+
// the worst.
126+
if (G->Pattern.match(Query)) {
127+
Cb(G->Name, G->LineNo);
128+
// As soon as we find a match in the vector we can break for the
129+
// vector, still we can't return, and need to continue for others
130+
// values in the map, as they may contain a better match.
131+
break;
132+
}
133+
}
134+
}
135+
}
136+
}
137+
138+
if (!SubstrToGlob.empty()) {
139+
// As we don't know when substring exactly starts, we will try all
140+
// possibilities. In most cases search will fail on first characters.
141+
for (StringRef Q = Query; !Q.empty(); Q = Q.drop_front()) {
142+
for (const auto &[_, V] : SubstrToGlob.find_prefixes(Q)) {
143+
for (const auto *G : reverse(V)) {
144+
if (G->Pattern.match(Query)) {
145+
Cb(G->Name, G->LineNo);
146+
break;
147+
}
148+
}
149+
}
150+
}
151+
}
100152
}
101153

102-
SpecialCaseList::Matcher::Matcher(bool UseGlobs, bool RemoveDotSlash)
154+
SpecialCaseList::Matcher::Matcher(bool UseGlobs, bool RemoveDotSlash)
103155
: RemoveDotSlash(RemoveDotSlash) {
104156
if (UseGlobs)
105157
M.emplace<GlobMatcher>();

0 commit comments

Comments
 (0)