Skip to content

Commit 67909c0

Browse files
authored
Merge pull request #62418 from hamishknight/qwoops
2 parents 19742ba + 6d3545f commit 67909c0

File tree

12 files changed

+119
-46
lines changed

12 files changed

+119
-46
lines changed

include/swift/SIL/SILCoverageMap.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ class SILCoverageMap : public llvm::ilist_node<SILCoverageMap>,
5555
};
5656

5757
private:
58+
/// The parent source file containing the coverage map.
59+
///
60+
/// NOTE: `ParentSourceFile->getFilename()` is not necessarily equivalent to
61+
/// `Filename`. `Filename` could be a .swift file, and `ParentSourceFile`
62+
/// could be a parsed .sil file. As such, this should only be used for
63+
/// determining which object file to emit the coverage map into.
64+
/// `Filename` should be used for coverage data.
65+
SourceFile *ParentSourceFile;
66+
5867
// The name of the source file where this mapping is found.
5968
StringRef Filename;
6069

@@ -78,19 +87,28 @@ class SILCoverageMap : public llvm::ilist_node<SILCoverageMap>,
7887
SILCoverageMap &operator=(const SILCoverageMap &) = delete;
7988

8089
/// Private constructor. Create these using SILCoverageMap::create.
81-
SILCoverageMap(uint64_t Hash);
90+
SILCoverageMap(SourceFile *ParentSourceFile, uint64_t Hash);
8291

8392
public:
8493
~SILCoverageMap();
8594

