From baa2007fae24930d9a309b74c63c1d0286fb5b76 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 28 Oct 2003 18:59:04 +0000 Subject: [PATCH] Initial checkin of profiling instrumentation pass. So far, despite the file name, we only support function profiling. This will be fixed in the near future. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9547 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/BlockProfiling.cpp | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 lib/Transforms/Instrumentation/BlockProfiling.cpp diff --git a/lib/Transforms/Instrumentation/BlockProfiling.cpp b/lib/Transforms/Instrumentation/BlockProfiling.cpp new file mode 100644 index 00000000000..5986ed9d134 --- /dev/null +++ b/lib/Transforms/Instrumentation/BlockProfiling.cpp @@ -0,0 +1,127 @@ +//===- BlockProfiling.cpp - Insert counters for block profiling -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments the specified program with counters for basic block or +// function profiling. This is the most basic form of profiling, which can tell +// which blocks are hot, but cannot reliably detect hot paths through the CFG. +// Block profiling counts the number of times each basic block executes, and +// function profiling counts the number of times each function is called. +// +// Note that this implementation is very naive. Control equivalent regions of +// the CFG should not require duplicate counters, but we do put duplicate +// counters in. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" + +namespace { + class FunctionProfiler : public Pass { + bool run(Module &M); + + void insertInitializationCall(Function *MainFn, const char *FnName, + GlobalValue *Array); + }; + + RegisterOpt X("insert-function-profiling", + "Insert instrumentation for function profiling"); +} + + +bool FunctionProfiler::run(Module &M) { + Function *Main = M.getMainFunction(); + if (Main == 0) { + std::cerr << "WARNING: cannot insert function profiling into a module" + << " with no main function!\n"; + return false; // No main, no instrumentation! + } + + unsigned NumFunctions = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isExternal()) + ++NumFunctions; + + const Type *ATy = ArrayType::get(Type::UIntTy, NumFunctions); + GlobalVariable *Counters = + new GlobalVariable(ATy, false, GlobalValue::InternalLinkage, + Constant::getNullValue(ATy), "FuncProfCounters", &M); + + ConstantPointerRef *CounterCPR = ConstantPointerRef::get(Counters); + std::vector GEPIndices; + GEPIndices.resize(2); + GEPIndices[0] = Constant::getNullValue(Type::LongTy); + + // Instrument all of the functions... + unsigned i = 0; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isExternal()) { + // Insert counter at the start of the function, but after any allocas. + BasicBlock *Entry = I->begin(); + BasicBlock::iterator InsertPos = Entry->begin(); + while (isa(InsertPos)) ++InsertPos; + + GEPIndices[1] = ConstantSInt::get(Type::LongTy, i++); + Constant *ElementPtr = + ConstantExpr::getGetElementPtr(CounterCPR, GEPIndices); + + Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); + Value *NewVal = BinaryOperator::create(Instruction::Add, OldVal, + ConstantInt::get(Type::UIntTy, 1), + "NewFuncCounter", InsertPos); + new StoreInst(NewVal, ElementPtr, InsertPos); + } + + // Add the initialization call to main. + insertInitializationCall(Main, "llvm_start_func_profiling", Counters); + return true; +} + +void FunctionProfiler::insertInitializationCall(Function *MainFn, + const char *FnName, + GlobalValue *Array) { + const Type *ArgVTy = PointerType::get(PointerType::get(Type::SByteTy)); + const Type *UIntPtr = PointerType::get(Type::UIntTy); + Module &M = *MainFn->getParent(); + Function *InitFn = M.getOrInsertFunction(FnName, Type::VoidTy, Type::IntTy, + ArgVTy, UIntPtr, Type::UIntTy, 0); + + // This could force argc and argv into programs that wouldn't otherwise have + // them, but instead we just pass null values in. + std::vector Args(4); + Args[0] = Constant::getNullValue(Type::IntTy); + Args[1] = Constant::getNullValue(ArgVTy); + + /* FIXME: We should pass in the command line arguments here! */ + switch (MainFn->asize()) { + default: + case 2: + case 1: + case 0: + break; + } + + ConstantPointerRef *ArrayCPR = ConstantPointerRef::get(Array); + std::vector GEPIndices(2, Constant::getNullValue(Type::LongTy)); + Args[2] = ConstantExpr::getGetElementPtr(ArrayCPR, GEPIndices); + + unsigned NumElements = + cast(Array->getType()->getElementType())->getNumElements(); + Args[3] = ConstantUInt::get(Type::UIntTy, NumElements); + + // Skip over any allocas in the entry block. + BasicBlock *Entry = MainFn->begin(); + BasicBlock::iterator InsertPos = Entry->begin(); + while (isa(InsertPos)) ++InsertPos; + + new CallInst(InitFn, Args, "", InsertPos); +} -- 2.34.1