Skip to content

Commit 992d3aa

Browse files
committed
[IRGen] Fix lowering of int_instrprof_increment
Update our usage of llvm's coverage API and fix the way we lower instrprof_increment intrinsics. This keeps us up-to-date with llvm/stable and makes instrumented IR easier to read.
1 parent 51d4e27 commit 992d3aa

File tree

3 files changed

+89
-40
lines changed

3 files changed

+89
-40
lines changed

lib/IRGen/GenCoverage.cpp

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,22 @@
2929
using namespace swift;
3030
using namespace irgen;
3131

32+
using llvm::coverage::CovMapVersion;
3233
using llvm::coverage::CounterMappingRegion;
3334

34-
// This is disabled for some reason.
35-
#define DISABLE_COVERAGE_MAPPING
36-
37-
#ifndef DISABLE_COVERAGE_MAPPING
3835
static bool isMachO(IRGenModule &IGM) {
3936
return SwiftTargetInfo::get(IGM).OutputObjectFormat == llvm::Triple::MachO;
4037
}
4138

4239
static StringRef getCoverageSection(IRGenModule &IGM) {
4340
return llvm::getInstrProfCoverageSectionName(isMachO(IGM));
4441
}
45-
#endif
42+
43+
static StringRef getProfNamesSection(IRGenModule &IGM) {
44+
return llvm::getInstrProfNameSectionName(isMachO(IGM));
45+
}
4646

4747
void IRGenModule::emitCoverageMapping() {
48-
#ifdef DISABLE_COVERAGE_MAPPING
49-
return;
50-
#else
5148
const auto &Mappings = SILMod->getCoverageMapList();
5249
// If there aren't any coverage maps, there's nothing to emit.
5350
if (Mappings.empty())
@@ -71,21 +68,20 @@ void IRGenModule::emitCoverageMapping() {
7168
}
7269

7370
// Encode the filenames first.
74-
std::string EncodedDataBuf;
75-
llvm::raw_string_ostream OS(EncodedDataBuf);
71+
std::string FilenamesAndCoverageMappings;
72+
llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
7673
llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
7774
size_t FilenamesSize = OS.str().size();
7875
size_t CurrentSize, PrevSize = FilenamesSize;
7976

8077
// Now we need to build up the list of function records.
8178
llvm::LLVMContext &Ctx = LLVMContext;
8279
auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
83-
auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
84-
auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
8580

86-
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
8781
llvm::Type *FunctionRecordTypes[] = {
82+
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
8883
#include "llvm/ProfileData/InstrProfData.inc"
84+
#undef COVMAP_FUNC_RECORD
8985
};
9086

9187
auto FunctionRecordTy =
@@ -107,19 +103,31 @@ void IRGenModule::emitCoverageMapping() {
107103
Regions);
108104
W.write(OS);
109105

110-
auto *NameVal = llvm::ConstantDataArray::getString(Ctx, M.getName(), false);
111-
auto *NameVar = new llvm::GlobalVariable(
112-
*getModule(), NameVal->getType(), true,
113-
llvm::GlobalValue::LinkOnceAnyLinkage, NameVal,
114-
llvm::getInstrProfNameVarPrefix() + M.getName());
106+
std::string NameValue = llvm::getPGOFuncName(
107+
M.getName(), llvm::GlobalValue::LinkOnceAnyLinkage, M.getFile());
108+
llvm::GlobalVariable *NamePtr = llvm::createPGOFuncNameVar(
109+
*getModule(), llvm::GlobalValue::LinkOnceAnyLinkage, NameValue);
110+
111+
// The instr-profiling pass in llvm typically sets the function name ptr's
112+
// section. We do it here because (1) SIL's int_instrprof_increment does not
113+
// use this exact GlobalVariable, so llvm misses it and (2) we shouldn't
114+
// expose all name ptrs to llvm via the getCoverageUnusedNamesVarName() API.
115+
NamePtr->setSection(getProfNamesSection(*this));
116+
NamePtr->setAlignment(1);
115117

116118
CurrentSize = OS.str().size();
119+
unsigned MappingLen = CurrentSize - PrevSize;
120+
StringRef CoverageMapping(OS.str().c_str() + PrevSize, MappingLen);
121+
122+
uint64_t FuncHash = M.getHash();
123+
117124
// Create a record for this function.
118125
llvm::Constant *FunctionRecordVals[] = {
119-
llvm::ConstantExpr::getBitCast(NameVar, Int8PtrTy),
120-
llvm::ConstantInt::get(Int32Ty, M.getName().size()),
121-
llvm::ConstantInt::get(Int32Ty, CurrentSize - PrevSize),
122-
llvm::ConstantInt::get(Int64Ty, M.getHash())};
126+
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
127+
#include "llvm/ProfileData/InstrProfData.inc"
128+
#undef COVMAP_FUNC_RECORD
129+
};
130+
123131
FunctionRecords.push_back(llvm::ConstantStruct::get(
124132
FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
125133
PrevSize = CurrentSize;
@@ -133,32 +141,43 @@ void IRGenModule::emitCoverageMapping() {
133141
for (size_t I = 0, S = 8 - Rem; I < S; ++I)
134142
OS << '\0';
135143
}
136-
auto *EncodedData =
144+
auto *FilenamesAndMappingsVal =
137145
llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
138146

139147
auto *RecordsTy =
140148
llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
141149
auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
142150

143-
// Now we embed everything into a constant with a well-known name.
144-
auto *CovDataTy =
145-
llvm::StructType::get(Ctx, {Int32Ty, Int32Ty, Int32Ty, Int32Ty, RecordsTy,
146-
EncodedData->getType()});
147-
llvm::Constant *TUDataVals[] = {
148-
llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
149-
llvm::ConstantInt::get(Int32Ty, FilenamesSize),
150-
llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
151-
llvm::ConstantInt::get(Int32Ty, llvm::coverage::CoverageMappingVersion1),
152-
RecordsVal,
153-
EncodedData};
154-
auto CovDataVal =
151+
// Create the coverage data header.
152+
llvm::Type *CovDataHeaderTypes[] = {
153+
#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
154+
#include "llvm/ProfileData/InstrProfData.inc"
155+
#undef COVMAP_HEADER
156+
};
157+
auto *CovDataHeaderTy =
158+
llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
159+
llvm::Constant *CovDataHeaderVals[] = {
160+
#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
161+
#include "llvm/ProfileData/InstrProfData.inc"
162+
#undef COVMAP_HEADER
163+
};
164+
auto *CovDataHeaderVal = llvm::ConstantStruct::get(
165+
CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
166+
167+
// Combine the header, function records, and mappings together.
168+
llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
169+
FilenamesAndMappingsVal->getType()};
170+
auto *CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
171+
llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
172+
FilenamesAndMappingsVal};
173+
auto *CovDataVal =
155174
llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
175+
156176
auto CovData = new llvm::GlobalVariable(
157177
*getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
158178
CovDataVal, llvm::getCoverageMappingVarName());
159179
CovData->setSection(getCoverageSection(*this));
160180
CovData->setAlignment(8);
161181

162182
addUsedGlobal(CovData);
163-
#endif
164183
}

