diff options
| author | Vedant Kumar <vsk@apple.com> | 2019-09-16 19:08:44 +0000 |
|---|---|---|
| committer | Vedant Kumar <vsk@apple.com> | 2019-09-16 19:08:44 +0000 |
| commit | 413647d730972eac9675f695c2ea63fb393a5531 (patch) | |
| tree | f9ed31bab717ab132cb998371c0a44e4d06e720e | |
| parent | 95de24978e80c1fac6d452057b21a448a0c6d7d6 (diff) | |
| download | bcm5719-llvm-413647d730972eac9675f695c2ea63fb393a5531.tar.gz bcm5719-llvm-413647d730972eac9675f695c2ea63fb393a5531.zip | |
[Coverage] Speed up file-based queries for coverage info, NFC
Speed up queries for coverage info in a file by reducing the amount of
time spent determining whether a function record corresponds to a file.
This gives a 36% speedup when generating a coverage report for `llc`.
The reduction is entirely in user time.
rdar://54758110
Differential Revision: https://reviews.llvm.org/D67575
llvm-svn: 372025
| -rw-r--r-- | llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h | 15 | ||||
| -rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 37 |
2 files changed, 49 insertions, 3 deletions
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 7284a67ba4a..0dd0c7ec806 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -301,7 +301,12 @@ public: struct FunctionRecord { /// Raw function name. std::string Name; - /// Associated files. + /// Mapping from FileID (i.e. vector index) to filename. Used to support + /// macro expansions within a function in which the macro and function are + /// defined in separate files. + /// + /// TODO: Uniquing filenames across all function records may be a performance + /// optimization. std::vector<std::string> Filenames; /// Regions in the function along with their counts. std::vector<CountedRegion> CountedRegions; @@ -508,6 +513,7 @@ public: class CoverageMapping { DenseMap<size_t, DenseSet<size_t>> RecordProvenance; std::vector<FunctionRecord> Functions; + DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices; std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; CoverageMapping() = default; @@ -516,6 +522,13 @@ class CoverageMapping { Error loadFunctionRecord(const CoverageMappingRecord &Record, IndexedInstrProfReader &ProfileReader); + /// Look up the indices for function records which are at least partially + /// defined in the specified file. This is guaranteed to return a superset of + /// such records: extra records not in the file may be included if there is + /// a hash collision on the filename. Clients must be robust to collisions. + ArrayRef<unsigned> + getImpreciseRecordIndicesForFilename(StringRef Filename) const; + public: CoverageMapping(const CoverageMapping &) = delete; CoverageMapping &operator=(const CoverageMapping &) = delete; diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 803605cd79f..8d5e56e26c0 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -194,6 +194,15 @@ void FunctionRecordIterator::skipOtherFiles() { *this = FunctionRecordIterator(); } +ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename( + StringRef Filename) const { + size_t FilenameHash = hash_value(Filename); + auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash); + if (RecordIt == FilenameHash2RecordIndices.end()) + return {}; + return RecordIt->second; +} + Error CoverageMapping::loadFunctionRecord( const CoverageMappingRecord &Record, IndexedInstrProfReader &ProfileReader) { @@ -249,6 +258,20 @@ Error CoverageMapping::loadFunctionRecord( return Error::success(); Functions.push_back(std::move(Function)); + + // Performance optimization: keep track of the indices of the function records + // which correspond to each filename. This can be used to substantially speed + // up queries for coverage info in a file. + unsigned RecordIndex = Functions.size() - 1; + for (StringRef Filename : Record.Filenames) { + auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)]; + // Note that there may be duplicates in the filename set for a function + // record, because of e.g. macro expansions in the function in which both + // the macro and the function are defined in the same file. + if (RecordIndices.empty() || RecordIndices.back() != RecordIndex) + RecordIndices.push_back(RecordIndex); + } + return Error::success(); } @@ -626,7 +649,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { CoverageData FileCoverage(Filename); std::vector<CountedRegion> Regions; - for (const auto &Function : Functions) { + // Look up the function records in the given file. Due to hash collisions on + // the filename, we may get back some records that are not in the file. + ArrayRef<unsigned> RecordIndices = + getImpreciseRecordIndicesForFilename(Filename); + for (unsigned RecordIndex : RecordIndices) { + const FunctionRecord &Function = Functions[RecordIndex]; auto MainFileID = findMainViewFileID(Filename, Function); auto FileIDs = gatherFileIDs(Filename, Function); for (const auto &CR : Function.CountedRegions) @@ -646,7 +674,12 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { std::vector<InstantiationGroup> CoverageMapping::getInstantiationGroups(StringRef Filename) const { FunctionInstantiationSetCollector InstantiationSetCollector; - for (const auto &Function : Functions) { + // Look up the function records in the given file. Due to hash collisions on + // the filename, we may get back some records that are not in the file. + ArrayRef<unsigned> RecordIndices = + getImpreciseRecordIndicesForFilename(Filename); + for (unsigned RecordIndex : RecordIndices) { + const FunctionRecord &Function = Functions[RecordIndex]; auto MainFileID = findMainViewFileID(Filename, Function); if (!MainFileID) continue; |

