Skip to content

Commit 47fc3d8

Browse files
committed
RequirementMachine: Speed up PropertyMap lookups with a suffix trie
Whereas term simplification uses a prefix trie with shortest matching, the PropertyMap uses a suffix trie with longest matching.
1 parent 776a088 commit 47fc3d8

File tree

4 files changed

+46
-45
lines changed

4 files changed

+46
-45
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -650,42 +650,19 @@ void PropertyBag::copyPropertiesFrom(const PropertyBag *next,
650650
}
651651
}
652652

653-
/// Look for an property bag corresponding to the given key, returning nullptr
654-
/// if one has not been recorded.
655-
PropertyBag *
656-
PropertyMap::getPropertiesIfPresent(const MutableTerm &key) const {
657-
assert(!key.empty());
658-
659-
for (const auto &props : Map) {
660-
int compare = props->getKey().compare(key, Protos);
661-
if (compare == 0)
662-
return props.get();
663-
if (compare > 0)
664-
return nullptr;
665-
}
666-
667-
return nullptr;
653+
PropertyMap::~PropertyMap() {
654+
Trie.updateHistograms(Context.PropertyTrieHistogram,
655+
Context.PropertyTrieRootHistogram);
656+
clear();
668657
}
669658

670659
/// Look for an property bag corresponding to a suffix of the given key.
671660
///
672661
/// Returns nullptr if no information is known about this key.
673662
PropertyBag *
674663
PropertyMap::lookUpProperties(const MutableTerm &key) const {
675-
if (auto *props = getPropertiesIfPresent(key))
676-
return props;
677-
678-
auto begin = key.begin() + 1;
679-
auto end = key.end();
680-
681-
while (begin != end) {
682-
MutableTerm suffix(begin, end);
683-
684-
if (auto *suffixClass = getPropertiesIfPresent(suffix))
685-
return suffixClass;
686-
687-
++begin;
688-
}
664+
if (auto result = Trie.find(key.rbegin(), key.rend()))
665+
return *result;
689666

690667
return nullptr;
691668
}
@@ -698,13 +675,10 @@ PropertyBag *
698675
PropertyMap::getOrCreateProperties(const MutableTerm &key) {
699676
assert(!key.empty());
700677

701-
if (!Map.empty()) {
702-
const auto &lastEquivClass = Map.back();
703-
int compare = lastEquivClass->getKey().compare(key, Protos);
704-
if (compare == 0)
705-
return lastEquivClass.get();
706-
707-
assert(compare < 0 && "Must record property bags in sorted order");
678+
if (!Entries.empty()) {
679+
const auto &lastEntry = Entries.back();
680+
if (lastEntry->getKey() == key)
681+
return lastEntry;
708682
}
709683

710684
auto *props = new PropertyBag(key);
@@ -733,13 +707,31 @@ PropertyMap::getOrCreateProperties(const MutableTerm &key) {
733707
if (auto *next = lookUpProperties(key))
734708
props->copyPropertiesFrom(next, Context);
735709

736-
Map.emplace_back(props);
710+
// Here is where we make the assumption that if the new key is not equal to
711+
// the key of the last entry, then it is larger than any key already in the
712+
// map.
713+
Entries.push_back(props);
714+
auto oldProps = Trie.insert(key.rbegin(), key.rend(), props);
715+
if (oldProps) {
716+
llvm::errs() << "Duplicate property map entry for " << key << "\n";
717+
llvm::errs() << "Old:\n";
718+
(*oldProps)->dump(llvm::errs());
719+
llvm::errs() << "\n";
720+
llvm::errs() << "New:\n";
721+
props->dump(llvm::errs());
722+
llvm::errs() << "\n";
723+
abort();
724+
}
737725

738726
return props;
739727
}
740728

741729
void PropertyMap::clear() {
742-
Map.clear();
730+
for (auto *props : Entries)
731+
delete props;
732+
733+
Trie.clear();
734+
Entries.clear();
743735
ConcreteTypeInDomainMap.clear();
744736
}
745737

@@ -757,7 +749,7 @@ void PropertyMap::addProperty(
757749
/// For each fully-concrete type, find the shortest term having that concrete type.
758750
/// This is later used by computeConstraintTermForTypeWitness().
759751
void PropertyMap::computeConcreteTypeInDomainMap() {
760-
for (const auto &props : Map) {
752+
for (const auto &props : Entries) {
761753
if (!props->isConcreteType())
762754
continue;
763755

@@ -787,7 +779,7 @@ void PropertyMap::computeConcreteTypeInDomainMap() {
787779

788780
void PropertyMap::concretizeNestedTypesFromConcreteParents(
789781
SmallVectorImpl<std::pair<MutableTerm, MutableTerm>> &inducedRules) const {
790-
for (const auto &props : Map) {
782+
for (const auto &props : Entries) {
791783
if (props->getConformsTo().empty())
792784
continue;
793785

@@ -1030,7 +1022,7 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
10301022

10311023
void PropertyMap::dump(llvm::raw_ostream &out) const {
10321024
out << "Property map: {\n";
1033-
for (const auto &props : Map) {
1025+
for (const auto &props : Entries) {
10341026
out << " ";
10351027
props->dump(out);
10361028
out << "\n";

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "llvm/ADT/SmallVector.h"
2424
#include "llvm/ADT/TinyPtrVector.h"
2525
#include <algorithm>
26-
#include <memory>
2726
#include <vector>
2827

2928
#include "ProtocolGraph.h"
@@ -139,7 +138,8 @@ class PropertyBag {
139138
/// Out-of-line methods are documented in PropertyMap.cpp.
140139
class PropertyMap {
141140
RewriteContext &Context;
142-
std::vector<std::unique_ptr<PropertyBag>> Map;
141+
std::vector<PropertyBag *> Entries;
142+
Trie<PropertyBag *, MatchKind::Longest> Trie;
143143

144144
using ConcreteTypeInDomain = std::pair<CanType, ArrayRef<const ProtocolDecl *>>;
145145
llvm::DenseMap<ConcreteTypeInDomain, MutableTerm> ConcreteTypeInDomainMap;
@@ -148,7 +148,6 @@ class PropertyMap {
148148
unsigned DebugConcreteUnification : 1;
149149
unsigned DebugConcretizeNestedTypes : 1;
150150

151-
PropertyBag *getPropertiesIfPresent(const MutableTerm &key) const;
152151
PropertyBag *getOrCreateProperties(const MutableTerm &key);
153152

154153
PropertyMap(const PropertyMap &) = delete;
@@ -164,6 +163,8 @@ class PropertyMap {
164163
DebugConcretizeNestedTypes = false;
165164
}
166165

166+
~PropertyMap();
167+
167168
PropertyBag *lookUpProperties(const MutableTerm &key) const;
168169

169170
void dump(llvm::raw_ostream &out) const;

lib/AST/RequirementMachine/RewriteContext.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ RewriteContext::RewriteContext(ASTContext &ctx)
2525
SymbolHistogram(Symbol::NumKinds),
2626
TermHistogram(4, /*Start=*/1),
2727
RuleTrieHistogram(16, /*Start=*/1),
28-
RuleTrieRootHistogram(16) {
28+
RuleTrieRootHistogram(16),
29+
PropertyTrieHistogram(16, /*Start=*/1),
30+
PropertyTrieRootHistogram(16) {
2931
}
3032

3133
Term RewriteContext::getTermForType(CanType paramType,
@@ -295,5 +297,9 @@ RewriteContext::~RewriteContext() {
295297
RuleTrieHistogram.dump(llvm::dbgs());
296298
llvm::dbgs() << "\n* Rule trie root fanout:\n";
297299
RuleTrieRootHistogram.dump(llvm::dbgs());
300+
llvm::dbgs() << "\n* Property trie fanout:\n";
301+
PropertyTrieHistogram.dump(llvm::dbgs());
302+
llvm::dbgs() << "\n* Property trie root fanout:\n";
303+
PropertyTrieRootHistogram.dump(llvm::dbgs());
298304
}
299305
}

lib/AST/RequirementMachine/RewriteContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class RewriteContext final {
6060
Histogram TermHistogram;
6161
Histogram RuleTrieHistogram;
6262
Histogram RuleTrieRootHistogram;
63+
Histogram PropertyTrieHistogram;
64+
Histogram PropertyTrieRootHistogram;
6365

6466
explicit RewriteContext(ASTContext &ctx);
6567

0 commit comments

Comments
 (0)