diff options
Diffstat (limited to 'clang/lib/CodeGen/CodeGenPGO.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 154 |
1 files changed, 115 insertions, 39 deletions
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 4def789132a..e6dbad856c3 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -13,6 +13,7 @@ #include "CodeGenPGO.h" #include "CodeGenFunction.h" +#include "CoverageMappingGen.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "llvm/IR/MDBuilder.h" @@ -24,8 +25,9 @@ using namespace clang; using namespace CodeGen; -void CodeGenPGO::setFuncName(llvm::Function *Fn) { - RawFuncName = Fn->getName(); +void CodeGenPGO::setFuncName(StringRef Name, + llvm::GlobalValue::LinkageTypes Linkage) { + RawFuncName = Name; // Function names may be prefixed with a binary '1' to indicate // that the backend should not modify the symbols due to any platform @@ -33,7 +35,7 @@ void CodeGenPGO::setFuncName(llvm::Function *Fn) { if (RawFuncName[0] == '\1') RawFuncName = RawFuncName.substr(1); - if (!Fn->hasLocalLinkage()) { + if (!llvm::GlobalValue::isLocalLinkage(Linkage)) { PrefixedFuncName.reset(new std::string(RawFuncName)); return; } @@ -49,6 +51,27 @@ void CodeGenPGO::setFuncName(llvm::Function *Fn) { PrefixedFuncName->append(RawFuncName); } +void CodeGenPGO::setFuncName(llvm::Function *Fn) { + setFuncName(Fn->getName(), Fn->getLinkage()); +} + +void CodeGenPGO::setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage) { + // Set the linkage for variables based on the function linkage. Usually, we + // want to match it, but available_externally and extern_weak both have the + // wrong semantics. + VarLinkage = Linkage; + switch (VarLinkage) { + case llvm::GlobalValue::ExternalWeakLinkage: + VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage; + break; + case llvm::GlobalValue::AvailableExternallyLinkage: + VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage; + break; + default: + break; + } +} + static llvm::Function *getRegisterFunc(CodeGenModule &CGM) { return CGM.getModule().getFunction("__llvm_profile_register_functions"); } @@ -120,37 +143,48 @@ llvm::GlobalVariable *CodeGenPGO::buildDataVar() { auto *Int64Ty = llvm::Type::getInt64Ty(Ctx); auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx); auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx); - llvm::Type *DataTypes[] = { - Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy - }; - auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes)); - llvm::Constant *DataVals[] = { - llvm::ConstantInt::get(Int32Ty, getFuncName().size()), - llvm::ConstantInt::get(Int32Ty, NumRegionCounters), - llvm::ConstantInt::get(Int64Ty, FunctionHash), - llvm::ConstantExpr::getBitCast(Name, Int8PtrTy), - llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy) - }; - auto *Data = - new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage, - llvm::ConstantStruct::get(DataTy, DataVals), - getFuncVarName("data")); + llvm::GlobalVariable *Data = nullptr; + if (RegionCounters) { + llvm::Type *DataTypes[] = { + Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy + }; + auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes)); + llvm::Constant *DataVals[] = { + llvm::ConstantInt::get(Int32Ty, getFuncName().size()), + llvm::ConstantInt::get(Int32Ty, NumRegionCounters), + llvm::ConstantInt::get(Int64Ty, FunctionHash), + llvm::ConstantExpr::getBitCast(Name, Int8PtrTy), + llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy) + }; + Data = + new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage, + llvm::ConstantStruct::get(DataTy, DataVals), + getFuncVarName("data")); + + // All the data should be packed into an array in its own section. + Data->setSection(getDataSection(CGM)); + Data->setAlignment(8); + } - // All the data should be packed into an array in its own section. - Data->setSection(getDataSection(CGM)); - Data->setAlignment(8); + // Create coverage mapping data variable. + if (!CoverageMapping.empty()) + CGM.getCoverageMapping()->addFunctionMappingRecord(Name, + getFuncName().size(), + CoverageMapping); // Hide all these symbols so that we correctly get a copy for each // executable. The profile format expects names and counters to be // contiguous, so references into shared objects would be invalid. if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) { Name->setVisibility(llvm::GlobalValue::HiddenVisibility); - Data->setVisibility(llvm::GlobalValue::HiddenVisibility); - RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility); + if (Data) { + Data->setVisibility(llvm::GlobalValue::HiddenVisibility); + RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility); + } } // Make sure the data doesn't get deleted. - CGM.addUsedGlobal(Data); + if (Data) CGM.addUsedGlobal(Data); return Data; } @@ -807,6 +841,20 @@ static void emitRuntimeHook(CodeGenModule &CGM) { CGM.addUsedGlobal(User); } +void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) { + // Make sure we only emit coverage mapping for one constructor/destructor. + // Clang emits several functions for the constructor and the destructor of + // a class. Every function is instrumented, but we only want to provide + // coverage for one of them. Because of that we only emit the coverage mapping + // for the base constructor/destructor. + if ((isa<CXXConstructorDecl>(GD.getDecl()) && + GD.getCtorType() != Ctor_Base) || + (isa<CXXDestructorDecl>(GD.getDecl()) && + GD.getDtorType() != Dtor_Base)) { + SkipCoverageMapping = true; + } +} + void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate; llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); @@ -814,27 +862,16 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { return; if (D->isImplicit()) return; + CGM.ClearUnusedCoverageMapping(D); setFuncName(Fn); - - // Set the linkage for variables based on the function linkage. Usually, we - // want to match it, but available_externally and extern_weak both have the - // wrong semantics. - VarLinkage = Fn->getLinkage(); - switch (VarLinkage) { - case llvm::GlobalValue::ExternalWeakLinkage: - VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage; - break; - case llvm::GlobalValue::AvailableExternallyLinkage: - VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage; - break; - default: - break; - } + setVarLinkage(Fn->getLinkage()); mapRegionCounters(D); if (InstrumentRegions) { emitRuntimeHook(CGM); emitCounterVariables(); + if (CGM.getCodeGenOpts().CoverageMapping) + emitCounterRegionMapping(D); } if (PGOReader) { SourceManager &SM = CGM.getContext().getSourceManager(); @@ -860,6 +897,45 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) { FunctionHash = Walker.Hash.finalize(); } +void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { + if (SkipCoverageMapping) + return; + // Don't map the functions inside the system headers + auto Loc = D->getBody()->getLocStart(); + if (CGM.getContext().getSourceManager().isInSystemHeader(Loc)) + return; + + llvm::raw_string_ostream OS(CoverageMapping); + CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), + CGM.getContext().getSourceManager(), + CGM.getLangOpts(), RegionCounterMap.get(), + NumRegionCounters); + MappingGen.emitCounterMapping(D, OS); + OS.flush(); +} + +void +CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName, + llvm::GlobalValue::LinkageTypes Linkage) { + if (SkipCoverageMapping) + return; + setFuncName(FuncName, Linkage); + setVarLinkage(Linkage); + + // Don't map the functions inside the system headers + auto Loc = D->getBody()->getLocStart(); + if (CGM.getContext().getSourceManager().isInSystemHeader(Loc)) + return; + + llvm::raw_string_ostream OS(CoverageMapping); + CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), + CGM.getContext().getSourceManager(), + CGM.getLangOpts()); + MappingGen.emitEmptyMapping(D, OS); + OS.flush(); + buildDataVar(); +} + void CodeGenPGO::computeRegionCounts(const Decl *D) { StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); ComputeRegionCounts Walker(*StmtCountMap, *this); |