14
14
#include " llvm/ProfileData/Coverage/CoverageMapping.h"
15
15
#include " llvm/ADT/ArrayRef.h"
16
16
#include " llvm/ADT/DenseMap.h"
17
+ #include " llvm/ADT/DenseSet.h"
17
18
#include " llvm/ADT/STLExtras.h"
18
19
#include " llvm/ADT/SmallBitVector.h"
19
20
#include " llvm/ADT/SmallVector.h"
23
24
#include " llvm/ProfileData/Coverage/CoverageMappingReader.h"
24
25
#include " llvm/ProfileData/InstrProfReader.h"
25
26
#include " llvm/Support/Debug.h"
27
+ #include " llvm/Support/DebugCounter.h"
26
28
#include " llvm/Support/Errc.h"
27
29
#include " llvm/Support/Error.h"
28
30
#include " llvm/Support/ErrorHandling.h"
29
31
#include " llvm/Support/MemoryBuffer.h"
32
+ #include " llvm/Support/ScopedPrinter.h"
30
33
#include " llvm/Support/VirtualFileSystem.h"
31
34
#include " llvm/Support/raw_ostream.h"
32
35
#include < algorithm>
@@ -1106,39 +1109,74 @@ Error CoverageMapping::loadFunctionRecord(
1106
1109
if (ShowArchExecutables){
1107
1110
HashStr += " :" + Arch.str ();
1108
1111
}else {
1112
+ // THIS ALGORITHM NEEDS TO BE FIXED!!!
1109
1113
auto LogicalFuncKey = std::make_pair (FilenamesHash, hash_value (OrigFuncName));
1110
1114
auto It = RecordIndices.find (LogicalFuncKey);
1111
- std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
1112
1115
1113
1116
if (It != RecordIndices.end ()) {
1114
1117
auto &ExistingFunction = Functions[It->second ];
1115
1118
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);
1120
1133
}
1121
1134
1122
- // Step 2: Only add NewRegions with unique ObjectFilenames
1135
+ // Merge the new regions into the existing function's regions.
1123
1136
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";
1125
1152
ExistingFunction.CountedRegions .push_back (NewRegion);
1126
1153
}
1127
-
1128
1154
}
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 ();
1129
1159
}
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!!!
1131
1163
}
1132
1164
// CHANGES MADE HERE
1133
1165
1166
+ // if(DebugCount == 29){
1167
+ // llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
1168
+ // }
1169
+
1170
+
1171
+
1134
1172
// Don't create records for (filenames, function) pairs we've already seen.
1135
1173
StringRef Hash (HashStr);
1136
1174
if (!RecordProvenance[FilenamesHash].insert (hash_value (Hash)).second ){
1137
1175
return Error::success ();
1138
1176
}
1139
1177
1178
+ AllFunctionRegions.push_back (Function);
1140
1179
Functions.push_back (std::move (Function));
1141
-
1142
1180
// Performance optimization: keep track of the indices of the function records
1143
1181
// which correspond to each filename. This can be used to substantially speed
1144
1182
// up queries for coverage info in a file.
@@ -1594,13 +1632,67 @@ class SegmentBuilder {
1594
1632
1595
1633
sortNestedRegions (Regions);
1596
1634
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
+
1597
1688
for (auto *I = Regions.begin (); I != Regions.end (); ++I){
1598
1689
bool FoundMatchInOtherBinary = false ;
1599
1690
for (auto *J = I + 1 ; J != Regions.end (); ++J){
1600
1691
if (I->ObjectFilename != J->ObjectFilename &&
1601
1692
J->Kind == CounterMappingRegion::SkippedRegion
1602
1693
&& I->Kind != CounterMappingRegion::SkippedRegion &&
1603
1694
J->startLoc () >= I->startLoc () && J->endLoc () <= I->endLoc ()){
1695
+ // llvm::errs() << "(" << to_string(J->startLoc().first) << ", " << to_string(J->endLoc().first) << ")" << "\n";
1604
1696
for (auto *K = J + 1 ; K != Regions.end (); ++K){
1605
1697
if (K->ObjectFilename == I->ObjectFilename &&
1606
1698
J->startLoc () == K->startLoc () && J->endLoc () == K->endLoc ()){
@@ -1614,6 +1706,13 @@ class SegmentBuilder {
1614
1706
}
1615
1707
}
1616
1708
}
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";
1617
1716
1618
1717
1619
1718
ArrayRef<CountedRegion> CombinedRegions = combineRegions (Regions);
@@ -1671,9 +1770,15 @@ static SmallBitVector gatherFileIDs(StringRef SourceFile,
1671
1770
static std::optional<unsigned >
1672
1771
findMainViewFileID (const FunctionRecord &Function) {
1673
1772
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
+ // }
1675
1779
if (CR.Kind == CounterMappingRegion::ExpansionRegion)
1676
1780
IsNotExpandedFile[CR.ExpandedFileID ] = false ;
1781
+ }
1677
1782
int I = IsNotExpandedFile.find_first ();
1678
1783
if (I == -1 )
1679
1784
return std::nullopt;
@@ -1695,17 +1800,26 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
1695
1800
return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
1696
1801
}
1697
1802
1698
- CoverageData CoverageMapping::getCoverageForFile (StringRef Filename) const {
1803
+ CoverageData CoverageMapping::getCoverageForFile (StringRef Filename, bool ShowArchExecutables ) const {
1699
1804
assert (SingleByteCoverage);
1700
1805
CoverageData FileCoverage (*SingleByteCoverage, Filename);
1701
1806
std::vector<CountedRegion> Regions;
1702
1807
1703
1808
// Look up the function records in the given file. Due to hash collisions on
1704
1809
// the filename, we may get back some records that are not in the file.
1810
+ // DenseSet<CountedRegion> DeDuplicationSet;
1705
1811
ArrayRef<unsigned > RecordIndices =
1706
1812
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);
1707
1821
for (unsigned RecordIndex : RecordIndices) {
1708
- const FunctionRecord &Function = Functions[RecordIndex];
1822
+ const FunctionRecord &Function = ShowArchExecutables ? Functions[RecordIndex] : AllFunctionRegions [RecordIndex];
1709
1823
auto MainFileID = findMainViewFileID (Filename, Function);
1710
1824
auto FileIDs = gatherFileIDs (Filename, Function);
1711
1825
for (const auto &CR : Function.CountedRegions )
@@ -1724,6 +1838,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
1724
1838
FileCoverage.MCDCRecords .push_back (MR);
1725
1839
}
1726
1840
1841
+
1842
+
1727
1843
LLVM_DEBUG (dbgs () << " Emitting segments for file: " << Filename << " \n " );
1728
1844
FileCoverage.Segments = SegmentBuilder::buildSegments (Regions);
1729
1845
0 commit comments