-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Coverage] Improve performance of propagating Counter of Expansions #122589
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -36,6 +36,7 @@ | |||||||
#include "llvm/Support/Path.h" | ||||||||
#include "llvm/Support/raw_ostream.h" | ||||||||
#include "llvm/TargetParser/Triple.h" | ||||||||
#include <limits> | ||||||||
#include <vector> | ||||||||
|
||||||||
using namespace llvm; | ||||||||
|
@@ -440,26 +441,83 @@ Error RawCoverageMappingReader::read() { | |||||||
// Set the counters for the expansion regions. | ||||||||
// i.e. Counter of expansion region = counter of the first region | ||||||||
// from the expanded file. | ||||||||
// Perform multiple passes to correctly propagate the counters through | ||||||||
// all the nested expansion regions. | ||||||||
SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; | ||||||||
FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); | ||||||||
for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { | ||||||||
for (auto &R : MappingRegions) { | ||||||||
if (R.Kind != CounterMappingRegion::ExpansionRegion) | ||||||||
continue; | ||||||||
assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); | ||||||||
FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; | ||||||||
// This assumes: | ||||||||
// - Records are partitioned by FileID. | ||||||||
// - The Count in Expansion is propagated from 1st Record in | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e.g. nth record's count == n-1th count + n-2th count ... 0th count? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for my less descriptive explanation. "1st (the top) Record in the cluster that is defined by FileID, that is referred with ExpandedFileID". |
||||||||
// ExpandedFileID. | ||||||||
// Therefore another fact below can be assumed. | ||||||||
// - Propagation chain consists of Expansions at each 1st Record. | ||||||||
|
||||||||
/// Node per File. | ||||||||
struct FileNode { | ||||||||
/// 1st Record in the File. | ||||||||
CounterMappingRegion *FirstR = nullptr; | ||||||||
/// The Expansion Record out of this File. | ||||||||
CounterMappingRegion *ExpanderR = nullptr; | ||||||||
/// Count hasn't been propagated yet (for Expansion) | ||||||||
bool ExpansionPending = false; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Maybe more descriptive? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like leave it "true as marked". Or |
||||||||
}; | ||||||||
SmallVector<FileNode> FileIDExpansionRegionMapping(VirtualFileMapping.size()); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Add a comment explaining what we're going to do with this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also what will the edges in the tree be? That's not clear to me right now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can I rename the name shorter and add more descriptions instead of the object? |
||||||||
|
||||||||
// Construct the tree. | ||||||||
auto PrevFileID = std::numeric_limits<unsigned>::max(); // Invalid value | ||||||||
for (auto &R : MappingRegions) { | ||||||||
if (R.Kind == CounterMappingRegion::ExpansionRegion) { | ||||||||
// The File that contains Expansion may be a node. | ||||||||
assert(!FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this checking that there is only one expansion region? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Expander" means "Expansion Region in other nodes". ExpandedFileID is unique in the current impl. |
||||||||
FileIDExpansionRegionMapping[R.ExpandedFileID].ExpanderR = &R; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be slightly cleaner to pull this out into a reference variable? E.g.
|
||||||||
|
||||||||
// It will be the node if (isExpansion and ExpansionPending). | ||||||||
FileIDExpansionRegionMapping[R.ExpandedFileID].ExpansionPending = true; | ||||||||
} | ||||||||
for (auto &R : MappingRegions) { | ||||||||
if (FileIDExpansionRegionMapping[R.FileID]) { | ||||||||
FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; | ||||||||
FileIDExpansionRegionMapping[R.FileID] = nullptr; | ||||||||
} | ||||||||
|
||||||||
if (PrevFileID != R.FileID) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can reduce indentation here.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me think restructuring this. |
||||||||
// Record 1st Record for each File. | ||||||||
assert(!FileIDExpansionRegionMapping[R.FileID].FirstR); | ||||||||
FileIDExpansionRegionMapping[R.FileID].FirstR = &R; | ||||||||
PrevFileID = R.FileID; | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
return Error::success(); | ||||||||
auto Propagate = [&](FileNode &X) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a lambda and not a function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not a lambda? I prefer using a lambda as definition of subfunction that shares the context. I could abandon serpentine seek just to get rid of the lambda. I don't want to introduce another method here. |
||||||||
// Skip already processed node. | ||||||||
if (!X.ExpanderR) | ||||||||
return false; | ||||||||
// Skip Pending Expansion node. | ||||||||
// Process non-Expansion Record and non-Pending Expansion. | ||||||||
if (X.ExpansionPending && | ||||||||
X.FirstR->Kind == CounterMappingRegion::ExpansionRegion) | ||||||||
return false; | ||||||||
|
||||||||
// Propagate. | ||||||||
X.ExpanderR->Count = X.FirstR->Count; | ||||||||
// Mark the destination ready. | ||||||||
FileIDExpansionRegionMapping[X.ExpanderR->FileID].ExpansionPending = false; | ||||||||
// Mark this processed. | ||||||||
X.ExpanderR = nullptr; | ||||||||
return true; | ||||||||
}; | ||||||||
|
||||||||
// This won't iterate in most cases but iterates finitely for | ||||||||
// unusual cases. | ||||||||
for (unsigned I = 0, E = FileIDExpansionRegionMapping.size(); I != E; ++I) { | ||||||||
// Propagate Descending. All Files will be processed if each | ||||||||
// ExpandedFileID is greater than FileID. | ||||||||
for (auto &X : reverse(FileIDExpansionRegionMapping)) | ||||||||
Propagate(X); | ||||||||
|
||||||||
// Check whether all Files are processed (or propagate Ascending, | ||||||||
// not possible in the usual assumptions). | ||||||||
bool Changed = false; | ||||||||
for (auto &X : FileIDExpansionRegionMapping) | ||||||||
Changed = (Propagate(X) || Changed); | ||||||||
|
||||||||
if (!Changed) | ||||||||
return Error::success(); | ||||||||
} | ||||||||
|
||||||||
return make_error<CoverageMapError>(coveragemap_error::malformed, | ||||||||
"unexpected Expansions"); | ||||||||
} | ||||||||
|
||||||||
Expected<bool> RawCoverageMappingDummyChecker::isDummy() { | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.g. no record is a part of two different files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each FIleID should have at least one record, since FileID is defied by Record.
Actually the Record is sorted by FileID in CoverageMappingWriter.