r203711 - CodeGen: Use a binary format for instrumentation based profiling
Justin Bogner
mail at justinbogner.com
Wed Mar 12 13:53:16 PDT 2014
Author: bogner
Date: Wed Mar 12 15:53:16 2014
New Revision: 203711
URL: http://llvm.org/viewvc/llvm-project?rev=203711&view=rev
Log:
CodeGen: Use a binary format for instrumentation based profiling
This updates CodeGenPGO to use the ProfileDataReader introduced to
llvm in r203703 and the new API for writing out the profile introduced
to compiler-rt in r203710.
Modified:
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
cfe/trunk/lib/CodeGen/CodeGenPGO.h
cfe/trunk/test/Profile/Inputs/c-attributes.profdata
cfe/trunk/test/Profile/Inputs/c-counter-overflows.profdata
cfe/trunk/test/Profile/Inputs/c-general.profdata
cfe/trunk/test/Profile/Inputs/c-outdated-data.profdata
cfe/trunk/test/Profile/Inputs/cxx-class.profdata
cfe/trunk/test/Profile/Inputs/cxx-throws.profdata
cfe/trunk/test/Profile/Inputs/objc-general.profdata
cfe/trunk/tools/driver/CMakeLists.txt
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Mar 12 15:53:16 2014
@@ -47,6 +47,7 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Profile/ProfileDataReader.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
@@ -77,7 +78,7 @@ CodeGenModule::CodeGenModule(ASTContext
ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0),
TheTargetCodeGenInfo(0), Types(*this), VTables(*this), ObjCRuntime(0),
OpenCLRuntime(0), CUDARuntime(0), DebugInfo(0), ARCData(0),
- NoObjCARCExceptionsMetadata(0), RRData(0), PGOData(0),
+ NoObjCARCExceptionsMetadata(0), RRData(0), PGOReader(nullptr),
CFConstantStringClassRef(0),
ConstantStringClassRef(0), NSConstantStringType(0),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0),
@@ -133,8 +134,14 @@ CodeGenModule::CodeGenModule(ASTContext
ARCData = new ARCEntrypoints();
RRData = new RREntrypoints();
- if (!CodeGenOpts.InstrProfileInput.empty())
- PGOData = new PGOProfileData(*this, CodeGenOpts.InstrProfileInput);
+ if (!CodeGenOpts.InstrProfileInput.empty()) {
+ if (llvm::error_code EC = llvm::ProfileDataReader::create(
+ CodeGenOpts.InstrProfileInput, PGOReader)) {
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "Could not read profile: %0");
+ getDiags().Report(DiagID) << EC.message();
+ }
+ }
}
CodeGenModule::~CodeGenModule() {
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Wed Mar 12 15:53:16 2014
@@ -42,6 +42,7 @@ namespace llvm {
class DataLayout;
class FunctionType;
class LLVMContext;
+ class ProfileDataReader;
}
namespace clang {
@@ -85,7 +86,6 @@ namespace CodeGen {
class CGCUDARuntime;
class BlockFieldFlags;
class FunctionArgList;
- class PGOProfileData;
struct OrderGlobalInits {
unsigned int priority;
@@ -257,7 +257,7 @@ class CodeGenModule : public CodeGenType
ARCEntrypoints *ARCData;
llvm::MDNode *NoObjCARCExceptionsMetadata;
RREntrypoints *RRData;
- PGOProfileData *PGOData;
+ std::unique_ptr<llvm::ProfileDataReader> PGOReader;
// WeakRefReferences - A set of references that have only been seen via
// a weakref so far. This is used to remove the weak of the reference if we
@@ -480,8 +480,8 @@ public:
return *RRData;
}
- PGOProfileData *getPGOData() const {
- return PGOData;
+ llvm::ProfileDataReader *getPGOReader() const {
+ return PGOReader.get();
}
llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Wed Mar 12 15:53:16 2014
@@ -17,132 +17,12 @@
#include "clang/AST/StmtVisitor.h"
#include "llvm/Config/config.h" // for strtoull()/strtoll() define
#include "llvm/IR/MDBuilder.h"
+#include "llvm/Profile/ProfileDataReader.h"
#include "llvm/Support/FileSystem.h"
using namespace clang;
using namespace CodeGen;
-static void ReportBadPGOData(CodeGenModule &CGM, const char *Message) {
- DiagnosticsEngine &Diags = CGM.getDiags();
- unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0");
- Diags.Report(diagID) << Message;
-}
-
-PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path)
- : CGM(CGM) {
- if (llvm::MemoryBuffer::getFile(Path, DataBuffer)) {
- ReportBadPGOData(CGM, "failed to open pgo data file");
- return;
- }
-
- if (DataBuffer->getBufferSize() > std::numeric_limits<unsigned>::max()) {
- ReportBadPGOData(CGM, "pgo data file too big");
- return;
- }
-
- // Scan through the data file and map each function to the corresponding
- // file offset where its counts are stored.
- const char *BufferStart = DataBuffer->getBufferStart();
- const char *BufferEnd = DataBuffer->getBufferEnd();
- const char *CurPtr = BufferStart;
- uint64_t MaxCount = 0;
- while (CurPtr < BufferEnd) {
- // Read the function name.
- const char *FuncStart = CurPtr;
- // For Objective-C methods, the name may include whitespace, so search
- // backward from the end of the line to find the space that separates the
- // name from the number of counters. (This is a temporary hack since we are
- // going to completely replace this file format in the near future.)
- CurPtr = strchr(CurPtr, '\n');
- if (!CurPtr) {
- ReportBadPGOData(CGM, "pgo data file has malformed function entry");
- return;
- }
- while (*--CurPtr != ' ')
- ;
- StringRef FuncName(FuncStart, CurPtr - FuncStart);
-
- // Read the number of counters.
- char *EndPtr;
- unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n' || NumCounters <= 0) {
- ReportBadPGOData(CGM, "pgo data file has unexpected number of counters");
- return;
- }
- CurPtr = EndPtr;
-
- // Read function count.
- uint64_t Count = strtoll(CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n') {
- ReportBadPGOData(CGM, "pgo-data file has bad count value");
- return;
- }
- CurPtr = EndPtr; // Point to '\n'.
- FunctionCounts[FuncName] = Count;
- MaxCount = Count > MaxCount ? Count : MaxCount;
-
- // There is one line for each counter; skip over those lines.
- // Since function count is already read, we start the loop from 1.
- for (unsigned N = 1; N < NumCounters; ++N) {
- CurPtr = strchr(++CurPtr, '\n');
- if (!CurPtr) {
- ReportBadPGOData(CGM, "pgo data file is missing some counter info");
- return;
- }
- }
-
- // Skip over the blank line separating functions.
- CurPtr += 2;
-
- DataOffsets[FuncName] = FuncStart - BufferStart;
- }
- MaxFunctionCount = MaxCount;
-}
-
-bool PGOProfileData::getFunctionCounts(StringRef FuncName,
- std::vector<uint64_t> &Counts) {
- // Find the relevant section of the pgo-data file.
- llvm::StringMap<unsigned>::const_iterator OffsetIter =
- DataOffsets.find(FuncName);
- if (OffsetIter == DataOffsets.end())
- return true;
- const char *CurPtr = DataBuffer->getBufferStart() + OffsetIter->getValue();
-
- // Skip over the function name.
- CurPtr = strchr(CurPtr, '\n');
- assert(CurPtr && "pgo-data has corrupted function entry");
- while (*--CurPtr != ' ')
- ;
-
- // Read the number of counters.
- char *EndPtr;
- unsigned NumCounters = strtol(++CurPtr, &EndPtr, 10);
- assert(EndPtr != CurPtr && *EndPtr == '\n' && NumCounters > 0 &&
- "pgo-data file has corrupted number of counters");
- CurPtr = EndPtr;
-
- Counts.reserve(NumCounters);
-
- for (unsigned N = 0; N < NumCounters; ++N) {
- // Read the count value.
- uint64_t Count = strtoll(CurPtr, &EndPtr, 10);
- if (EndPtr == CurPtr || *EndPtr != '\n') {
- ReportBadPGOData(CGM, "pgo-data file has bad count value");
- return true;
- }
- Counts.push_back(Count);
- CurPtr = EndPtr + 1;
- }
-
- // Make sure the number of counters matches up.
- if (Counts.size() != NumCounters) {
- ReportBadPGOData(CGM, "pgo-data file has inconsistent counters");
- return true;
- }
-
- return false;
-}
-
void CodeGenPGO::setFuncName(llvm::Function *Fn) {
StringRef Func = Fn->getName();
@@ -177,22 +57,23 @@ void CodeGenPGO::emitWriteoutFunction()
llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx);
llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
- llvm::Function *WriteoutF =
- CGM.getModule().getFunction("__llvm_pgo_writeout");
- if (!WriteoutF) {
- llvm::FunctionType *WriteoutFTy =
+ llvm::Function *AddFuncsF =
+ CGM.getModule().getFunction("__llvm_pgo_add_functions");
+ if (!AddFuncsF) {
+ llvm::FunctionType *AddFuncsFTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
- WriteoutF = llvm::Function::Create(WriteoutFTy,
+ AddFuncsF = llvm::Function::Create(AddFuncsFTy,
llvm::GlobalValue::InternalLinkage,
- "__llvm_pgo_writeout", &CGM.getModule());
+ "__llvm_pgo_add_functions",
+ &CGM.getModule());
}
- WriteoutF->setUnnamedAddr(true);
- WriteoutF->addFnAttr(llvm::Attribute::NoInline);
+ AddFuncsF->setUnnamedAddr(true);
+ AddFuncsF->addFnAttr(llvm::Attribute::NoInline);
if (CGM.getCodeGenOpts().DisableRedZone)
- WriteoutF->addFnAttr(llvm::Attribute::NoRedZone);
+ AddFuncsF->addFnAttr(llvm::Attribute::NoRedZone);
- llvm::BasicBlock *BB = WriteoutF->empty() ?
- llvm::BasicBlock::Create(Ctx, "", WriteoutF) : &WriteoutF->getEntryBlock();
+ llvm::BasicBlock *BB = AddFuncsF->empty() ?
+ llvm::BasicBlock::Create(Ctx, "", AddFuncsF) : &AddFuncsF->getEntryBlock();
CGBuilderTy PGOBuilder(BB);
@@ -202,32 +83,35 @@ void CodeGenPGO::emitWriteoutFunction()
PGOBuilder.SetInsertPoint(I);
llvm::Type *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx);
+ llvm::Type *Int64Ty = llvm::Type::getInt64Ty(Ctx);
llvm::Type *Args[] = {
Int8PtrTy, // const char *FuncName
+ Int64Ty, // uint64_t FunctionHash
Int32Ty, // uint32_t NumCounters
Int64PtrTy // uint64_t *Counters
};
llvm::FunctionType *FTy =
llvm::FunctionType::get(PGOBuilder.getVoidTy(), Args, false);
llvm::Constant *EmitFunc =
- CGM.getModule().getOrInsertFunction("llvm_pgo_emit", FTy);
+ CGM.getModule().getOrInsertFunction("llvm_pgo_add_function", FTy);
llvm::Constant *NameString =
CGM.GetAddrOfConstantCString(getFuncName(), "__llvm_pgo_name");
NameString = llvm::ConstantExpr::getBitCast(NameString, Int8PtrTy);
- PGOBuilder.CreateCall3(EmitFunc, NameString,
+ PGOBuilder.CreateCall4(EmitFunc, NameString,
+ // TODO: This should be a hash, not just the count!
+ PGOBuilder.getInt64(NumRegionCounters),
PGOBuilder.getInt32(NumRegionCounters),
PGOBuilder.CreateBitCast(RegionCounters, Int64PtrTy));
}
llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) {
- llvm::Function *WriteoutF =
- CGM.getModule().getFunction("__llvm_pgo_writeout");
- if (!WriteoutF)
+ llvm::Function *AddFuncsF =
+ CGM.getModule().getFunction("__llvm_pgo_add_functions");
+ if (!AddFuncsF)
return NULL;
- // Create a small bit of code that registers the "__llvm_pgo_writeout" to
- // be executed at exit.
+ // Create a small bit of code that initializes PGO at startup
llvm::Function *F = CGM.getModule().getFunction("__llvm_pgo_init");
if (F)
return NULL;
@@ -255,7 +139,7 @@ llvm::Function *CodeGenPGO::emitInitiali
// Inialize the environment and register the local writeout function.
llvm::Constant *PGOInit =
CGM.getModule().getOrInsertFunction("llvm_pgo_init", FTy);
- PGOBuilder.CreateCall(PGOInit, WriteoutF);
+ PGOBuilder.CreateCall(PGOInit, AddFuncsF);
PGOBuilder.CreateRetVoid();
return F;
@@ -758,8 +642,8 @@ namespace {
void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
- PGOProfileData *PGOData = CGM.getPGOData();
- if (!InstrumentRegions && !PGOData)
+ llvm::ProfileDataReader *PGOReader = CGM.getPGOReader();
+ if (!InstrumentRegions && !PGOReader)
return;
if (!D)
return;
@@ -767,10 +651,10 @@ void CodeGenPGO::assignRegionCounters(co
mapRegionCounters(D);
if (InstrumentRegions)
emitCounterVariables();
- if (PGOData) {
- loadRegionCounts(PGOData);
+ if (PGOReader) {
+ loadRegionCounts(PGOReader);
computeRegionCounts(D);
- applyFunctionAttributes(PGOData, Fn);
+ applyFunctionAttributes(PGOReader, Fn);
}
}
@@ -797,12 +681,12 @@ void CodeGenPGO::computeRegionCounts(con
Walker.VisitBlockDecl(BD);
}
-void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData,
+void CodeGenPGO::applyFunctionAttributes(llvm::ProfileDataReader *PGOReader,
llvm::Function *Fn) {
if (!haveRegionCounts())
return;
- uint64_t MaxFunctionCount = PGOData->getMaximumFunctionCount();
+ uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
uint64_t FunctionCount = getRegionCount(0);
if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
// Turn on InlineHint attribute for hot functions.
@@ -835,13 +719,15 @@ void CodeGenPGO::emitCounterIncrement(CG
Builder.CreateStore(Count, Addr);
}
-void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) {
+void CodeGenPGO::loadRegionCounts(llvm::ProfileDataReader *PGOReader) {
// For now, ignore the counts from the PGO data file only if the number of
// counters does not match. This could be tightened down in the future to
// ignore counts when the input changes in various ways, e.g., by comparing a
// hash value based on some characteristics of the input.
RegionCounts = new std::vector<uint64_t>();
- if (PGOData->getFunctionCounts(getFuncName(), *RegionCounts) ||
+ uint64_t Hash;
+ // TODO: Check for hash mismatch
+ if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts) ||
RegionCounts->size() != NumRegionCounters) {
delete RegionCounts;
RegionCounts = 0;
Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Wed Mar 12 15:53:16 2014
@@ -26,27 +26,6 @@ namespace clang {
namespace CodeGen {
class RegionCounter;
-/// The raw counter data from an instrumented PGO binary
-class PGOProfileData {
-private:
- /// The PGO data
- std::unique_ptr<llvm::MemoryBuffer> DataBuffer;
- /// Offsets into DataBuffer for each function's counters
- llvm::StringMap<unsigned> DataOffsets;
- /// Execution counts for each function.
- llvm::StringMap<uint64_t> FunctionCounts;
- /// The maximal execution count among all functions.
- uint64_t MaxFunctionCount;
- CodeGenModule &CGM;
-public:
- PGOProfileData(CodeGenModule &CGM, std::string Path);
- /// Fill Counts with the profile data for the given function name. Returns
- /// false on success.
- bool getFunctionCounts(StringRef FuncName, std::vector<uint64_t> &Counts);
- /// Return the maximum of all known function counts.
- uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
-};
-
/// Per-function PGO state. This class should generally not be used directly,
/// but instead through the CodeGenFunction and RegionCounter types.
class CodeGenPGO {
@@ -136,8 +115,9 @@ private:
void setFuncName(llvm::Function *Fn);
void mapRegionCounters(const Decl *D);
void computeRegionCounts(const Decl *D);
- void applyFunctionAttributes(PGOProfileData *PGOData, llvm::Function *Fn);
- void loadRegionCounts(PGOProfileData *PGOData);
+ void applyFunctionAttributes(llvm::ProfileDataReader *PGOReader,
+ llvm::Function *Fn);
+ void loadRegionCounts(llvm::ProfileDataReader *PGOReader);
void emitCounterVariables();
/// Emit code to increment the counter at the given index
Modified: cfe/trunk/test/Profile/Inputs/c-attributes.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/c-attributes.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/c-attributes.profdata (original) and cfe/trunk/test/Profile/Inputs/c-attributes.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/c-counter-overflows.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/c-counter-overflows.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/c-counter-overflows.profdata (original) and cfe/trunk/test/Profile/Inputs/c-counter-overflows.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/c-general.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/c-general.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/c-general.profdata (original) and cfe/trunk/test/Profile/Inputs/c-general.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/c-outdated-data.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/c-outdated-data.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/c-outdated-data.profdata (original) and cfe/trunk/test/Profile/Inputs/c-outdated-data.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/cxx-class.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/cxx-class.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/cxx-class.profdata (original) and cfe/trunk/test/Profile/Inputs/cxx-class.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/cxx-throws.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/cxx-throws.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/cxx-throws.profdata (original) and cfe/trunk/test/Profile/Inputs/cxx-throws.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/test/Profile/Inputs/objc-general.profdata
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/Inputs/objc-general.profdata?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
Binary files cfe/trunk/test/Profile/Inputs/objc-general.profdata (original) and cfe/trunk/test/Profile/Inputs/objc-general.profdata Wed Mar 12 15:53:16 2014 differ
Modified: cfe/trunk/tools/driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/driver/CMakeLists.txt?rev=203711&r1=203710&r2=203711&view=diff
==============================================================================
--- cfe/trunk/tools/driver/CMakeLists.txt (original)
+++ cfe/trunk/tools/driver/CMakeLists.txt Wed Mar 12 15:53:16 2014
@@ -10,6 +10,7 @@ set( LLVM_LINK_COMPONENTS
MCParser
ObjCARCOpts
Option
+ Profile
ScalarOpts
Support
TransformUtils
More information about the cfe-commits
mailing list