8695
static SILCoverageMap *
87-
create(SILModule &M, StringRef Filename, StringRef Name,
88-
StringRef PGOFuncName, uint64_t Hash,
96+
create(SILModule &M, SourceFile *ParentSourceFile, StringRef Filename,
97+
StringRef Name, StringRef PGOFuncName, uint64_t Hash,
8998
ArrayRef<MappedRegion> MappedRegions,
9099
ArrayRef<llvm::coverage::CounterExpression> Expressions);
91100

101+
/// The parent source file containing the coverage map.
102+
///
103+
/// NOTE: `getParentSourceFile()->getFilename()` is not necessarily equivalent
104+
/// to `getFilename()`. `getFilename()` could be a .swift file, and
105+
/// `getParentSourceFile()` could be a parsed .sil file. As such, this should
106+
/// only be used for determining which object file to emit the coverage map
107+
/// in. `getFilename()` should be used for coverage data.
108+
SourceFile *getParentSourceFile() const { return ParentSourceFile; }
109+
92110
/// Return the name of the source file where this mapping is found.
93-
StringRef getFile() const { return Filename; }
111+
StringRef getFilename() const { return Filename; }
94112

95113
/// Return the mangled name of the function this mapping covers.
96114
StringRef getName() const { return Name; }

lib/IRGen/GenCoverage.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,14 @@ static std::string getInstrProfSection(IRGenModule &IGM,
4242
return llvm::getInstrProfSectionName(SK, IGM.Triple.getObjectFormat());
4343
}
4444

45-
void IRGenModule::emitCoverageMapping() {
45+
void IRGenModule::emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings) {
46+
// If there aren't any coverage maps, there's nothing to emit.
47+
if (Mappings.empty())
48+
return;
49+
4650
SmallVector<llvm::Constant *, 4> UnusedFuncNames;
47-
std::vector<const SILCoverageMap *> Mappings;
48-
for (const auto &M : getSILModule().getCoverageMaps()) {
49-
auto FuncName = M.second->getPGOFuncName();
51+
for (const auto *Mapping : Mappings) {
52+
auto FuncName = Mapping->getPGOFuncName();
5053
auto VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
5154
auto FuncNameVarName = llvm::getPGOFuncNameVarName(FuncName, VarLinkage);
5255

@@ -58,13 +61,8 @@ void IRGenModule::emitCoverageMapping() {
5861
auto *Var = llvm::createPGOFuncNameVar(Module, VarLinkage, FuncName);
5962
UnusedFuncNames.push_back(llvm::ConstantExpr::getBitCast(Var, Int8PtrTy));
6063
}
61-
Mappings.push_back(M.second);
6264
}
6365

64-
// If there aren't any coverage maps, there's nothing to emit.
65-
if (Mappings.empty())
66-
return;
67-
6866
// Emit the name data for any unused functions.
6967
if (!UnusedFuncNames.empty()) {
7068
auto NamePtrsTy = llvm::ArrayType::get(Int8PtrTy, UnusedFuncNames.size());
@@ -80,8 +78,8 @@ void IRGenModule::emitCoverageMapping() {
8078

8179
std::vector<StringRef> Files;
8280
for (const auto &M : Mappings)
83-
if (std::find(Files.begin(), Files.end(), M->getFile()) == Files.end())
84-
Files.push_back(M->getFile());
81+
if (std::find(Files.begin(), Files.end(), M->getFilename()) == Files.end())
82+
Files.push_back(M->getFilename());
8583

8684
auto remapper = getOptions().CoveragePrefixMap;
8785

@@ -115,7 +113,7 @@ void IRGenModule::emitCoverageMapping() {
115113
std::string FuncRecordName = "__covrec_" + llvm::utohexstr(NameHash);
116114

117115
unsigned FileID =
118-
std::find(Files.begin(), Files.end(), M->getFile()) - Files.begin();
116+
std::find(Files.begin(), Files.end(), M->getFilename()) - Files.begin();
119117
std::vector<CounterMappingRegion> Regions;
120118
for (const auto &MR : M->getMappedRegions())
121119
Regions.emplace_back(CounterMappingRegion::makeRegion(
@@ -194,6 +192,27 @@ void IRGenModule::emitCoverageMapping() {
194192
}
195193

196194
void IRGenerator::emitCoverageMapping() {
197-
for (auto &IGM : *this)
198-
IGM.second->emitCoverageMapping();
195+
if (SIL.getCoverageMaps().empty())
196+
return;
197+
198+
// Shard the coverage maps across their designated IRGenModules. This is
199+
// necessary to ensure we don't output N copies of a coverage map when doing
200+
// parallel IRGen, where N is the number of output object files.
201+
//
202+
// Note we don't just dump all the coverage maps into the primary IGM as
203+
// that would require creating unecessary name data entries, since the name
204+
// data is likely to already be present in the IGM that contains the entity
205+
// being profiled (unless it has been optimized out). Matching the coverage
206+
// map to its originating SourceFile also matches the behavior of a debug
207+
// build where the files are compiled separately.
208+
llvm::DenseMap<IRGenModule *, std::vector<const SILCoverageMap *>> MapsToEmit;
209+
for (const auto &M : SIL.getCoverageMaps()) {
210+
auto &Mapping = M.second;
211+
auto *SF = Mapping->getParentSourceFile();
212+
MapsToEmit[getGenModule(SF)].push_back(Mapping);
213+
}
214+
for (auto &IGMPair : *this) {
215+
auto *IGM = IGMPair.second;
216+
IGM->emitCoverageMaps(MapsToEmit[IGM]);
217+
}
199218
}

lib/IRGen/IRGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
13691369
// Emit coverage mapping info. This needs to happen after we've emitted
13701370
// any lazy definitions, as we need to know whether or not we emitted a
13711371
// profiler increment for a given coverage map.
1372-
IGM.emitCoverageMapping();
1372+
irgen.emitCoverageMapping();
13731373

13741374
// Emit symbols for eliminated dead methods.
13751375
IGM.emitVTableStubs();

lib/IRGen/IRGenModule.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,17 @@ void IRGenerator::addGenModule(SourceFile *SF, IRGenModule *IGM) {
18921892
Queue.push_back(IGM);
18931893
}
18941894

1895+
IRGenModule *IRGenerator::getGenModule(SourceFile *SF) {
1896+
// If we're emitting for a single module, or a single file, we always use the
1897+
// primary IGM.
1898+
if (GenModules.size() == 1)
1899+
return getPrimaryIGM();
1900+
1901+
IRGenModule *IGM = GenModules[SF];
1902+
assert(IGM);
1903+
return IGM;
1904+
}
1905+
18951906
IRGenModule *IRGenerator::getGenModule(DeclContext *ctxt) {
18961907
if (GenModules.size() == 1 || !ctxt) {
18971908
return getPrimaryIGM();

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ namespace swift {
104104
class ProtocolConformance;
105105
class ProtocolCompositionType;
106106
class RootProtocolConformance;
107+
class SILCoverageMap;
107108
struct SILDeclRef;
108109
class SILDefaultWitnessTable;
109110
class SILDifferentiabilityWitness;
@@ -350,11 +351,7 @@ class IRGenerator {
350351
void addGenModule(SourceFile *SF, IRGenModule *IGM);
351352

352353
/// Get an IRGenModule for a source file.
353-
IRGenModule *getGenModule(SourceFile *SF) {
354-
IRGenModule *IGM = GenModules[SF];
355-
assert(IGM);
356-
return IGM;
357-
}
354+
IRGenModule *getGenModule(SourceFile *SF);
358355

359356
SourceFile *getSourceFile(IRGenModule *module) {
360357
for (auto pair : GenModules) {
@@ -1481,7 +1478,7 @@ private: \
14811478
void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *D);
14821479

14831480
void emitSILGlobalVariable(SILGlobalVariable *gv);
1484-
void emitCoverageMapping();
1481+
void emitCoverageMaps(ArrayRef<const SILCoverageMap *> Mappings);
14851482
void emitSILFunction(SILFunction *f);
14861483
void emitSILWitnessTable(SILWitnessTable *wt);
14871484
void emitSILProperty(SILProperty *prop);

lib/SIL/IR/SILCoverageMap.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ using namespace swift;
2424
using llvm::coverage::CounterExpression;
2525

2626
SILCoverageMap *
27-
SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
27+
SILCoverageMap::create(SILModule &M, SourceFile *ParentSourceFile,
28+
StringRef Filename, StringRef Name,
2829
StringRef PGOFuncName, uint64_t Hash,
2930
ArrayRef<MappedRegion> MappedRegions,
3031
ArrayRef<CounterExpression> Expressions) {
3132
auto *Buf = M.allocate<SILCoverageMap>(1);
32-
SILCoverageMap *CM = ::new (Buf) SILCoverageMap(Hash);
33+
SILCoverageMap *CM = ::new (Buf) SILCoverageMap(ParentSourceFile, Hash);
3334

3435
// Store a copy of the names so that we own the lifetime.
3536
CM->Filename = M.allocateCopy(Filename);
@@ -50,7 +51,8 @@ SILCoverageMap::create(SILModule &M, StringRef Filename, StringRef Name,
5051
return CM;
5152
}
5253

53-
SILCoverageMap::SILCoverageMap(uint64_t Hash) : Hash(Hash) {}
54+
SILCoverageMap::SILCoverageMap(SourceFile *ParentSourceFile, uint64_t Hash)
55+
: ParentSourceFile(ParentSourceFile), Hash(Hash) {}
5456

5557
SILCoverageMap::~SILCoverageMap() {}
5658

lib/SIL/IR/SILPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3877,7 +3877,7 @@ void SILDifferentiabilityWitness::dump() const {
38773877

38783878
void SILCoverageMap::print(SILPrintContext &PrintCtx) const {
38793879
llvm::raw_ostream &OS = PrintCtx.OS();
3880-
OS << "sil_coverage_map " << QuotedString(getFile()) << " "
3880+
OS << "sil_coverage_map " << QuotedString(getFilename()) << " "
38813881
<< QuotedString(getName()) << " " << QuotedString(getPGOFuncName()) << " "
38823882
<< getHash() << " {\t// " << demangleSymbol(getName()) << "\n";
38833883
if (PrintCtx.sortSIL())

lib/SIL/IR/SILProfiler.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,7 @@ struct CoverageMapping : public ASTWalker {
10331033
SILCoverageMap *emitSourceRegions(
10341034
SILModule &M, StringRef Name, StringRef PGOFuncName, uint64_t Hash,
10351035
llvm::DenseMap<ProfileCounterRef, unsigned> &CounterIndices,
1036-
StringRef Filename) {
1036+
SourceFile *SF, StringRef Filename) {
10371037
if (SourceRegions.empty())
10381038
return nullptr;
10391039

@@ -1051,8 +1051,8 @@ struct CoverageMapping : public ASTWalker {
10511051
Regions.emplace_back(Start.first, Start.second, End.first, End.second,
10521052
Counter.expand(Builder, CounterIndices));
10531053
}
1054-
return SILCoverageMap::create(M, Filename, Name, PGOFuncName, Hash, Regions,
1055-
Builder.getExpressions());
1054+
return SILCoverageMap::create(M, SF, Filename, Name, PGOFuncName, Hash,
1055+
Regions, Builder.getExpressions());
10561056
}
10571057

10581058
PreWalkAction walkToDeclPre(Decl *D) override {
@@ -1331,13 +1331,6 @@ getEquivalentPGOLinkage(FormalLinkage Linkage) {
13311331
llvm_unreachable("Unhandled FormalLinkage in switch.");
13321332
}
13331333

1334-
static StringRef getCurrentFileName(SILDeclRef forDecl) {
1335-
auto *DC = forDecl.getInnermostDeclContext();
1336-
if (auto *ParentFile = DC->getParentSourceFile())
1337-
return ParentFile->getFilename();
1338-
return {};
1339-
}
1340-
13411334
static void walkNode(NodeToProfile Node, ASTWalker &Walker) {
13421335
if (auto N = Node.getAsNode()) {
13431336
N.walk(Walker);
@@ -1350,8 +1343,11 @@ static void walkNode(NodeToProfile Node, ASTWalker &Walker) {
13501343

13511344
void SILProfiler::assignRegionCounters() {
13521345
const auto &SM = M.getASTContext().SourceMgr;
1346+
auto *DC = forDecl.getInnermostDeclContext();
1347+
auto *SF = DC->getParentSourceFile();
1348+
assert(SF && "Not within a SourceFile?");
13531349

1354-
CurrentFileName = getCurrentFileName(forDecl);
1350+
CurrentFileName = SF->getFilename();
13551351

13561352
MapRegionCounters Mapper(forDecl, RegionCounterMap);
13571353

@@ -1387,7 +1383,7 @@ void SILProfiler::assignRegionCounters() {
13871383
walkNode(Root, Coverage);
13881384
CovMap =
13891385
Coverage.emitSourceRegions(M, CurrentFuncName, PGOFuncName, PGOFuncHash,
1390-
RegionCounterMap, CurrentFileName);
1386+
RegionCounterMap, SF, CurrentFileName);
13911387
}
13921388

13931389
if (llvm::IndexedInstrProfReader *IPR = M.getPGOReader()) {

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7946,8 +7946,9 @@ bool SILParserState::parseSILCoverageMap(Parser &P) {
79467946
LBraceLoc);
79477947

79487948
if (!BodyHasError)
7949-
SILCoverageMap::create(M, Filename.str(), FuncName.str(), PGOFuncName.str(),
7950-
Hash, Regions, Builder.getExpressions());
7949+
SILCoverageMap::create(M, &P.SF, Filename.str(), FuncName.str(),
7950+
PGOFuncName.str(), Hash, Regions,
7951+
Builder.getExpressions());
79517952
return false;
79527953
}
79537954

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public func func1() { func2() }

0 commit comments

Comments
 (0)