Skip to content

Commit ebcd68e

Browse files
author
Andres Wearden
committed
fixed issues with time complexity and region counts
1 parent bea56b9 commit ebcd68e

File tree

8 files changed

+147
-286
lines changed

8 files changed

+147
-286
lines changed

llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,16 @@ struct FunctionRecord {
748748
FunctionRecord(FunctionRecord &&FR) = default;
749749
FunctionRecord &operator=(FunctionRecord &&) = default;
750750

751+
FunctionRecord(const FunctionRecord &FR)
752+
: Name(FR.Name),
753+
Filenames(FR.Filenames),
754+
CountedRegions(FR.CountedRegions),
755+
CountedBranchRegions(FR.CountedBranchRegions),
756+
MCDCRecords(FR.MCDCRecords),
757+
ExecutionCount(FR.ExecutionCount),
758+
ObjectFilename(FR.ObjectFilename) {}
759+
760+
751761
void pushMCDCRecord(MCDCRecord &&Record) {
752762
MCDCRecords.push_back(std::move(Record));
753763
}
@@ -1006,7 +1016,9 @@ class CoverageMapping {
10061016
std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
10071017
StringRef Arch;
10081018
DenseMap<std::pair<size_t, hash_code>, unsigned> RecordIndices;
1009-
uint64_t Counter = 0;
1019+
uint64_t DebugCount = 0;
1020+
std::vector<FunctionRecord> AllFunctionRegions;
1021+
10101022

10111023
std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> AggregatedCounts;
10121024

@@ -1103,7 +1115,7 @@ class CoverageMapping {
11031115
/// The given filename must be the name as recorded in the coverage
11041116
/// information. That is, only names returned from getUniqueSourceFiles will
11051117
/// yield a result.
1106-
LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const;
1118+
LLVM_ABI CoverageData getCoverageForFile(StringRef Filename, bool ShowArchExecutables = false) const;
11071119

11081120
/// Get the coverage for a particular function.
11091121
LLVM_ABI CoverageData

llvm/lib/ProfileData/Coverage/CoverageMapping.cpp

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
1515
#include "llvm/ADT/ArrayRef.h"
1616
#include "llvm/ADT/DenseMap.h"
17+
#include "llvm/ADT/DenseSet.h"
1718
#include "llvm/ADT/STLExtras.h"
1819
#include "llvm/ADT/SmallBitVector.h"
1920
#include "llvm/ADT/SmallVector.h"
@@ -23,10 +24,12 @@
2324
#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
2425
#include "llvm/ProfileData/InstrProfReader.h"
2526
#include "llvm/Support/Debug.h"
27+
#include "llvm/Support/DebugCounter.h"
2628
#include "llvm/Support/Errc.h"
2729
#include "llvm/Support/Error.h"
2830
#include "llvm/Support/ErrorHandling.h"
2931
#include "llvm/Support/MemoryBuffer.h"
32+
#include "llvm/Support/ScopedPrinter.h"
3033
#include "llvm/Support/VirtualFileSystem.h"
3134
#include "llvm/Support/raw_ostream.h"
3235
#include <algorithm>
@@ -1106,39 +1109,74 @@ Error CoverageMapping::loadFunctionRecord(
11061109
if(ShowArchExecutables){
11071110
HashStr += ":" + Arch.str();
11081111
}else{
1112+
//THIS ALGORITHM NEEDS TO BE FIXED!!!
11091113
auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
11101114
auto It = RecordIndices.find(LogicalFuncKey);
1111-
std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
11121115

11131116
if (It != RecordIndices.end()) {
11141117
auto &ExistingFunction = Functions[It->second];
11151118

1116-
// Step 1: Build a set of existing ObjectFilenames
1117-
std::unordered_set<std::string> ExistingFilenames;
1118-
for (const auto &ExistingRegion : ExistingFunction.CountedRegions) {
1119-
ExistingFilenames.insert(ExistingRegion.ObjectFilename.str());
1119+
1120+
// Create a map of existing regions for efficient lookup.
1121+
// The key uniquely identifies the source region.
1122+
using RegionKey = std::tuple<unsigned, unsigned, unsigned, unsigned, unsigned>;
1123+
std::map<RegionKey, CountedRegion *> ExistingRegionsMap;
1124+
for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
1125+
RegionKey Key = {ExistingRegion.FileID, ExistingRegion.LineStart,
1126+
ExistingRegion.ColumnStart, ExistingRegion.LineEnd,
1127+
ExistingRegion.ColumnEnd};
1128+
ExistingRegionsMap[Key] = &ExistingRegion;
1129+
}
1130+
1131+
for (auto NewRegion : Function.CountedRegions) {
1132+
AllFunctionRegions[It->second].CountedRegions.push_back(NewRegion);
11201133
}
11211134

1122-
// Step 2: Only add NewRegions with unique ObjectFilenames
1135+
// Merge the new regions into the existing function's regions.
11231136
for (const auto &NewRegion : Function.CountedRegions) {
1124-
if (ExistingFilenames.find(NewRegion.ObjectFilename.str()) == ExistingFilenames.end()) {
1137+
RegionKey Key = {NewRegion.FileID, NewRegion.LineStart,
1138+
NewRegion.ColumnStart, NewRegion.LineEnd,
1139+
NewRegion.ColumnEnd};
1140+
auto MapIt = ExistingRegionsMap.find(Key);
1141+
if (MapIt != ExistingRegionsMap.end()) {
1142+
// Region already exists, merge counts by taking the max.
1143+
CountedRegion *ExistingRegion = MapIt->second;
1144+
// llvm::errs() << "EXECUTION COUNTS BEFORE: " + to_string(ExistingRegion->ExecutionCount) << "\n";
1145+
// llvm::errs() << "(" << ExistingRegion->LineStart << ", " << ExistingRegion->LineEnd << ")" << "\n";
1146+
ExistingRegion->ExecutionCount += NewRegion.ExecutionCount;
1147+
// llvm::errs() << "EXECUTION COUNTS AFTER: " + to_string(ExistingRegion->ExecutionCount) << "\n";
1148+
// DebugCount++;
1149+
} else {
1150+
// llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
1151+
// llvm::errs() << "(" << NewRegion.LineStart << ", " << NewRegion.LineEnd << ")" << "\n";
11251152
ExistingFunction.CountedRegions.push_back(NewRegion);
11261153
}
1127-
11281154
}
1155+
// Since we modified an existing function, we don't add a new one.
1156+
// We just need to make sure we don't add the new 'Function' object later.
1157+
// The logic below this block needs to be adjusted to handle this.
1158+
return Error::success();
11291159
}
1130-
RecordIndices[LogicalFuncKey] = Functions.size();
1160+
// llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
1161+
RecordIndices.insert({LogicalFuncKey, Functions.size()});
1162+
//THIS ALGORITHM NEEDS TO BE FIXED!!!
11311163
}
11321164
//CHANGES MADE HERE
11331165

1166+
// if(DebugCount == 29){
1167+
// llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
1168+
// }
1169+
1170+
1171+
11341172
// Don't create records for (filenames, function) pairs we've already seen.
11351173
StringRef Hash(HashStr);
11361174
if (!RecordProvenance[FilenamesHash].insert(hash_value(Hash)).second){
11371175
return Error::success();
11381176
}
11391177

1178+
AllFunctionRegions.push_back(Function);
11401179
Functions.push_back(std::move(Function));
1141-
11421180
// Performance optimization: keep track of the indices of the function records
11431181
// which correspond to each filename. This can be used to substantially speed
11441182
// up queries for coverage info in a file.
@@ -1594,13 +1632,67 @@ class SegmentBuilder {
15941632

15951633
sortNestedRegions(Regions);
15961634

1635+
// // This map is used to efficiently check for the existence of a specific region
1636+
// // from a specific binary, which is the purpose of the innermost loop in the
1637+
// // original code.
1638+
// // Key: A tuple uniquely identifying a region's location and its binary of origin.
1639+
// // Value: A boolean indicating if the region is NOT a SkippedRegion.
1640+
// using RegionKey = std::tuple<LineColPair, LineColPair, StringRef>;
1641+
// std::map<RegionKey, bool> RegionExistenceMap;
1642+
// for (const auto &R : Regions) {
1643+
// RegionKey Key = {R.startLoc(), R.endLoc(), R.ObjectFilename};
1644+
// // Only insert if it's a more "valid" region than what might already be there.
1645+
// if (R.Kind != CounterMappingRegion::SkippedRegion)
1646+
// RegionExistenceMap[Key] = true;
1647+
// else
1648+
// RegionExistenceMap.try_emplace(Key, false);
1649+
// }
1650+
1651+
// for (auto &I : Regions) {
1652+
// // We are only interested in patching SkippedRegions.
1653+
// if (I.Kind != CounterMappingRegion::SkippedRegion)
1654+
// continue;
1655+
1656+
// for (auto &J : Regions) {
1657+
// // Find a non-skipped region 'J' from a different binary that contains 'I'.
1658+
// if (I.ObjectFilename == J.ObjectFilename ||
1659+
// J.Kind == CounterMappingRegion::SkippedRegion ||
1660+
// !(I.startLoc() >= J.startLoc() && I.endLoc() <= J.endLoc())) {
1661+
// continue;
1662+
// }
1663+
1664+
// // Check if a non-skipped region already exists at I's exact location
1665+
// // coming from J's binary. This replaces the O(N) inner loop.
1666+
// RegionKey KeyToFind = {I.startLoc(), I.endLoc(), J.ObjectFilename};
1667+
// auto It = RegionExistenceMap.find(KeyToFind);
1668+
1669+
// // If no region from J's binary exists at I's location, or if it does
1670+
// // but it's a SkippedRegion, we can patch I with J's data.
1671+
// if (It == RegionExistenceMap.end() || It->second == false) {
1672+
// I.Kind = J.Kind;
1673+
// I.ExecutionCount = J.ExecutionCount;
1674+
// // We found a patch, no need to check other containing regions.
1675+
// break;
1676+
// }
1677+
// }
1678+
// }
1679+
1680+
// llvm::errs() << "START HERE" << "\n";
1681+
// for(auto *I = Regions.begin(); I != Regions.end(); ++I){
1682+
// llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
1683+
// llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
1684+
// }
1685+
// llvm::errs() << "END HERE" << "\n";
1686+
1687+
15971688
for(auto *I = Regions.begin(); I != Regions.end(); ++I){
15981689
bool FoundMatchInOtherBinary = false;
15991690
for(auto *J = I + 1; J != Regions.end(); ++J){
16001691
if(I->ObjectFilename != J->ObjectFilename &&
16011692
J->Kind == CounterMappingRegion::SkippedRegion
16021693
&& I->Kind != CounterMappingRegion::SkippedRegion &&
16031694
J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()){
1695+
// llvm::errs() << "(" << to_string(J->startLoc().first) << ", " << to_string(J->endLoc().first) << ")" << "\n";
16041696
for(auto *K = J + 1; K != Regions.end(); ++K){
16051697
if(K->ObjectFilename == I->ObjectFilename &&
16061698
J->startLoc() == K->startLoc() && J->endLoc() == K->endLoc()){
@@ -1614,6 +1706,13 @@ class SegmentBuilder {
16141706
}
16151707
}
16161708
}
1709+
1710+
// llvm::errs() << "START HERE" << "\n";
1711+
// for(auto *I = Regions.begin(); I != Regions.end(); ++I){
1712+
// llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
1713+
// llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
1714+
// }
1715+
// llvm::errs() << "END HERE" << "\n";
16171716

16181717

16191718
ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
@@ -1671,9 +1770,15 @@ static SmallBitVector gatherFileIDs(StringRef SourceFile,
16711770
static std::optional<unsigned>
16721771
findMainViewFileID(const FunctionRecord &Function) {
16731772
SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
1674-
for (const auto &CR : Function.CountedRegions)
1773+
uint64_t counter = 0;
1774+
for (const auto &CR : Function.CountedRegions){
1775+
// counter++;
1776+
// if(counter == 245){
1777+
// llvm::errs() << counter << "\n";
1778+
// }
16751779
if (CR.Kind == CounterMappingRegion::ExpansionRegion)
16761780
IsNotExpandedFile[CR.ExpandedFileID] = false;
1781+
}
16771782
int I = IsNotExpandedFile.find_first();
16781783
if (I == -1)
16791784
return std::nullopt;
@@ -1695,17 +1800,26 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
16951800
return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
16961801
}
16971802

1698-
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
1803+
CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowArchExecutables) const {
16991804
assert(SingleByteCoverage);
17001805
CoverageData FileCoverage(*SingleByteCoverage, Filename);
17011806
std::vector<CountedRegion> Regions;
17021807

17031808
// Look up the function records in the given file. Due to hash collisions on
17041809
// the filename, we may get back some records that are not in the file.
1810+
// DenseSet<CountedRegion> DeDuplicationSet;
17051811
ArrayRef<unsigned> RecordIndices =
17061812
getImpreciseRecordIndicesForFilename(Filename);
1813+
// for (unsigned RecordIndex : RecordIndices) {
1814+
// const FunctionRecord &Function = AllFunctionRegions[RecordIndex];
1815+
// for(const auto &I : Function.CountedRegions){
1816+
// llvm::errs() << "(" << to_string(I.startLoc().first) << ", " << to_string(I.endLoc().first) << ")" << "\n";
1817+
// }
1818+
// }
1819+
// ArrayRef<unsigned> RecordIndices =
1820+
// getImpreciseRecordIndicesForFilename(Filename);
17071821
for (unsigned RecordIndex : RecordIndices) {
1708-
const FunctionRecord &Function = Functions[RecordIndex];
1822+
const FunctionRecord &Function = ShowArchExecutables ? Functions[RecordIndex] : AllFunctionRegions[RecordIndex];
17091823
auto MainFileID = findMainViewFileID(Filename, Function);
17101824
auto FileIDs = gatherFileIDs(Filename, Function);
17111825
for (const auto &CR : Function.CountedRegions)
@@ -1724,6 +1838,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
17241838
FileCoverage.MCDCRecords.push_back(MR);
17251839
}
17261840

1841+
1842+
17271843
LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
17281844
FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
17291845

llvm/tools/llvm-cov/CodeCoverage.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
3030
#include "llvm/ProfileData/InstrProfReader.h"
3131
#include "llvm/Support/CommandLine.h"
32+
#include "llvm/Support/DebugCounter.h"
3233
#include "llvm/Support/FileSystem.h"
3334
#include "llvm/Support/Format.h"
3435
#include "llvm/Support/MemoryBuffer.h"
@@ -396,7 +397,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
396397
auto SourceBuffer = getSourceFile(SourceFile);
397398
if (!SourceBuffer)
398399
return nullptr;
399-
auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
400+
auto FileCoverage = Coverage.getCoverageForFile(SourceFile, ViewOpts.ShowArchExecutables);
400401
if (FileCoverage.empty())
401402
return nullptr;
402403

llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)