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