mirror of
https://github.com/intel/llvm.git
synced 2026-01-31 16:29:50 +08:00
InstrProf: Use LLVM's -instrprof pass for profiling
The logic for lowering profiling counters has been moved to an LLVM pass. Emit the intrinsics rather than duplicating the whole pass in clang. llvm-svn: 223683
This commit is contained in:
@@ -366,6 +366,12 @@ void EmitAssemblyHelper::CreatePasses() {
|
||||
MPM->add(createStripSymbolsPass(true));
|
||||
}
|
||||
|
||||
if (CodeGenOpts.ProfileInstrGenerate) {
|
||||
InstrProfOptions Options;
|
||||
Options.NoRedZone = CodeGenOpts.DisableRedZone;
|
||||
MPM->add(createInstrProfilingPass(Options));
|
||||
}
|
||||
|
||||
PMBuilder.populateModulePassManager(*MPM);
|
||||
}
|
||||
|
||||
|
||||
@@ -1215,8 +1215,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
|
||||
RegionCounter Cnt = getPGORegionCounter(blockDecl->getBody());
|
||||
Cnt.beginRegion(Builder);
|
||||
EmitStmt(blockDecl->getBody());
|
||||
PGO.emitInstrumentationData();
|
||||
PGO.destroyRegionCounters();
|
||||
}
|
||||
|
||||
// Remember where we were...
|
||||
|
||||
@@ -508,8 +508,6 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
|
||||
Cnt.beginRegion(Builder);
|
||||
EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody()));
|
||||
FinishFunction(OMD->getBodyRBrace());
|
||||
PGO.emitInstrumentationData();
|
||||
PGO.destroyRegionCounters();
|
||||
}
|
||||
|
||||
/// emitStructGetterCall - Call the runtime function to load a property
|
||||
|
||||
@@ -2208,8 +2208,6 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
|
||||
PGO.assignRegionCounters(CD, F);
|
||||
CapturedStmtInfo->EmitBody(*this, CD->getBody());
|
||||
FinishFunction(CD->getBodyRBrace());
|
||||
PGO.emitInstrumentationData();
|
||||
PGO.destroyRegionCounters();
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
@@ -916,9 +916,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
|
||||
// a quick pass now to see if we can.
|
||||
if (!CurFn->doesNotThrow())
|
||||
TryMarkNoThrow(CurFn);
|
||||
|
||||
PGO.emitInstrumentationData();
|
||||
PGO.destroyRegionCounters();
|
||||
}
|
||||
|
||||
/// ContainsLabel - Return true if the statement contains a label in it. If
|
||||
|
||||
@@ -345,9 +345,6 @@ void CodeGenModule::Release() {
|
||||
if (ObjCRuntime)
|
||||
if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction())
|
||||
AddGlobalCtor(ObjCInitFunction);
|
||||
if (getCodeGenOpts().ProfileInstrGenerate)
|
||||
if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this))
|
||||
AddGlobalCtor(PGOInit, 0);
|
||||
if (PGOReader && PGOStats.hasDiagnostics())
|
||||
PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
|
||||
EmitCtorList(GlobalCtors, "llvm.global_ctors");
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "CoverageMappingGen.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/ProfileData/InstrProfReader.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
@@ -46,190 +47,33 @@ void CodeGenPGO::setFuncName(StringRef Name,
|
||||
else
|
||||
FuncName = FuncName.insert(0, CGM.getCodeGenOpts().MainFileName + ":");
|
||||
}
|
||||
|
||||
// If we're generating a profile, create a variable for the name.
|
||||
if (CGM.getCodeGenOpts().ProfileInstrGenerate)
|
||||
createFuncNameVar(Linkage);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
void CodeGenPGO::createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage) {
|
||||
// Usually, we want to match the function's linkage, but
|
||||
// available_externally and extern_weak both have the wrong semantics.
|
||||
if (Linkage == llvm::GlobalValue::ExternalWeakLinkage)
|
||||
Linkage = llvm::GlobalValue::LinkOnceAnyLinkage;
|
||||
else if (Linkage == llvm::GlobalValue::AvailableExternallyLinkage)
|
||||
Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
|
||||
|
||||
static llvm::Function *getRegisterFunc(CodeGenModule &CGM) {
|
||||
return CGM.getModule().getFunction("__llvm_profile_register_functions");
|
||||
}
|
||||
auto *Value =
|
||||
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), FuncName, false);
|
||||
FuncNameVar =
|
||||
new llvm::GlobalVariable(CGM.getModule(), Value->getType(), true, Linkage,
|
||||
Value, "__llvm_profile_name_" + FuncName);
|
||||
|
||||
static llvm::BasicBlock *getOrInsertRegisterBB(CodeGenModule &CGM) {
|
||||
// Don't do this for Darwin. compiler-rt uses linker magic.
|
||||
if (CGM.getTarget().getTriple().isOSDarwin())
|
||||
return nullptr;
|
||||
|
||||
// Only need to insert this once per module.
|
||||
if (llvm::Function *RegisterF = getRegisterFunc(CGM))
|
||||
return &RegisterF->getEntryBlock();
|
||||
|
||||
// Construct the function.
|
||||
auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
|
||||
auto *RegisterFTy = llvm::FunctionType::get(VoidTy, false);
|
||||
auto *RegisterF = llvm::Function::Create(RegisterFTy,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
"__llvm_profile_register_functions",
|
||||
&CGM.getModule());
|
||||
RegisterF->setUnnamedAddr(true);
|
||||
if (CGM.getCodeGenOpts().DisableRedZone)
|
||||
RegisterF->addFnAttr(llvm::Attribute::NoRedZone);
|
||||
|
||||
// Construct and return the entry block.
|
||||
auto *BB = llvm::BasicBlock::Create(CGM.getLLVMContext(), "", RegisterF);
|
||||
CGBuilderTy Builder(BB);
|
||||
Builder.CreateRetVoid();
|
||||
return BB;
|
||||
}
|
||||
|
||||
static llvm::Constant *getOrInsertRuntimeRegister(CodeGenModule &CGM) {
|
||||
auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
|
||||
auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
auto *RuntimeRegisterTy = llvm::FunctionType::get(VoidTy, VoidPtrTy, false);
|
||||
return CGM.getModule().getOrInsertFunction("__llvm_profile_register_function",
|
||||
RuntimeRegisterTy);
|
||||
}
|
||||
|
||||
static bool isMachO(const CodeGenModule &CGM) {
|
||||
return CGM.getTarget().getTriple().isOSBinFormatMachO();
|
||||
}
|
||||
|
||||
static StringRef getCountersSection(const CodeGenModule &CGM) {
|
||||
return isMachO(CGM) ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts";
|
||||
}
|
||||
|
||||
static StringRef getNameSection(const CodeGenModule &CGM) {
|
||||
return isMachO(CGM) ? "__DATA,__llvm_prf_names" : "__llvm_prf_names";
|
||||
}
|
||||
|
||||
static StringRef getDataSection(const CodeGenModule &CGM) {
|
||||
return isMachO(CGM) ? "__DATA,__llvm_prf_data" : "__llvm_prf_data";
|
||||
}
|
||||
|
||||
llvm::GlobalVariable *CodeGenPGO::buildDataVar() {
|
||||
// Create name variable.
|
||||
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
|
||||
auto *VarName = llvm::ConstantDataArray::getString(Ctx, getFuncName(),
|
||||
false);
|
||||
auto *Name = new llvm::GlobalVariable(CGM.getModule(), VarName->getType(),
|
||||
true, VarLinkage, VarName,
|
||||
getFuncVarName("name"));
|
||||
Name->setSection(getNameSection(CGM));
|
||||
Name->setAlignment(1);
|
||||
|
||||
// Create data variable.
|
||||
auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
|
||||
auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
|
||||
auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
|
||||
auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx);
|
||||
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);
|
||||
}
|
||||
|
||||
// Create coverage mapping data variable.
|
||||
if (!CoverageMapping.empty())
|
||||
CGM.getCoverageMapping()->addFunctionMappingRecord(Name, getFuncName(),
|
||||
FunctionHash,
|
||||
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);
|
||||
if (Data) {
|
||||
Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||
RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the data doesn't get deleted.
|
||||
if (Data) CGM.addUsedGlobal(Data);
|
||||
return Data;
|
||||
}
|
||||
|
||||
void CodeGenPGO::emitInstrumentationData() {
|
||||
if (!RegionCounters)
|
||||
return;
|
||||
|
||||
// Build the data.
|
||||
auto *Data = buildDataVar();
|
||||
|
||||
// Register the data.
|
||||
auto *RegisterBB = getOrInsertRegisterBB(CGM);
|
||||
if (!RegisterBB)
|
||||
return;
|
||||
CGBuilderTy Builder(RegisterBB->getTerminator());
|
||||
auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
Builder.CreateCall(getOrInsertRuntimeRegister(CGM),
|
||||
Builder.CreateBitCast(Data, VoidPtrTy));
|
||||
}
|
||||
|
||||
llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) {
|
||||
if (!CGM.getCodeGenOpts().ProfileInstrGenerate)
|
||||
return nullptr;
|
||||
|
||||
assert(CGM.getModule().getFunction("__llvm_profile_init") == nullptr &&
|
||||
"profile initialization already emitted");
|
||||
|
||||
// Get the function to call at initialization.
|
||||
llvm::Constant *RegisterF = getRegisterFunc(CGM);
|
||||
if (!RegisterF)
|
||||
return nullptr;
|
||||
|
||||
// Create the initialization function.
|
||||
auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
|
||||
auto *F = llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
"__llvm_profile_init", &CGM.getModule());
|
||||
F->setUnnamedAddr(true);
|
||||
F->addFnAttr(llvm::Attribute::NoInline);
|
||||
if (CGM.getCodeGenOpts().DisableRedZone)
|
||||
F->addFnAttr(llvm::Attribute::NoRedZone);
|
||||
|
||||
// Add the basic block and the necessary calls.
|
||||
CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", F));
|
||||
Builder.CreateCall(RegisterF);
|
||||
Builder.CreateRetVoid();
|
||||
|
||||
return F;
|
||||
// Hide the symbol so that we correctly get a copy for each executable.
|
||||
if (!llvm::GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
|
||||
FuncNameVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -809,35 +653,6 @@ uint64_t PGOHash::finalize() {
|
||||
return endian::read<uint64_t, little, unaligned>(Result);
|
||||
}
|
||||
|
||||
static void emitRuntimeHook(CodeGenModule &CGM) {
|
||||
const char *const RuntimeVarName = "__llvm_profile_runtime";
|
||||
const char *const RuntimeUserName = "__llvm_profile_runtime_user";
|
||||
if (CGM.getModule().getGlobalVariable(RuntimeVarName))
|
||||
return;
|
||||
|
||||
// Declare the runtime hook.
|
||||
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
|
||||
auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
|
||||
auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false,
|
||||
llvm::GlobalValue::ExternalLinkage,
|
||||
nullptr, RuntimeVarName);
|
||||
|
||||
// Make a function that uses it.
|
||||
auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false),
|
||||
llvm::GlobalValue::LinkOnceODRLinkage,
|
||||
RuntimeUserName, &CGM.getModule());
|
||||
User->addFnAttr(llvm::Attribute::NoInline);
|
||||
if (CGM.getCodeGenOpts().DisableRedZone)
|
||||
User->addFnAttr(llvm::Attribute::NoRedZone);
|
||||
CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User));
|
||||
auto *Load = Builder.CreateLoad(Var);
|
||||
Builder.CreateRet(Load);
|
||||
|
||||
// Create a use of the function. Now the definition of the runtime variable
|
||||
// should get pulled in, along with any static initializears.
|
||||
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
|
||||
@@ -861,15 +676,10 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
|
||||
return;
|
||||
CGM.ClearUnusedCoverageMapping(D);
|
||||
setFuncName(Fn);
|
||||
setVarLinkage(Fn->getLinkage());
|
||||
|
||||
mapRegionCounters(D);
|
||||
if (InstrumentRegions) {
|
||||
emitRuntimeHook(CGM);
|
||||
emitCounterVariables();
|
||||
if (CGM.getCodeGenOpts().CoverageMapping)
|
||||
emitCounterRegionMapping(D);
|
||||
}
|
||||
if (CGM.getCodeGenOpts().CoverageMapping)
|
||||
emitCounterRegionMapping(D);
|
||||
if (PGOReader) {
|
||||
SourceManager &SM = CGM.getContext().getSourceManager();
|
||||
loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
|
||||
@@ -902,12 +712,19 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
|
||||
if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
|
||||
return;
|
||||
|
||||
std::string CoverageMapping;
|
||||
llvm::raw_string_ostream OS(CoverageMapping);
|
||||
CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
|
||||
CGM.getContext().getSourceManager(),
|
||||
CGM.getLangOpts(), RegionCounterMap.get());
|
||||
MappingGen.emitCounterMapping(D, OS);
|
||||
OS.flush();
|
||||
|
||||
if (CoverageMapping.empty())
|
||||
return;
|
||||
|
||||
CGM.getCoverageMapping()->addFunctionMappingRecord(
|
||||
FuncNameVar, FuncName, FunctionHash, CoverageMapping);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -916,20 +733,25 @@ CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
|
||||
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;
|
||||
|
||||
std::string CoverageMapping;
|
||||
llvm::raw_string_ostream OS(CoverageMapping);
|
||||
CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
|
||||
CGM.getContext().getSourceManager(),
|
||||
CGM.getLangOpts());
|
||||
MappingGen.emitEmptyMapping(D, OS);
|
||||
OS.flush();
|
||||
buildDataVar();
|
||||
|
||||
if (CoverageMapping.empty())
|
||||
return;
|
||||
|
||||
CGM.getCoverageMapping()->addFunctionMappingRecord(
|
||||
FuncNameVar, FuncName, FunctionHash, CoverageMapping);
|
||||
}
|
||||
|
||||
void CodeGenPGO::computeRegionCounts(const Decl *D) {
|
||||
@@ -963,34 +785,23 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
|
||||
Fn->addFnAttr(llvm::Attribute::Cold);
|
||||
}
|
||||
|
||||
void CodeGenPGO::emitCounterVariables() {
|
||||
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
|
||||
llvm::ArrayType *CounterTy = llvm::ArrayType::get(llvm::Type::getInt64Ty(Ctx),
|
||||
NumRegionCounters);
|
||||
RegionCounters =
|
||||
new llvm::GlobalVariable(CGM.getModule(), CounterTy, false, VarLinkage,
|
||||
llvm::Constant::getNullValue(CounterTy),
|
||||
getFuncVarName("counters"));
|
||||
RegionCounters->setAlignment(8);
|
||||
RegionCounters->setSection(getCountersSection(CGM));
|
||||
}
|
||||
|
||||
void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
|
||||
if (!RegionCounters)
|
||||
if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
|
||||
return;
|
||||
llvm::Value *Addr =
|
||||
Builder.CreateConstInBoundsGEP2_64(RegionCounters, 0, Counter);
|
||||
llvm::Value *Count = Builder.CreateLoad(Addr, "pgocount");
|
||||
Count = Builder.CreateAdd(Count, Builder.getInt64(1));
|
||||
Builder.CreateStore(Count, Addr);
|
||||
auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
Builder.CreateCall4(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
|
||||
llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
|
||||
Builder.getInt64(FunctionHash),
|
||||
Builder.getInt32(NumRegionCounters),
|
||||
Builder.getInt32(Counter));
|
||||
}
|
||||
|
||||
void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
|
||||
bool IsInMainFile) {
|
||||
CGM.getPGOStats().addVisited(IsInMainFile);
|
||||
RegionCounts.clear();
|
||||
if (std::error_code EC = PGOReader->getFunctionCounts(
|
||||
getFuncName(), FunctionHash, RegionCounts)) {
|
||||
if (std::error_code EC =
|
||||
PGOReader->getFunctionCounts(FuncName, FunctionHash, RegionCounts)) {
|
||||
if (EC == llvm::instrprof_error::unknown_function)
|
||||
CGM.getPGOStats().addMissing(IsInMainFile);
|
||||
else if (EC == llvm::instrprof_error::hash_mismatch)
|
||||
@@ -1002,13 +813,6 @@ void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenPGO::destroyRegionCounters() {
|
||||
RegionCounterMap.reset();
|
||||
StmtCountMap.reset();
|
||||
RegionCounts.clear();
|
||||
RegionCounters = nullptr;
|
||||
}
|
||||
|
||||
/// \brief Calculate what to divide by to scale weights.
|
||||
///
|
||||
/// Given the maximum weight, calculate a divisor that will scale all the
|
||||
|
||||
@@ -32,24 +32,21 @@ class CodeGenPGO {
|
||||
private:
|
||||
CodeGenModule &CGM;
|
||||
std::string FuncName;
|
||||
llvm::GlobalValue::LinkageTypes VarLinkage;
|
||||
llvm::GlobalVariable *FuncNameVar;
|
||||
|
||||
unsigned NumRegionCounters;
|
||||
uint64_t FunctionHash;
|
||||
llvm::GlobalVariable *RegionCounters;
|
||||
std::unique_ptr<llvm::DenseMap<const Stmt *, unsigned>> RegionCounterMap;
|
||||
std::unique_ptr<llvm::DenseMap<const Stmt *, uint64_t>> StmtCountMap;
|
||||
std::vector<uint64_t> RegionCounts;
|
||||
uint64_t CurrentRegionCount;
|
||||
std::string CoverageMapping;
|
||||
/// \brief A flag that is set to true when this function doesn't need
|
||||
/// to have coverage mapping data.
|
||||
bool SkipCoverageMapping;
|
||||
|
||||
public:
|
||||
CodeGenPGO(CodeGenModule &CGM)
|
||||
: CGM(CGM), NumRegionCounters(0), FunctionHash(0),
|
||||
RegionCounters(nullptr), CurrentRegionCount(0),
|
||||
: CGM(CGM), NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0),
|
||||
SkipCoverageMapping(false) {}
|
||||
|
||||
/// Whether or not we have PGO region data for the current function. This is
|
||||
@@ -57,13 +54,6 @@ public:
|
||||
/// discarded.
|
||||
bool haveRegionCounts() const { return !RegionCounts.empty(); }
|
||||
|
||||
/// Get the string used to identify this function in the profile data.
|
||||
/// For functions with local linkage, this includes the main file name.
|
||||
StringRef getFuncName() const { return StringRef(FuncName); }
|
||||
std::string getFuncVarName(StringRef VarName) const {
|
||||
return ("__llvm_profile_" + VarName + "_" + FuncName).str();
|
||||
}
|
||||
|
||||
/// Return the counter value of the current region.
|
||||
uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
|
||||
|
||||
@@ -110,13 +100,6 @@ public:
|
||||
/// generates global variables or associates PGO data with each of the
|
||||
/// counters depending on whether we are generating or using instrumentation.
|
||||
void assignRegionCounters(const Decl *D, llvm::Function *Fn);
|
||||
/// Emit static data structures for instrumentation data.
|
||||
void emitInstrumentationData();
|
||||
/// Clean up region counter state. Must be called if assignRegionCounters is
|
||||
/// used.
|
||||
void destroyRegionCounters();
|
||||
/// Emit static initialization code, if any.
|
||||
static llvm::Function *emitInitialization(CodeGenModule &CGM);
|
||||
/// Emit a coverage mapping range with a counter zero
|
||||
/// for an unused declaration.
|
||||
void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
|
||||
@@ -124,7 +107,7 @@ public:
|
||||
private:
|
||||
void setFuncName(llvm::Function *Fn);
|
||||
void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage);
|
||||
void setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage);
|
||||
void createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage);
|
||||
void mapRegionCounters(const Decl *D);
|
||||
void computeRegionCounts(const Decl *D);
|
||||
void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
|
||||
@@ -132,7 +115,6 @@ private:
|
||||
void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
|
||||
bool IsInMainFile);
|
||||
void emitCounterVariables();
|
||||
llvm::GlobalVariable *buildDataVar();
|
||||
void emitCounterRegionMapping(const Decl *D);
|
||||
|
||||
/// Emit code to increment the counter at the given index
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// get thrown out.
|
||||
// RUN: %clang_cc1 -O2 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage-available_externally.c %s -o - -emit-llvm -fprofile-instr-generate | FileCheck %s
|
||||
|
||||
// CHECK: @__llvm_profile_counters_foo = linkonce_odr hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name_foo = linkonce_odr hidden constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1
|
||||
|
||||
// CHECK: @__llvm_profile_counters_foo = linkonce_odr hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_data_foo = linkonce_odr hidden constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
inline int foo(void) { return 1; }
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
// Check the data structures emitted by instrumentation.
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage.c %s -o - -emit-llvm -fprofile-instr-generate | FileCheck %s
|
||||
|
||||
// CHECK: @__llvm_profile_runtime = external global i32
|
||||
// CHECK: @__llvm_profile_counters_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name_foo = hidden constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_name_foo_weak = weak hidden constant [8 x i8] c"foo_weak", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_name_main = hidden constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @"__llvm_profile_name_c-linkage.c:foo_internal" = internal constant [24 x i8] c"c-linkage.c:foo_internal", section "__DATA,__llvm_prf_names", align 1
|
||||
|
||||
// CHECK: @__llvm_profile_counters_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_data_foo = hidden constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
void foo(void) { }
|
||||
|
||||
// CHECK: @__llvm_profile_counters_foo_weak = weak hidden global [5 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name_foo_weak = weak hidden constant [8 x i8] c"foo_weak", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_data_foo_weak = weak hidden constant { i32, i32, i64, i8*, i64* } { i32 8, i32 5, i64 {{[0-9]+}}, i8* getelementptr inbounds ([8 x i8]* @__llvm_profile_name_foo_weak, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters_foo_weak, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
void foo_weak(void) __attribute__((weak));
|
||||
void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} }
|
||||
|
||||
// CHECK: @__llvm_profile_counters_main = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name_main = hidden constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_data_main = hidden constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
static void foo_internal(void);
|
||||
int main(void) {
|
||||
@@ -25,11 +26,11 @@ int main(void) {
|
||||
}
|
||||
|
||||
// CHECK: @"__llvm_profile_counters_c-linkage.c:foo_internal" = internal global [3 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @"__llvm_profile_name_c-linkage.c:foo_internal" = internal constant [24 x i8] c"c-linkage.c:foo_internal", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @"__llvm_profile_data_c-linkage.c:foo_internal" = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 {{[0-9]+}}, i8* getelementptr inbounds ([24 x i8]* @"__llvm_profile_name_c-linkage.c:foo_internal", i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @"__llvm_profile_counters_c-linkage.c:foo_internal", i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
static void foo_internal(void) { if (0){} if (0){} }
|
||||
|
||||
// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @"__llvm_profile_data_c-linkage.c:foo_internal" to i8*)], section "llvm.metadata"
|
||||
// CHECK: @__llvm_profile_runtime = external global i32
|
||||
// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @"__llvm_profile_data_c-linkage.c:foo_internal" to i8*), i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)], section "llvm.metadata"
|
||||
|
||||
// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
|
||||
// CHECK: %[[REG:.*]] = load i32* @__llvm_profile_runtime
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -emit-llvm -main-file-name cxx-linkage.cpp %s -o - -fprofile-instr-generate | FileCheck %s
|
||||
|
||||
// CHECK: @__llvm_profile_runtime = external global i32
|
||||
// CHECK: @__llvm_profile_counters__Z3foov = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name__Z3foov = hidden constant [7 x i8] c"_Z3foov", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_name__Z8foo_weakv = weak hidden constant [12 x i8] c"_Z8foo_weakv", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_name_main = hidden constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_name__Z10foo_inlinev = linkonce_odr hidden constant [15 x i8] c"_Z10foo_inlinev", section "__DATA,__llvm_prf_names", align 1
|
||||
|
||||
// CHECK: @__llvm_profile_counters__Z3foov = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_data__Z3foov = hidden constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([7 x i8]* @__llvm_profile_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
void foo(void) { }
|
||||
|
||||
// CHECK: @__llvm_profile_counters__Z8foo_weakv = weak hidden global [5 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name__Z8foo_weakv = weak hidden constant [12 x i8] c"_Z8foo_weakv", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_data__Z8foo_weakv = weak hidden constant { i32, i32, i64, i8*, i64* } { i32 12, i32 5, i64 {{[0-9]+}}, i8* getelementptr inbounds ([12 x i8]* @__llvm_profile_name__Z8foo_weakv, i32 0, i32 0), i64* getelementptr inbounds ([5 x i64]* @__llvm_profile_counters__Z8foo_weakv, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
void foo_weak(void) __attribute__((weak));
|
||||
void foo_weak(void) { if (0){} if (0){} if (0){} if (0){} }
|
||||
|
||||
// CHECK: @__llvm_profile_counters_main = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name_main = hidden constant [4 x i8] c"main", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_data_main = hidden constant { i32, i32, i64, i8*, i64* } { i32 4, i32 1, i64 {{[0-9]+}}, i8* getelementptr inbounds ([4 x i8]* @__llvm_profile_name_main, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_main, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
inline void foo_inline(void);
|
||||
int main(void) {
|
||||
@@ -24,11 +25,11 @@ int main(void) {
|
||||
}
|
||||
|
||||
// CHECK: @__llvm_profile_counters__Z10foo_inlinev = linkonce_odr hidden global [7 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
|
||||
// CHECK: @__llvm_profile_name__Z10foo_inlinev = linkonce_odr hidden constant [15 x i8] c"_Z10foo_inlinev", section "__DATA,__llvm_prf_names", align 1
|
||||
// CHECK: @__llvm_profile_data__Z10foo_inlinev = linkonce_odr hidden constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 {{[0-9]+}}, i8* getelementptr inbounds ([15 x i8]* @__llvm_profile_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_profile_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
|
||||
inline void foo_inline(void) { if (0){} if (0){} if (0){} if (0){} if (0){} if (0){}}
|
||||
|
||||
// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"
|
||||
// CHECK: @__llvm_profile_runtime = external global i32
|
||||
// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*), i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)], section "llvm.metadata"
|
||||
|
||||
// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
|
||||
// CHECK: %[[REG:.*]] = load i32* @__llvm_profile_runtime
|
||||
|
||||
Reference in New Issue
Block a user