[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