lib/IRGen/GenFunc.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@
8585
#include "clang/AST/RecordLayout.h"
8686
#include "clang/CodeGen/CodeGenABITypes.h"
8787
#include "clang/CodeGen/ModuleBuilder.h"
88+
#include "llvm/IR/Constants.h"
8889
#include "llvm/IR/DerivedTypes.h"
8990
#include "llvm/IR/Function.h"
9091
#include "llvm/IR/Intrinsics.h"
9192
#include "llvm/IR/Module.h"
9293
#include "llvm/IR/CallSite.h"
94+
#include "llvm/ProfileData/InstrProf.h"
9395
#include "llvm/Support/Debug.h"
9496
#include "llvm/ADT/StringSwitch.h"
9597

@@ -1725,6 +1727,36 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, Identifier FnId,
17251727
// If this is an LLVM IR intrinsic, lower it to an intrinsic call.
17261728
const IntrinsicInfo &IInfo = IGF.IGM.SILMod->getIntrinsicInfo(FnId);
17271729
llvm::Intrinsic::ID IID = IInfo.ID;
1730+
1731+
// Calls to the int_instrprof_increment intrinsic are emitted during SILGen.
1732+
// At that stage, the function name GV used by the profiling pass is hidden.
1733+
// Fix the intrinsic call here by pointing it to the correct GV.
1734+
if (IID == llvm::Intrinsic::instrprof_increment) {
1735+
// Extract the function name.
1736+
auto *NameGEP = cast<llvm::User>(args.claimNext());
1737+
auto *NameGV = cast<llvm::GlobalVariable>(NameGEP->getOperand(0));
1738+
auto *NameC = NameGV->getInitializer();
1739+
StringRef Name = cast<llvm::ConstantDataArray>(NameC)->getRawDataValues();
1740+
1741+
// Find the existing function name pointer.
1742+
std::string NameValue = llvm::getInstrProfNameVarPrefix();
1743+
NameValue += Name;
1744+
StringRef ProfName = StringRef(NameValue).rtrim(StringRef("\0", 1));
1745+
auto *FuncNamePtr = IGF.IGM.Module.getNamedGlobal(ProfName);
1746+
assert(FuncNamePtr && "No function name pointer for counter update");
1747+
1748+
// Create a GEP into the function name.
1749+
llvm::SmallVector<llvm::Value *, 2> Indices(2, NameGEP->getOperand(1));
1750+
auto *FuncName = llvm::GetElementPtrInst::CreateInBounds(
1751+
FuncNamePtr, makeArrayRef(Indices), "", IGF.Builder.GetInsertBlock());
1752+
1753+
// Replace the placeholder value with the new GEP.
1754+
Explosion replacement;
1755+
replacement.add(FuncName);
1756+
replacement.add(args.claimAll());
1757+
args = std::move(replacement);
1758+
}
1759+
17281760
if (IID != llvm::Intrinsic::not_intrinsic) {
17291761
SmallVector<llvm::Type*, 4> ArgTys;
17301762
for (auto T : IInfo.Types)

lib/SILGen/SILGenProfiling.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,14 +673,12 @@ void SILGenProfiling::emitCounterIncrement(SILGenBuilder &Builder,ASTNode Node){
673673

674674
SILLocation Loc = getLocation(Node);
675675
SILValue Args[] = {
676-
// TODO: In C++ we give this string linkage that matches the functions, so
677-
// that it's uniqued appropriately across TUs.
676+
// The intrinsic must refer to the function profiling name var, which is
677+
// inaccessible during SILGen. Rely on irgen to rewrite the function name.
678678
Builder.createStringLiteral(Loc, StringRef(CurrentFuncName),
679679
StringLiteralInst::Encoding::UTF8),
680680
Builder.createIntegerLiteral(Loc, Int64Ty, FunctionHash),
681681
Builder.createIntegerLiteral(Loc, Int32Ty, NumRegionCounters),
682-
// TODO: Should we take care to emit only one copy of each of the above
683-
// three literals per function?
684682
Builder.createIntegerLiteral(Loc, Int32Ty, CounterIt->second)};
685683
Builder.createBuiltin(Loc, C.getIdentifier("int_instrprof_increment"),
686684
SGM.Types.getEmptyTupleType(), {}, Args);

0 commit comments

Comments
 (0)