]> granicus.if.org Git - clang/commitdiff
Revert "CodeGen: Use a binary format for instrumentation based profiling"
authorJustin Bogner <mail@justinbogner.com>
Wed, 12 Mar 2014 21:06:31 +0000 (21:06 +0000)
committerJustin Bogner <mail@justinbogner.com>
Wed, 12 Mar 2014 21:06:31 +0000 (21:06 +0000)
I've clearly done something wrong with how to get this to link
correctly. Reverting for now.

This reverts commit r203711.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203712 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/CodeGenPGO.cpp
lib/CodeGen/CodeGenPGO.h
test/Profile/Inputs/c-attributes.profdata
test/Profile/Inputs/c-counter-overflows.profdata
test/Profile/Inputs/c-general.profdata
test/Profile/Inputs/c-outdated-data.profdata
test/Profile/Inputs/cxx-class.profdata
test/Profile/Inputs/cxx-throws.profdata
test/Profile/Inputs/objc-general.profdata
tools/driver/CMakeLists.txt

index 484c4edc24b96061831a55db2e2f298a89c0a2b0..4f040e2780988b2cb8014722fd035d4c2d521d0b 100644 (file)
@@ -47,7 +47,6 @@
 #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"
 
@@ -78,7 +77,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), PGOReader(nullptr),
+      NoObjCARCExceptionsMetadata(0), RRData(0), PGOData(0),
       CFConstantStringClassRef(0),
       ConstantStringClassRef(0), NSConstantStringType(0),
       NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0),
@@ -134,14 +133,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
     ARCData = new ARCEntrypoints();
   RRData = new RREntrypoints();
 
