diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 15 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 152 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.h | 27 | ||||
-rw-r--r-- | clang/tools/driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/tools/driver/Makefile | 2 |
7 files changed, 33 insertions, 178 deletions
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 12cb1ab2559..0d49a0951c9 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS Linker MC ObjCARCOpts + ProfileData ScalarOpts Support Target diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d4daaa55c79..69a9092e1c4 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -47,6 +47,7 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" @@ -78,7 +79,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, 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), @@ -134,8 +135,14 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, 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::IndexedInstrProfReader::create( + CodeGenOpts.InstrProfileInput, PGOReader)) { + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "Could not read profile: %0"); + getDiags().Report(DiagID) << EC.message(); + } + } } CodeGenModule::~CodeGenModule() { @@ -286,7 +293,7 @@ void CodeGenModule::Release() { if (getCodeGenOpts().ProfileInstrGenerate) if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this)) AddGlobalCtor(PGOInit, 0); - if (PGOData && PGOStats.isOutOfDate()) + if (PGOReader && PGOStats.isOutOfDate()) getDiags().Report(diag::warn_profile_data_out_of_date) << PGOStats.Visited << PGOStats.Missing << PGOStats.Mismatched; EmitCtorList(GlobalCtors, "llvm.global_ctors"); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index f6614dd44bd..0fd325b083b 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -42,6 +42,7 @@ namespace llvm { class DataLayout; class FunctionType; class LLVMContext; + class IndexedInstrProfReader; } namespace clang { @@ -85,7 +86,6 @@ namespace CodeGen { class CGCUDARuntime; class BlockFieldFlags; class FunctionArgList; - class PGOProfileData; struct OrderGlobalInits { unsigned int priority; @@ -266,7 +266,7 @@ class CodeGenModule : public CodeGenTypeCache { ARCEntrypoints *ARCData; llvm::MDNode *NoObjCARCExceptionsMetadata; RREntrypoints *RRData; - PGOProfileData *PGOData; + std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader; InstrProfStats PGOStats; // WeakRefReferences - A set of references that have only been seen via @@ -493,13 +493,8 @@ public: return *RRData; } - InstrProfStats &getPGOStats() { - return PGOStats; - } - - PGOProfileData *getPGOData() const { - return PGOData; - } + InstrProfStats &getPGOStats() { return PGOStats; } + llvm::IndexedInstrProfReader *getPGOReader() const { return PGOReader.get(); } llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) { return StaticLocalDeclMap[D]; diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 28e9c0b046f..aaeafd1a64d 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -17,6 +17,7 @@ #include "clang/AST/StmtVisitor.h" #include "llvm/Config/config.h" // for strtoull()/strtoul() define #include "llvm/IR/MDBuilder.h" +#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" @@ -24,136 +25,6 @@ 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; - } - StringRef FuncName(FuncStart, CurPtr - FuncStart); - - // Skip over the function hash. - CurPtr = strchr(++CurPtr, '\n'); - if (!CurPtr) { - ReportBadPGOData(CGM, "pgo data file is missing the function hash"); - return; - } - - // Read the number of counters. - char *EndPtr; - unsigned NumCounters = strtoul(++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 = strtoull(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, uint64_t &FuncHash, - 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"); - - char *EndPtr; - // Read the function hash. - FuncHash = strtoull(++CurPtr, &EndPtr, 10); - assert(EndPtr != CurPtr && *EndPtr == '\n' && - "pgo-data file has corrupted function hash"); - CurPtr = EndPtr; - - // Read the number of counters. - unsigned NumCounters = strtoul(++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 = strtoull(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) { RawFuncName = Fn->getName(); @@ -930,8 +801,8 @@ static void emitRuntimeHook(CodeGenModule &CGM) { void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate; - PGOProfileData *PGOData = CGM.getPGOData(); - if (!InstrumentRegions && !PGOData) + llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); + if (!InstrumentRegions && !PGOReader) return; if (!D) return; @@ -957,10 +828,10 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { emitRuntimeHook(CGM); emitCounterVariables(); } - if (PGOData) { - loadRegionCounts(PGOData); + if (PGOReader) { + loadRegionCounts(PGOReader); computeRegionCounts(D); - applyFunctionAttributes(PGOData, Fn); + applyFunctionAttributes(PGOReader, Fn); } } @@ -992,12 +863,13 @@ void CodeGenPGO::computeRegionCounts(const Decl *D) { Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); } -void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData, - llvm::Function *Fn) { +void +CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *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. @@ -1031,11 +903,11 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) { Builder.CreateStore(Count, Addr); } -void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) { +void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader) { CGM.getPGOStats().Visited++; RegionCounts.reset(new std::vector<uint64_t>); uint64_t Hash; - if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) { + if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) { CGM.getPGOStats().Missing++; RegionCounts.reset(); } else if (Hash != FunctionHash || diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index c59a58e3f89..98e5b1fd1ac 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -26,28 +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, uint64_t &FuncHash, - 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 { @@ -138,8 +116,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::IndexedInstrProfReader *PGOReader, + llvm::Function *Fn); + void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader); void emitCounterVariables(); llvm::GlobalVariable *buildDataVar(); diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt index f60162f5e10..67d2115b84b 100644 --- a/clang/tools/driver/CMakeLists.txt +++ b/clang/tools/driver/CMakeLists.txt @@ -10,6 +10,7 @@ set( LLVM_LINK_COMPONENTS MCParser ObjCARCOpts Option + ProfileData ScalarOpts Support TransformUtils diff --git a/clang/tools/driver/Makefile b/clang/tools/driver/Makefile index d75b19cf2a1..7404496875f 100644 --- a/clang/tools/driver/Makefile +++ b/clang/tools/driver/Makefile @@ -33,7 +33,7 @@ endif LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \ instrumentation ipo irreader linker objcarcopts option \ - selectiondag + profiledata selectiondag USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \ clangSerialization.a clangCodeGen.a clangParse.a clangSema.a |