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