<div class="gmail_quote">On 12 April 2011 08:55, Jim Grosbach <span dir="ltr"><<a href="mailto:grosbach@apple.com">grosbach@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

Hi Nick,<br>
<br>
clang is issuing a warning for this. Mind having a look?<br></blockquote><div><br></div><div>Sorry! I meant for counter to be a uint64_t, and updated that. Neither gcc nor clang warned when I built it this time, but I could imagine that it still might on a different platform. Let me know if it's not fixed past r129380.</div>

<div><br></div><div>Nick</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC)<br>
/Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: warning:<br>
      conversion specifies type 'unsigned long' but the argument has type<br>
      'int64_t' (aka 'long long') [-Wformat]<br>
<div class="im">  printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter);<br>
</div>                      ~~^                              ~~~~~~~~<br>
                      %lld<br>
1 warning generated.<br>
<br>
(highlighting points to the "%lu" and "*counter" inputs)<br>
<font color="#888888"><br>
-Jim<br>
</font><div><div></div><div class="h5"><br>
On Apr 11, 2011, at 6:06 PM, Nick Lewycky wrote:<br>
<br>
> Author: nicholas<br>
> Date: Mon Apr 11 20:06:09 2011<br>
> New Revision: 129340<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=129340&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=129340&view=rev</a><br>
> Log:<br>
> Add support for line profiling. Very work-in-progress.<br>
><br>
> Use debug info in the IR to find the directory/file:line:col. Each time that location changes, bump a counter.<br>
><br>
> 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.<br>


><br>
> 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.<br>
><br>
> Added:<br>
>    llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp<br>
>    llvm/trunk/runtime/libprofile/LineProfiling.c<br>
> Modified:<br>
>    llvm/trunk/include/llvm/InitializePasses.h<br>
>    llvm/trunk/include/llvm/LinkAllPasses.h<br>
>    llvm/trunk/include/llvm/Transforms/Instrumentation.h<br>
>    llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp<br>
>    llvm/trunk/runtime/libprofile/libprofile.exports<br>
><br>
> Modified: llvm/trunk/include/llvm/InitializePasses.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff</a><br>


> ==============================================================================<br>
> --- llvm/trunk/include/llvm/InitializePasses.h (original)<br>
> +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 20:06:09 2011<br>
> @@ -94,6 +94,7 @@<br>
> void initializeEdgeBundlesPass(PassRegistry&);<br>
> void initializeEdgeProfilerPass(PassRegistry&);<br>
> void initializePathProfilerPass(PassRegistry&);<br>
> +void initializeLineProfilerPass(PassRegistry&);<br>
> void initializeEarlyCSEPass(PassRegistry&);<br>
> void initializeExpandISelPseudosPass(PassRegistry&);<br>
> void initializeFindUsedTypesPass(PassRegistry&);<br>
><br>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff</a><br>


> ==============================================================================<br>
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)<br>
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 20:06:09 2011<br>
> @@ -70,6 +70,7 @@<br>
>       (void) llvm::createEdgeProfilerPass();<br>
>       (void) llvm::createOptimalEdgeProfilerPass();<br>
>       (void) llvm::createPathProfilerPass();<br>
> +      (void) llvm::createLineProfilerPass();<br>
>       (void) llvm::createFunctionInliningPass();<br>
>       (void) llvm::createAlwaysInlinerPass();<br>
>       (void) llvm::createGlobalDCEPass();<br>
><br>
> Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff</a><br>


> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original)<br>
> +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Mon Apr 11 20:06:09 2011<br>
> @@ -17,7 +17,6 @@<br>
> namespace llvm {<br>
><br>
> class ModulePass;<br>
> -class FunctionPass;<br>
><br>
> // Insert edge profiling instrumentation<br>
> ModulePass *createEdgeProfilerPass();<br>
> @@ -28,6 +27,9 @@<br>
> // Insert path profiling instrumentation<br>
> ModulePass *createPathProfilerPass();<br>
><br>
> +// Insert line profiling instrumentation<br>
> +ModulePass *createLineProfilerPass();<br>
> +<br>
> } // End llvm namespace<br>
><br>
> #endif<br>
><br>
> Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff</a><br>


> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original)<br>
> +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Mon Apr 11 20:06:09 2011<br>
> @@ -23,6 +23,7 @@<br>
>   initializeEdgeProfilerPass(Registry);<br>
>   initializeOptimalEdgeProfilerPass(Registry);<br>
>   initializePathProfilerPass(Registry);<br>
> +  initializeLineProfilerPass(Registry);<br>
> }<br>
><br>
> /// LLVMInitializeInstrumentation - C binding for<br>
><br>
> Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto</a><br>


> ==============================================================================<br>
> --- llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp (added)<br>
> +++ llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp Mon Apr 11 20:06:09 2011<br>
> @@ -0,0 +1,217 @@<br>
> +//===- LineProfiling.cpp - Insert counters for line profiling -------------===//<br>
> +//<br>
> +//                      The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +// This pass creates counters for the number of times that the original source<br>
> +// lines of code were executed.<br>
> +//<br>
> +// The lines are found from existing debug info in the LLVM IR. Iterating<br>
> +// through LLVM instructions, every time the debug location changes we insert a<br>
> +// new counter and instructions to increment the counter there. A global<br>
> +// destructor runs to dump the counters out to a file.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#define DEBUG_TYPE "insert-line-profiling"<br>
> +<br>
> +#include "ProfilingUtils.h"<br>
> +#include "llvm/Transforms/Instrumentation.h"<br>
> +#include "llvm/Analysis/DebugInfo.h"<br>
> +#include "llvm/Module.h"<br>
> +#include "llvm/Pass.h"<br>
> +#include "llvm/Instructions.h"<br>
> +#include "llvm/Support/raw_ostream.h"<br>
> +#include "llvm/Support/Debug.h"<br>
> +#include "llvm/Support/DebugLoc.h"<br>
> +#include "llvm/Support/InstIterator.h"<br>
> +#include "llvm/Support/IRBuilder.h"<br>
> +#include "llvm/ADT/DenseMap.h"<br>
> +#include "llvm/ADT/Statistic.h"<br>
> +#include "llvm/ADT/StringExtras.h"<br>
> +#include <set><br>
> +#include <string><br>
> +using namespace llvm;<br>
> +<br>
> +STATISTIC(NumUpdatesInserted, "The # of counter increments inserted.");<br>
> +<br>
> +namespace {<br>
> +  class LineProfiler : public ModulePass {<br>
> +    bool runOnModule(Module &M);<br>
> +  public:<br>
> +    static char ID;<br>
> +    LineProfiler() : ModulePass(ID) {<br>
> +      initializeLineProfilerPass(*PassRegistry::getPassRegistry());<br>
> +    }<br>
> +    virtual const char *getPassName() const {<br>
> +      return "Line Profiler";<br>
> +    }<br>
> +<br>
> +  private:<br>
> +    // Get pointers to the functions in the runtime library.<br>
> +    Constant *getStartFileFunc();<br>
> +    Constant *getCounterFunc();<br>
> +    Constant *getEndFileFunc();<br>
> +<br>
> +    // Insert an increment of the counter before instruction I.<br>
> +    void InsertCounterUpdateBefore(Instruction *I);<br>
> +<br>
> +    // Add the function to write out all our counters to the global destructor<br>
> +    // list.<br>
> +    void InsertCounterWriteout();<br>
> +<br>
> +    // Mapping from the source location to the counter tracking that location.<br>
> +    DenseMap<DebugLoc, GlobalVariable *> counters;<br>
> +<br>
> +    Module *Mod;<br>
> +    LLVMContext *Ctx;<br>
> +  };<br>
> +}<br>
> +<br>
> +char LineProfiler::ID = 0;<br>
> +INITIALIZE_PASS(LineProfiler, "insert-line-profiling",<br>
> +                "Insert instrumentation for line profiling", false, false)<br>
> +<br>
> +ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); }<br>
> +<br>
> +bool LineProfiler::runOnModule(Module &M) {<br>
> +  Mod = &M;<br>
> +  Ctx = &M.getContext();<br>
> +<br>
> +  DebugLoc last_line;  // initializes to unknown<br>
> +  bool Changed = false;<br>
> +  for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {<br>
> +    for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) {<br>
> +      const DebugLoc &loc = II->getDebugLoc();<br>
> +      if (loc.isUnknown()) continue;<br>
> +      if (loc == last_line) continue;<br>
> +      last_line = loc;<br>
> +<br>
> +      InsertCounterUpdateBefore(&*II);<br>
> +      ++NumUpdatesInserted;<br>
> +      Changed = true;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  if (Changed) {<br>
> +    InsertCounterWriteout();<br>
> +  }<br>
> +<br>
> +  return Changed;<br>
> +}<br>
> +<br>
> +void LineProfiler::InsertCounterUpdateBefore(Instruction *I) {<br>
> +  const DebugLoc &loc = I->getDebugLoc();<br>
> +  GlobalVariable *&counter = counters[loc];<br>
> +  const Type *Int64Ty = Type::getInt64Ty(*Ctx);<br>
> +  if (!counter) {<br>
> +    counter = new GlobalVariable(*Mod, Int64Ty, false,<br>
> +                                 GlobalValue::InternalLinkage,<br>
> +                                 Constant::getNullValue(Int64Ty),<br>
> +                                 "__llvm_prof_linecov_ctr", 0, false, 0);<br>
> +    counter->setVisibility(GlobalVariable::HiddenVisibility);<br>
> +    counter->setUnnamedAddr(true);<br>
> +  }<br>
> +<br>
> +  if (isa<PHINode>(I)) {<br>
> +    // We may not error out or crash in this case, because a module could put<br>
> +    // changing line numbers on phi nodes and still pass the verifier.<br>
> +    dbgs() << "Refusing to insert code before phi: " << *I << "\n";<br>
> +    I = I->getParent()->getFirstNonPHI();<br>
> +  }<br>
> +<br>
> +  IRBuilder<> builder(I);<br>
> +  Value *ctr = builder.CreateLoad(counter);<br>
> +  ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1));<br>
> +  builder.CreateStore(ctr, counter);<br>
> +}<br>
> +<br>
> +static DISubprogram FindSubprogram(DIScope scope) {<br>
> +  while (!scope.isSubprogram()) {<br>
> +    assert(scope.isLexicalBlock() &&<br>
> +           "Debug location not lexical block or subprogram");<br>
> +    scope = DILexicalBlock(scope).getContext();<br>
> +  }<br>
> +  return DISubprogram(scope);<br>
> +}<br>
> +<br>
> +Constant *LineProfiler::getStartFileFunc() {<br>
> +  const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) };<br>
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),<br>
> +                                              Args, false);<br>
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy);<br>
> +}<br>
> +<br>
> +Constant *LineProfiler::getCounterFunc() {<br>
> +  const Type *Args[] = {<br>
> +    Type::getInt8PtrTy(*Ctx),   // const char *dir<br>
> +    Type::getInt8PtrTy(*Ctx),   // const char *file<br>
> +    Type::getInt32Ty(*Ctx),     // uint32_t line<br>
> +    Type::getInt32Ty(*Ctx),     // uint32_t column<br>
> +    Type::getInt64PtrTy(*Ctx),  // int64_t *counter<br>
> +  };<br>
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),<br>
> +                                              Args, false);<br>
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", FTy);<br>
> +}<br>
> +<br>
> +Constant *LineProfiler::getEndFileFunc() {<br>
> +  const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);<br>
> +  return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy);<br>
> +}<br>
> +<br>
> +void LineProfiler::InsertCounterWriteout() {<br>
> +  std::set<std::string> compile_units;<br>
> +  for (DenseMap<DebugLoc, GlobalVariable *>::iterator I = counters.begin(),<br>
> +           E = counters.end(); I != E; ++I) {<br>
> +    const DebugLoc &loc = I->first;<br>
> +    DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));<br>
> +    compile_units.insert(subprogram.getCompileUnit().getFilename().str());<br>
> +  }<br>
> +<br>
> +  const FunctionType *WriteoutFTy =<br>
> +      FunctionType::get(Type::getVoidTy(*Ctx), false);<br>
> +  Function *WriteoutF = Function::Create(WriteoutFTy,<br>
> +                                         GlobalValue::InternalLinkage,<br>
> +                                         "__llvm_prof_linecov_dtor",<br>
> +                                         Mod);<br>
> +  WriteoutF->setUnnamedAddr(true);<br>
> +  BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);<br>
> +  IRBuilder<> builder(BB);<br>
> +<br>
> +  Constant *StartFile = getStartFileFunc();<br>
> +  Constant *EmitCounter = getCounterFunc();<br>
> +  Constant *EndFile = getEndFileFunc();<br>
> +<br>
> +  for (std::set<std::string>::const_iterator CUI = compile_units.begin(),<br>
> +           CUE = compile_units.end(); CUI != CUE; ++CUI) {<br>
> +    builder.CreateCall(StartFile,<br>
> +                       builder.CreateGlobalStringPtr(*CUI));<br>
> +    for (DenseMap<DebugLoc, GlobalVariable *>::iterator I = counters.begin(),<br>
> +             E = counters.end(); I != E; ++I) {<br>
> +      const DebugLoc &loc = I->first;<br>
> +      DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));<br>
> +      DICompileUnit compileunit(subprogram.getCompileUnit());<br>
> +<br>
> +      if (compileunit.getFilename() != *CUI)<br>
> +        continue;<br>
> +<br>
> +      Value *Args[] = {<br>
> +        builder.CreateGlobalStringPtr(subprogram.getDirectory()),<br>
> +        builder.CreateGlobalStringPtr(subprogram.getFilename()),<br>
> +        ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()),<br>
> +        ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()),<br>
> +        I->second<br>
> +      };<br>
> +      builder.CreateCall(EmitCounter, Args);<br>
> +    }<br>
> +    builder.CreateCall(EndFile);<br>
> +  }<br>
> +  builder.CreateRetVoid();<br>
> +<br>
> +  InsertProfilingShutdownCall(WriteoutF, Mod);<br>
> +}<br>
><br>
> Added: llvm/trunk/runtime/libprofile/LineProfiling.c<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto</a><br>