-  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();
-    }
-  }
+  if (!CodeGenOpts.InstrProfileInput.empty())
+    PGOData = new PGOProfileData(*this, CodeGenOpts.InstrProfileInput);
 }
 
 CodeGenModule::~CodeGenModule() {
index 061ec48e3751d62fa2c428248817c839f9a667db..4bd8b7a3de7e454f198d95005b08feb5746c0ad1 100644 (file)
@@ -42,7 +42,6 @@ namespace llvm {
   class DataLayout;
   class FunctionType;
   class LLVMContext;
-  class ProfileDataReader;
 }
 
 namespace clang {
@@ -86,6 +85,7 @@ namespace CodeGen {
   class CGCUDARuntime;
   class BlockFieldFlags;
   class FunctionArgList;
+  class PGOProfileData;
 
   struct OrderGlobalInits {
     unsigned int priority;
@@ -257,7 +257,7 @@ class CodeGenModule : public CodeGenTypeCache {
   ARCEntrypoints *ARCData;
   llvm::MDNode *NoObjCARCExceptionsMetadata;
   RREntrypoints *RRData;
-  std::unique_ptr<llvm::ProfileDataReader> PGOReader;
+  PGOProfileData *PGOData;
 
   // 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;
   }
 
-  llvm::ProfileDataReader *getPGOReader() const {
-    return PGOReader.get();
+  PGOProfileData *getPGOData() const {
+    return PGOData;
   }
 
   llvm::Constant *getStaticLocalDeclAddress(const VarDecl *D) {
index abd47ccd2cb288c2bdcf2292970f3af101024a7f..3206daa76a6cc686c45769a134a25062d505fa38 100644 (file)
 #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();
 
@@ -57,23 +177,22 @@ void CodeGenPGO::emitWriteoutFunction() {
   llvm::Type *Int32Ty = llvm::Type::getInt32Ty(Ctx);
   llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
 
-  llvm::Function *AddFuncsF =
-    CGM.getModule().getFunction("__llvm_pgo_add_functions");
-  if (!AddFuncsF) {
-    llvm::FunctionType *AddFuncsFTy =
+  llvm::Function *WriteoutF =
+    CGM.getModule().getFunction("__llvm_pgo_writeout");
+  if (!WriteoutF) {
+    llvm::FunctionType *WriteoutFTy =
       llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false);
-    AddFuncsF = llvm::Function::Create(AddFuncsFTy,
+    WriteoutF = llvm::Function::Create(WriteoutFTy,
                                        llvm::GlobalValue::InternalLinkage,
-                                       "__llvm_pgo_add_functions",
-                                       &CGM.getModule());
+                                       "__llvm_pgo_writeout", &CGM.getModule());
   }
-  AddFuncsF->setUnnamedAddr(true);
-  AddFuncsF->addFnAttr(llvm::Attribute::NoInline);
+  WriteoutF->setUnnamedAddr(true);
+  WriteoutF->addFnAttr(llvm::Attribute::NoInline);
   if (CGM.getCodeGenOpts().DisableRedZone)
-    AddFuncsF->addFnAttr(llvm::Attribute::NoRedZone);
+    WriteoutF->addFnAttr(llvm::Attribute::NoRedZone);
 
-  llvm::BasicBlock *BB = AddFuncsF->empty() ?
-    llvm::BasicBlock::Create(Ctx, "", AddFuncsF) : &AddFuncsF->getEntryBlock();
+  llvm::BasicBlock *BB = WriteoutF->empty() ?
+    llvm::BasicBlock::Create(Ctx, "", WriteoutF) : &WriteoutF->getEntryBlock();
 
   CGBuilderTy PGOBuilder(BB);
 
@@ -83,35 +202,32 @@ 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_add_function", FTy);
+    CGM.getModule().getOrInsertFunction("llvm_pgo_emit", FTy);
 
   llvm::Constant *NameString =
     CGM.GetAddrOfConstantCString(getFuncName(), "__llvm_pgo_name");
   NameString = llvm::ConstantExpr::getBitCast(NameString, Int8PtrTy);
-  PGOBuilder.CreateCall4(EmitFunc, NameString,
-                         // TODO: This should be a hash, not just the count!
-                         PGOBuilder.getInt64(NumRegionCounters),
+  PGOBuilder.CreateCall3(EmitFunc, NameString,
                          PGOBuilder.getInt32(NumRegionCounters),
                          PGOBuilder.CreateBitCast(RegionCounters, Int64PtrTy));
 }
 
 llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) {
-  llvm::Function *AddFuncsF =
-    CGM.getModule().getFunction("__llvm_pgo_add_functions");
-  if (!AddFuncsF)
+  llvm::Function *WriteoutF =
+    CGM.getModule().getFunction("__llvm_pgo_writeout");
+  if (!WriteoutF)
     return NULL;
 
-  // Create a small bit of code that initializes PGO at startup
+  // Create a small bit of code that registers the "__llvm_pgo_writeout" to
+  // be executed at exit.
   llvm::Function *F = CGM.getModule().getFunction("__llvm_pgo_init");
   if (F)
     return NULL;
@@ -139,7 +255,7 @@ llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) {
   // Inialize the environment and register the local writeout function.
   llvm::Constant *PGOInit =
     CGM.getModule().getOrInsertFunction("llvm_pgo_init", FTy);
-  PGOBuilder.CreateCall(PGOInit, AddFuncsF);
+  PGOBuilder.CreateCall(PGOInit, WriteoutF);
   PGOBuilder.CreateRetVoid();
 
   return F;
@@ -642,8 +758,8 @@ namespace {
 
 void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
   bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
-  llvm::ProfileDataReader *PGOReader = CGM.getPGOReader();
-  if (!InstrumentRegions && !PGOReader)
+  PGOProfileData *PGOData = CGM.getPGOData();
+  if (!InstrumentRegions && !PGOData)
     return;
   if (!D)
     return;
@@ -651,10 +767,10 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
   mapRegionCounters(D);
   if (InstrumentRegions)
     emitCounterVariables();
-  if (PGOReader) {
-    loadRegionCounts(PGOReader);
+  if (PGOData) {
+    loadRegionCounts(PGOData);
     computeRegionCounts(D);
-    applyFunctionAttributes(PGOReader, Fn);
+    applyFunctionAttributes(PGOData, Fn);
   }
 }
 
@@ -681,12 +797,12 @@ void CodeGenPGO::computeRegionCounts(const Decl *D) {
     Walker.VisitBlockDecl(BD);
 }
 
-void CodeGenPGO::applyFunctionAttributes(llvm::ProfileDataReader *PGOReader,
+void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData,
                                          llvm::Function *Fn) {
   if (!haveRegionCounts())
     return;
 
-  uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
+  uint64_t MaxFunctionCount = PGOData->getMaximumFunctionCount();
   uint64_t FunctionCount = getRegionCount(0);
   if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
     // Turn on InlineHint attribute for hot functions.
@@ -719,15 +835,13 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
   Builder.CreateStore(Count, Addr);
 }
 
-void CodeGenPGO::loadRegionCounts(llvm::ProfileDataReader *PGOReader) {
+void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) {
   // 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>();
-  uint64_t Hash;
-  // TODO: Check for hash mismatch
-  if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts) ||
+  if (PGOData->getFunctionCounts(getFuncName(), *RegionCounts) ||
       RegionCounts->size() != NumRegionCounters) {
     delete RegionCounts;
     RegionCounts = 0;
index 7c19414a0bd4a735a673225435b748480165e177..51d59cf9a9b1c2856deb6606e11dcb52e5902ddc 100644 (file)
@@ -26,6 +26,27 @@ 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 {
@@ -115,9 +136,8 @@ private:
   void setFuncName(llvm::Function *Fn);
   void mapRegionCounters(const Decl *D);
   void computeRegionCounts(const Decl *D);
-  void applyFunctionAttributes(llvm::ProfileDataReader *PGOReader,
-                               llvm::Function *Fn);
-  void loadRegionCounts(llvm::ProfileDataReader *PGOReader);
+  void applyFunctionAttributes(PGOProfileData *PGOData, llvm::Function *Fn);
+  void loadRegionCounts(PGOProfileData *PGOData);
   void emitCounterVariables();
 
   /// Emit code to increment the counter at the given index
index 8cb0af84f0ac8ece085aedb6788c9b8b7831649e..38decbd5568a7d573261c65cf2192e11df618078 100644 (file)
Binary files a/test/Profile/Inputs/c-attributes.profdata and b/test/Profile/Inputs/c-attributes.profdata differ
index 24fc3ae3edb8cd37b6fdad3fb1c6c8f6c6e01a1b..377a08502d104179263bcf7cc5bed33dd87aebb3 100644 (file)
Binary files a/test/Profile/Inputs/c-counter-overflows.profdata and b/test/Profile/Inputs/c-counter-overflows.profdata differ
index 6a248f48dea0717b558513b5bbaaecf276e2948e..083b8fe55b4d7b61be68a2c57cc7bded95dbf5e7 100644 (file)
Binary files a/test/Profile/Inputs/c-general.profdata and b/test/Profile/Inputs/c-general.profdata differ
index 05da71603f87b18b2e20a0aad2f16ef4a0357736..e1c51a6975d393515dd1c3a391af9c417e01e61e 100644 (file)
Binary files a/test/Profile/Inputs/c-outdated-data.profdata and b/test/Profile/Inputs/c-outdated-data.profdata differ
index 713f18d147da6400a1eb2fe8075626a6d2430130..983ab5511655521d5880be823a910cbe81e4ba15 100644 (file)
Binary files a/test/Profile/Inputs/cxx-class.profdata and b/test/Profile/Inputs/cxx-class.profdata differ
index 3c0aab2b9508c9f9a828e1aa0586370105b87df0..a49522f55844498765ff073494e1d249d693768b 100644 (file)
Binary files a/test/Profile/Inputs/cxx-throws.profdata and b/test/Profile/Inputs/cxx-throws.profdata differ
index b7fa2217f7063b04d5ecbbcf96d1d905337d8a05..06c9832b3c5894546c31eb59c53457ee7738d9ea 100644 (file)
Binary files a/test/Profile/Inputs/objc-general.profdata and b/test/Profile/Inputs/objc-general.profdata differ
index 2e65bcc81b57248e9407e087b14413574c4f74bb..9442ba65da9da593e0a843626587c470a5b694bb 100644 (file)
@@ -10,7 +10,6 @@ set( LLVM_LINK_COMPONENTS
   MCParser
   ObjCARCOpts
   Option
-  Profile
   ScalarOpts
   Support
   TransformUtils