[llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling.cpp runtime/libprofile/LineProfiling.c runtime/libprofile/libprofile.exports

Jim Grosbach grosbach at apple.com
Tue Apr 12 08:55:34 PDT 2011


Hi Nick,

clang is issuing a warning for this. Mind having a look?

llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC)
/Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: warning: 
      conversion specifies type 'unsigned long' but the argument has type
      'int64_t' (aka 'long long') [-Wformat]
  printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter);
                      ~~^                              ~~~~~~~~
                      %lld
1 warning generated.

(highlighting points to the "%lu" and "*counter" inputs)

-Jim

On Apr 11, 2011, at 6:06 PM, Nick Lewycky wrote:

> Author: nicholas
> Date: Mon Apr 11 20:06:09 2011
> New Revision: 129340
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=129340&view=rev
> Log:
> Add support for line profiling. Very work-in-progress.
> 
> Use debug info in the IR to find the directory/file:line:col. Each time that location changes, bump a counter.
> 
> Unlike the existing profiling system, we don't try to look at argv[], and thusly don't require main() to be present in the IR. This matches GCC's technique where you specify the profiling flag when producing each .o file.
> 
> The runtime library is minimal, currently just calling printf at program shutdown time. The API is designed to make it possible to emit GCOV data later on.
> 
> Added:
>    llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp
>    llvm/trunk/runtime/libprofile/LineProfiling.c
> Modified:
>    llvm/trunk/include/llvm/InitializePasses.h
>    llvm/trunk/include/llvm/LinkAllPasses.h
>    llvm/trunk/include/llvm/Transforms/Instrumentation.h
>    llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
>    llvm/trunk/runtime/libprofile/libprofile.exports
> 
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 20:06:09 2011
> @@ -94,6 +94,7 @@
> void initializeEdgeBundlesPass(PassRegistry&);
> void initializeEdgeProfilerPass(PassRegistry&);
> void initializePathProfilerPass(PassRegistry&);
> +void initializeLineProfilerPass(PassRegistry&);
> void initializeEarlyCSEPass(PassRegistry&);
> void initializeExpandISelPseudosPass(PassRegistry&);
> void initializeFindUsedTypesPass(PassRegistry&);
> 
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 20:06:09 2011
> @@ -70,6 +70,7 @@
>       (void) llvm::createEdgeProfilerPass();
>       (void) llvm::createOptimalEdgeProfilerPass();
>       (void) llvm::createPathProfilerPass();
> +      (void) llvm::createLineProfilerPass();
>       (void) llvm::createFunctionInliningPass();
>       (void) llvm::createAlwaysInlinerPass();
>       (void) llvm::createGlobalDCEPass();
> 
> Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Mon Apr 11 20:06:09 2011
> @@ -17,7 +17,6 @@
> namespace llvm {
> 
> class ModulePass;
> -class FunctionPass;
> 
> // Insert edge profiling instrumentation
> ModulePass *createEdgeProfilerPass();
> @@ -28,6 +27,9 @@
> // Insert path profiling instrumentation
> ModulePass *createPathProfilerPass();
> 
> +// Insert line profiling instrumentation
> +ModulePass *createLineProfilerPass();
> +
> } // End llvm namespace
> 
> #endif
> 
> Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original)
> +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Mon Apr 11 20:06:09 2011
> @@ -23,6 +23,7 @@
>   initializeEdgeProfilerPass(Registry);
>   initializeOptimalEdgeProfilerPass(Registry);
>   initializePathProfilerPass(Registry);
> +  initializeLineProfilerPass(Registry);
> }
> 
> /// LLVMInitializeInstrumentation - C binding for
> 
> Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp (added)
> +++ llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp Mon Apr 11 20:06:09 2011
> @@ -0,0 +1,217 @@
> +//===- LineProfiling.cpp - Insert counters for line profiling -------------===//
> +//
> +//                      The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This pass creates counters for the number of times that the original source
> +// lines of code were executed.
> +//
> +// The lines are found from existing debug info in the LLVM IR. Iterating
> +// through LLVM instructions, every time the debug location changes we insert a
> +// new counter and instructions to increment the counter there. A global
> +// destructor runs to dump the counters out to a file.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "insert-line-profiling"
> +
> +#include "ProfilingUtils.h"
> +#include "llvm/Transforms/Instrumentation.h"
> +#include "llvm/Analysis/DebugInfo.h"
> +#include "llvm/Module.h"
> +#include "llvm/Pass.h"
> +#include "llvm/Instructions.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/DebugLoc.h"
> +#include "llvm/Support/InstIterator.h"
> +#include "llvm/Support/IRBuilder.h"
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/ADT/Statistic.h"
> +#include "llvm/ADT/StringExtras.h"
> +#include <set>
> +#include <string>
> +using namespace llvm;
> +
> +STATISTIC(NumUpdatesInserted, "The # of counter increments inserted.");
> +
> +namespace {
> +  class LineProfiler : public ModulePass {
> +    bool runOnModule(Module &M);
> +  public:
> +    static char ID;
> +    LineProfiler() : ModulePass(ID) {
> +      initializeLineProfilerPass(*PassRegistry::getPassRegistry());
> +    }
> +    virtual const char *getPassName() const {
> +      return "Line Profiler";
> +    }
> +
> +  private:
> +    // Get pointers to the functions in the runtime library.
> +    Constant *getStartFileFunc();
> +    Constant *getCounterFunc();
> +    Constant *getEndFileFunc();
> +
> +    // Insert an increment of the counter before instruction I.
> +    void InsertCounterUpdateBefore(Instruction *I);
> +
> +    // Add the function to write out all our counters to the global destructor
> +    // list.
> +    void InsertCounterWriteout();
> +
> +    // Mapping from the source location to the counter tracking that location.
> +    DenseMap<DebugLoc, GlobalVariable *> counters;
> +
> +    Module *Mod;
> +    LLVMContext *Ctx;
> +  };
> +}
> +
> +char LineProfiler::ID = 0;
> +INITIALIZE_PASS(LineProfiler, "insert-line-profiling",
> +                "Insert instrumentation for line profiling", false, false)
> +
> +ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); }
> +
> +bool LineProfiler::runOnModule(Module &M) {
> +  Mod = &M;
> +  Ctx = &M.getContext();
> +
> +  DebugLoc last_line;  // initializes to unknown
> +  bool Changed = false;
> +  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
> +    for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) {
> +      const DebugLoc &loc = II->getDebugLoc();
> +      if (loc.isUnknown()) continue;
> +      if (loc == last_line) continue;
> +      last_line = loc;
> +
> +      InsertCounterUpdateBefore(&*II);
> +      ++NumUpdatesInserted;
> +      Changed = true;
> +    }
> +  }
> +
> +  if (Changed) {
> +    InsertCounterWriteout();
> +  }
> +
> +  return Changed;
> +}
> +
> +void LineProfiler::InsertCounterUpdateBefore(Instruction *I) {
> +  const DebugLoc &loc = I->getDebugLoc();
> +  GlobalVariable *&counter = counters[loc];
> +  const Type *Int64Ty = Type::getInt64Ty(*Ctx);
> +  if (!counter) {
> +    counter = new GlobalVariable(*Mod, Int64Ty, false,
> +                                 GlobalValue::InternalLinkage,
> +                                 Constant::getNullValue(Int64Ty),
> +                                 "__llvm_prof_linecov_ctr", 0, false, 0);
> +    counter->setVisibility(GlobalVariable::HiddenVisibility);
> +    counter->setUnnamedAddr(true);
> +  }
> +
> +  if (isa<PHINode>(I)) {
> +    // We may not error out or crash in this case, because a module could put
> +    // changing line numbers on phi nodes and still pass the verifier.
> +    dbgs() << "Refusing to insert code before phi: " << *I << "\n";
> +    I = I->getParent()->getFirstNonPHI();
> +  }
> +
> +  IRBuilder<> builder(I);
> +  Value *ctr = builder.CreateLoad(counter);
> +  ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1));
> +  builder.CreateStore(ctr, counter);
> +}
> +
> +static DISubprogram FindSubprogram(DIScope scope) {
> +  while (!scope.isSubprogram()) {
> +    assert(scope.isLexicalBlock() &&
> +           "Debug location not lexical block or subprogram");
> +    scope = DILexicalBlock(scope).getContext();
> +  }
> +  return DISubprogram(scope);
> +}
> +
> +Constant *LineProfiler::getStartFileFunc() {
> +  const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) };
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
> +                                              Args, false);
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy);
> +}
> +
> +Constant *LineProfiler::getCounterFunc() {
> +  const Type *Args[] = {
> +    Type::getInt8PtrTy(*Ctx),   // const char *dir
> +    Type::getInt8PtrTy(*Ctx),   // const char *file
> +    Type::getInt32Ty(*Ctx),     // uint32_t line
> +    Type::getInt32Ty(*Ctx),     // uint32_t column
> +    Type::getInt64PtrTy(*Ctx),  // int64_t *counter
> +  };
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
> +                                              Args, false);
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", FTy);
> +}
> +
> +Constant *LineProfiler::getEndFileFunc() {
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy);
> +}
> +
> +void LineProfiler::InsertCounterWriteout() {
> +  std::set<std::string> compile_units;
> +  for (DenseMap<DebugLoc, GlobalVariable *>::iterator I = counters.begin(),
> +           E = counters.end(); I != E; ++I) {
> +    const DebugLoc &loc = I->first;
> +    DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));
> +    compile_units.insert(subprogram.getCompileUnit().getFilename().str());
> +  }
> +
> +  const FunctionType *WriteoutFTy =
> +      FunctionType::get(Type::getVoidTy(*Ctx), false);
> +  Function *WriteoutF = Function::Create(WriteoutFTy,
> +                                         GlobalValue::InternalLinkage,
> +                                         "__llvm_prof_linecov_dtor",
> +                                         Mod);
> +  WriteoutF->setUnnamedAddr(true);
> +  BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);
> +  IRBuilder<> builder(BB);
> +
> +  Constant *StartFile = getStartFileFunc();
> +  Constant *EmitCounter = getCounterFunc();
> +  Constant *EndFile = getEndFileFunc();
> +
> +  for (std::set<std::string>::const_iterator CUI = compile_units.begin(),
> +           CUE = compile_units.end(); CUI != CUE; ++CUI) {
> +    builder.CreateCall(StartFile,
> +                       builder.CreateGlobalStringPtr(*CUI));
> +    for (DenseMap<DebugLoc, GlobalVariable *>::iterator I = counters.begin(),
> +             E = counters.end(); I != E; ++I) {
> +      const DebugLoc &loc = I->first;
> +      DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));
> +      DICompileUnit compileunit(subprogram.getCompileUnit());
> +
> +      if (compileunit.getFilename() != *CUI)
> +        continue;
> +
> +      Value *Args[] = {
> +        builder.CreateGlobalStringPtr(subprogram.getDirectory()),
> +        builder.CreateGlobalStringPtr(subprogram.getFilename()),
> +        ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()),
> +        ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()),
> +        I->second
> +      };
> +      builder.CreateCall(EmitCounter, Args);
> +    }
> +    builder.CreateCall(EndFile);
> +  }
> +  builder.CreateRetVoid();
> +
> +  InsertProfilingShutdownCall(WriteoutF, Mod);
> +}
> 
> Added: llvm/trunk/runtime/libprofile/LineProfiling.c
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto
> ==============================================================================
> --- llvm/trunk/runtime/libprofile/LineProfiling.c (added)
> +++ llvm/trunk/runtime/libprofile/LineProfiling.c Mon Apr 11 20:06:09 2011
> @@ -0,0 +1,37 @@
> +/*===- LineProfiling.c - Support library for line profiling ---------------===*\
> +|*
> +|*                     The LLVM Compiler Infrastructure
> +|*
> +|* This file is distributed under the University of Illinois Open Source
> +|* License. See LICENSE.TXT for details.
> +|* 
> +|*===----------------------------------------------------------------------===*|
> +|* 
> +|* This file implements the call back routines for the line profiling
> +|* instrumentation pass. Link against this library when running code through
> +|* the -insert-line-profiling LLVM pass.
> +|*
> +\*===----------------------------------------------------------------------===*/
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +
> +/* A file in this case is a translation unit. Each .o file built with line
> + * profiling enabled will emit to a different file. Only one file may be
> + * started at a time.
> + */
> +void llvm_prof_linectr_start_file(const char *orig_filename) {
> +  printf("[%s]\n", orig_filename);
> +}
> +
> +/* Emit data about a counter to the data file. */
> +void llvm_prof_linectr_emit_counter(const char *dir, const char *file,
> +                                    uint32_t line, uint32_t column,
> +                                    int64_t *counter) {
> +  printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter);
> +}
> +
> +void llvm_prof_linectr_end_file() {
> +  printf("-----\n");
> +}
> 
> Modified: llvm/trunk/runtime/libprofile/libprofile.exports
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff
> ==============================================================================
> --- llvm/trunk/runtime/libprofile/libprofile.exports (original)
> +++ llvm/trunk/runtime/libprofile/libprofile.exports Mon Apr 11 20:06:09 2011
> @@ -5,3 +5,6 @@
> llvm_trace_basic_block
> llvm_increment_path_count
> llvm_decrement_path_count
> +llvm_prof_linectr_start_file
> +llvm_prof_linectr_emit_counter
> +llvm_prof_linectr_end_file
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list