> ==============================================================================<br>
> --- llvm/trunk/runtime/libprofile/LineProfiling.c (added)<br>
> +++ llvm/trunk/runtime/libprofile/LineProfiling.c Mon Apr 11 20:06:09 2011<br>
> @@ -0,0 +1,37 @@<br>
> +/*===- LineProfiling.c - Support library for line profiling ---------------===*\<br>
> +|*<br>
> +|*                     The LLVM Compiler Infrastructure<br>
> +|*<br>
> +|* This file is distributed under the University of Illinois Open Source<br>
> +|* License. See LICENSE.TXT for details.<br>
> +|*<br>
> +|*===----------------------------------------------------------------------===*|<br>
> +|*<br>
> +|* This file implements the call back routines for the line profiling<br>
> +|* instrumentation pass. Link against this library when running code through<br>
> +|* the -insert-line-profiling LLVM pass.<br>
> +|*<br>
> +\*===----------------------------------------------------------------------===*/<br>
> +<br>
> +#include <stdlib.h><br>
> +#include <stdio.h><br>
> +#include <stdint.h><br>
> +<br>
> +/* A file in this case is a translation unit. Each .o file built with line<br>
> + * profiling enabled will emit to a different file. Only one file may be<br>
> + * started at a time.<br>
> + */<br>
> +void llvm_prof_linectr_start_file(const char *orig_filename) {<br>
> +  printf("[%s]\n", orig_filename);<br>
> +}<br>
> +<br>
> +/* Emit data about a counter to the data file. */<br>
> +void llvm_prof_linectr_emit_counter(const char *dir, const char *file,<br>
> +                                    uint32_t line, uint32_t column,<br>
> +                                    int64_t *counter) {<br>
> +  printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter);<br>
> +}<br>
> +<br>
> +void llvm_prof_linectr_end_file() {<br>
> +  printf("-----\n");<br>
> +}<br>
><br>
> Modified: llvm/trunk/runtime/libprofile/libprofile.exports<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff</a><br>


> ==============================================================================<br>
> --- llvm/trunk/runtime/libprofile/libprofile.exports (original)<br>
> +++ llvm/trunk/runtime/libprofile/libprofile.exports Mon Apr 11 20:06:09 2011<br>
> @@ -5,3 +5,6 @@<br>
> llvm_trace_basic_block<br>
> llvm_increment_path_count<br>
> llvm_decrement_path_count<br>
> +llvm_prof_linectr_start_file<br>
> +llvm_prof_linectr_emit_counter<br>
> +llvm_prof_linectr_end_file<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br>