ProfilingUtils.cpp revision 7cbd8a3e92221437048b484d5ef9c0a22d0f8c58
1//===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements a few helper functions which are used by profile 11// instrumentation code to instrument the code. This allows the profiler pass 12// to worry about *what* to insert, and these functions take care of *how* to do 13// it. 14// 15//===----------------------------------------------------------------------===// 16 17#include "ProfilingUtils.h" 18#include "llvm/Constants.h" 19#include "llvm/DerivedTypes.h" 20#include "llvm/Instructions.h" 21#include "llvm/Module.h" 22 23void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, 24 GlobalValue *Array) { 25 const Type *ArgVTy = 26 PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)); 27 const PointerType *UIntPtr = PointerType::getUnqual(Type::Int32Ty); 28 Module &M = *MainFn->getParent(); 29 Constant *InitFn = M.getOrInsertFunction(FnName, Type::Int32Ty, Type::Int32Ty, 30 ArgVTy, UIntPtr, Type::Int32Ty, 31 (Type *)0); 32 33 // This could force argc and argv into programs that wouldn't otherwise have 34 // them, but instead we just pass null values in. 35 std::vector<Value*> Args(4); 36 Args[0] = Constant::getNullValue(Type::Int32Ty); 37 Args[1] = Constant::getNullValue(ArgVTy); 38 39 // Skip over any allocas in the entry block. 40 BasicBlock *Entry = MainFn->begin(); 41 BasicBlock::iterator InsertPos = Entry->begin(); 42 while (isa<AllocaInst>(InsertPos)) ++InsertPos; 43 44 std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::Int32Ty)); 45 unsigned NumElements = 0; 46 if (Array) { 47 Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0], 48 GEPIndices.size()); 49 NumElements = 50 cast<ArrayType>(Array->getType()->getElementType())->getNumElements(); 51 } else { 52 // If this profiling instrumentation doesn't have a constant array, just 53 // pass null. 54 Args[2] = ConstantPointerNull::get(UIntPtr); 55 } 56 Args[3] = ConstantInt::get(Type::Int32Ty, NumElements); 57 58 Instruction *InitCall = CallInst::Create(InitFn, Args.begin(), Args.end(), 59 "newargc", InsertPos); 60 61 // If argc or argv are not available in main, just pass null values in. 62 Function::arg_iterator AI; 63 switch (MainFn->arg_size()) { 64 default: 65 case 2: 66 AI = MainFn->arg_begin(); ++AI; 67 if (AI->getType() != ArgVTy) { 68 Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy, 69 false); 70 InitCall->setOperand(2, 71 CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall)); 72 } else { 73 InitCall->setOperand(2, AI); 74 } 75 /* FALL THROUGH */ 76 77 case 1: 78 AI = MainFn->arg_begin(); 79 // If the program looked at argc, have it look at the return value of the 80 // init call instead. 81 if (AI->getType() != Type::Int32Ty) { 82 Instruction::CastOps opcode; 83 if (!AI->use_empty()) { 84 opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true); 85 AI->replaceAllUsesWith( 86 CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos)); 87 } 88 opcode = CastInst::getCastOpcode(AI, true, Type::Int32Ty, true); 89 InitCall->setOperand(1, 90 CastInst::Create(opcode, AI, Type::Int32Ty, "argc.cast", InitCall)); 91 } else { 92 AI->replaceAllUsesWith(InitCall); 93 InitCall->setOperand(1, AI); 94 } 95 96 case 0: break; 97 } 98} 99 100void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, 101 GlobalValue *CounterArray) { 102 // Insert the increment after any alloca or PHI instructions... 103 BasicBlock::iterator InsertPos = BB->begin(); 104 while (isa<AllocaInst>(InsertPos) || isa<PHINode>(InsertPos)) 105 ++InsertPos; 106 107 // Create the getelementptr constant expression 108 std::vector<Constant*> Indices(2); 109 Indices[0] = Constant::getNullValue(Type::Int32Ty); 110 Indices[1] = ConstantInt::get(Type::Int32Ty, CounterNum); 111 Constant *ElementPtr = 112 ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], Indices.size()); 113 114 // Load, increment and store the value back. 115 Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); 116 Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal, 117 ConstantInt::get(Type::Int32Ty, 1), 118 "NewFuncCounter", InsertPos); 119 new StoreInst(NewVal, ElementPtr, InsertPos); 120} 121