From bb227c1b798f6d91dd946a0a9db79d1941911fab Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Mon, 28 Nov 2005 18:00:38 +0000 Subject: [PATCH] Added documented rsprofiler interface. Also remove new profiler passes, the old ones have been updated to implement the interface. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24499 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/Instrumentation.h | 2 - include/llvm/Transforms/LinkAllPasses.h | 2 - include/llvm/Transforms/RSProfiling.h | 30 +++ .../Instrumentation/BlockProfiling.cpp | 8 +- .../Instrumentation/RSProfiling.cpp | 173 +++++------------- lib/Transforms/Instrumentation/RSProfiling.h | 17 +- 6 files changed, 93 insertions(+), 139 deletions(-) create mode 100644 include/llvm/Transforms/RSProfiling.h diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 84e3e54c205..bc3e9e44bae 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -44,8 +44,6 @@ ModulePass *createTraceBasicBlockPass(); FunctionPass *createProfilePathsPass(); // Random Sampling Profiling Framework -ModulePass* createBlockProfilerRSPass(); -ModulePass* createFunctionProfilerRSPass(); ModulePass* createNullProfilerRSPass(); FunctionPass* createRSProfilingPass(); diff --git a/include/llvm/Transforms/LinkAllPasses.h b/include/llvm/Transforms/LinkAllPasses.h index f9ec5f1be7b..2ec63ce4952 100644 --- a/include/llvm/Transforms/LinkAllPasses.h +++ b/include/llvm/Transforms/LinkAllPasses.h @@ -106,8 +106,6 @@ namespace { (void) llvm::createTraceValuesPassForFunction(); (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createCondPropagationPass(); - (void) llvm::createBlockProfilerRSPass(); - (void) llvm::createFunctionProfilerRSPass(); (void) llvm::createNullProfilerRSPass(); (void) llvm::createRSProfilingPass(); diff --git a/include/llvm/Transforms/RSProfiling.h b/include/llvm/Transforms/RSProfiling.h new file mode 100644 index 00000000000..897f63ef620 --- /dev/null +++ b/include/llvm/Transforms/RSProfiling.h @@ -0,0 +1,30 @@ +//===- RSProfiling.cpp - Various profiling using random sampling ----------===// +// +// 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 file defines the abstract interface that a profiler must implement to +// support the random profiling transform. +// +//===----------------------------------------------------------------------===// + +namespace llvm { + //===--------------------------------------------------------------------===// + /// RSProfilers - The basic Random Sampling Profiler Interface Any profiler + /// that implements this interface can be transformed by the random sampling + /// pass to be sample based rather than always on. + /// + /// The only exposed function can be queried to find out if an instruction + /// was original or if it was inserted by the profiler. Implementations of + /// this interface are expected to chain to other implementations, such that + /// multiple profilers can be support simultaniously. + struct RSProfilers : public ModulePass { + /// isProfiling - This method returns true if the value passed it was + /// inserted by the profiler. + virtual bool isProfiling(Value* v) = 0; + }; +}; diff --git a/lib/Transforms/Instrumentation/BlockProfiling.cpp b/lib/Transforms/Instrumentation/BlockProfiling.cpp index f92f0ef6f03..9a85fc50d1c 100644 --- a/lib/Transforms/Instrumentation/BlockProfiling.cpp +++ b/lib/Transforms/Instrumentation/BlockProfiling.cpp @@ -24,18 +24,21 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Transforms/Instrumentation.h" +#include "RSProfiling.h" #include "ProfilingUtils.h" #include using namespace llvm; namespace { - class FunctionProfiler : public ModulePass { + class FunctionProfiler : public RSProfilers_std { bool runOnModule(Module &M); }; RegisterOpt X("insert-function-profiling", "Insert instrumentation for function profiling"); + RegisterAnalysisGroup XG; + } ModulePass *llvm::createFunctionProfilerPass() { @@ -74,12 +77,13 @@ bool FunctionProfiler::runOnModule(Module &M) { namespace { - class BlockProfiler : public ModulePass { + class BlockProfiler : public RSProfilers_std { bool runOnModule(Module &M); }; RegisterOpt Y("insert-block-profiling", "Insert instrumentation for block profiling"); + RegisterAnalysisGroup YG; } ModulePass *llvm::createBlockProfilerPass() { return new BlockProfiler(); } diff --git a/lib/Transforms/Instrumentation/RSProfiling.cpp b/lib/Transforms/Instrumentation/RSProfiling.cpp index 8a3f678b9a9..bd124bb686c 100644 --- a/lib/Transforms/Instrumentation/RSProfiling.cpp +++ b/lib/Transforms/Instrumentation/RSProfiling.cpp @@ -10,7 +10,9 @@ // These passes implement a random sampling based profiling. Different methods // of choosing when to sample are supported, as well as different types of // profiling. This is done as two passes. The first is a sequence of profiling -// passes which insert profiling into the program, and remember what they inserted. +// passes which insert profiling into the program, and remember what they +// inserted. +// // The second stage duplicates all instructions in a function, ignoring the // profiling code, then connects the two versions togeather at the entry and at // backedges. At each connection point a choice is made as to whether to jump @@ -31,9 +33,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Pass.h" -#include "llvm/Function.h" #include "llvm/Module.h" -#include "llvm/BasicBlock.h" #include "llvm/Instructions.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -43,7 +43,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Instrumentation.h" -#include "ProfilingUtils.h" +//#include "ProfilingUtils.h" #include "RSProfiling.h" #include @@ -65,19 +65,11 @@ namespace { cl::desc("How to randomly choose to profile:"), cl::values( clEnumValN(GBV, "global", "global counter"), - clEnumValN(GBVO, "ra_global", "register allocated global counter"), + clEnumValN(GBVO, "ra_global", + "register allocated global counter"), clEnumValN(HOSTCC, "rdcc", "cycle counter"), clEnumValEnd)); - - class FunctionProfilerRS : public RSProfilers { - bool runOnModule(Module &M); - }; - - class BlockProfilerRS : public RSProfilers { - bool runOnModule(Module &M); - }; - class NullProfilerRS : public RSProfilers { public: bool isProfiling(Value* v) { @@ -93,15 +85,8 @@ namespace { static RegisterAnalysisGroup A("Profiling passes"); static RegisterOpt NP("insert-null-profiling-rs", - "Measure profiling framework overhead"); + "Measure profiling framework overhead"); static RegisterAnalysisGroup NPT; - static RegisterOpt BBP("insert-block-profiling-rs", - "Add block count instrumentation"); - static RegisterAnalysisGroup BBPT; - static RegisterOpt FP("insert-function-profiling-rs", - "Add function count instrumentation"); - static RegisterAnalysisGroup FPT; - //Something that chooses how to sample class Chooser { @@ -160,7 +145,7 @@ namespace { }; RegisterOpt X("insert-rs-profiling-framework", - "Insert random sampling instrumentation framework"); + "Insert random sampling instrumentation framework"); }; //Local utilities @@ -203,17 +188,18 @@ void GlobalRandomCounter::ProcessChoicePoint(BasicBlock* bb) { //decrement counter LoadInst* l = new LoadInst(Counter, "counter", t); - SetCondInst* s = new SetCondInst(Instruction::SetEQ, l, ConstantUInt::get(T, 0), + SetCondInst* s = new SetCondInst(Instruction::SetEQ, l, + ConstantUInt::get(T, 0), "countercc", t); - Value* nv = BinaryOperator::create(Instruction::Sub, l, - ConstantInt::get(T, 1), + Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1), "counternew", t); new StoreInst(nv, Counter, t); t->setCondition(s); //reset counter BasicBlock* oldnext = t->getSuccessor(0); - BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(), oldnext); + BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(), + oldnext); TerminatorInst* t2 = new BranchInst(oldnext, resetblock); t->setSuccessor(0, resetblock); new StoreInst(ResetValue, Counter, t2); @@ -274,17 +260,18 @@ void GlobalRandomCounterOpt::ProcessChoicePoint(BasicBlock* bb) { //decrement counter LoadInst* l = new LoadInst(AI, "counter", t); - SetCondInst* s = new SetCondInst(Instruction::SetEQ, l, ConstantUInt::get(T, 0), + SetCondInst* s = new SetCondInst(Instruction::SetEQ, l, + ConstantUInt::get(T, 0), "countercc", t); - Value* nv = BinaryOperator::create(Instruction::Sub, l, - ConstantInt::get(T, 1), + Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1), "counternew", t); new StoreInst(nv, AI, t); t->setCondition(s); //reset counter BasicBlock* oldnext = t->getSuccessor(0); - BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(), oldnext); + BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(), + oldnext); TerminatorInst* t2 = new BranchInst(oldnext, resetblock); t->setSuccessor(0, resetblock); new StoreInst(ResetValue, AI, t2); @@ -304,9 +291,12 @@ void CycleCounter::ProcessChoicePoint(BasicBlock* bb) { BranchInst* t = cast(bb->getTerminator()); CallInst* c = new CallInst(F, "rdcc", t); - BinaryOperator* b = BinaryOperator::create(Instruction::And, c, ConstantUInt::get(Type::ULongTy, rm), "mrdcc", t); + BinaryOperator* b = + BinaryOperator::createAnd(c, ConstantUInt::get(Type::ULongTy, rm), + "mrdcc", t); - SetCondInst* s = new SetCondInst(Instruction::SetEQ, b, ConstantUInt::get(Type::ULongTy, 0), + SetCondInst* s = new SetCondInst(Instruction::SetEQ, b, + ConstantUInt::get(Type::ULongTy, 0), "mrdccc", t); t->setCondition(s); } @@ -314,7 +304,7 @@ void CycleCounter::ProcessChoicePoint(BasicBlock* bb) { /////////////////////////////////////// // Profiling: /////////////////////////////////////// -bool RSProfilers::isProfiling(Value* v) { +bool RSProfilers_std::isProfiling(Value* v) { if (profcode.find(v) != profcode.end()) return true; //else @@ -322,7 +312,7 @@ bool RSProfilers::isProfiling(Value* v) { return LI.isProfiling(v); } -void RSProfilers::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, +void RSProfilers_std::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, GlobalValue *CounterArray) { // Insert the increment after any alloca or PHI instructions... BasicBlock::iterator InsertPos = BB->begin(); @@ -338,77 +328,18 @@ void RSProfilers::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, // Load, increment and store the value back. Value *OldVal = new LoadInst(ElementPtr, "OldCounter", InsertPos); profcode.insert(OldVal); - Value *NewVal = BinaryOperator::create(Instruction::Add, OldVal, - ConstantInt::get(Type::UIntTy, 1), - "NewCounter", InsertPos); + Value *NewVal = BinaryOperator::createAdd(OldVal, + ConstantInt::get(Type::UIntTy, 1), + "NewCounter", InsertPos); profcode.insert(NewVal); profcode.insert(new StoreInst(NewVal, ElementPtr, InsertPos)); } -void RSProfilers::getAnalysisUsage(AnalysisUsage &AU) const { +void RSProfilers_std::getAnalysisUsage(AnalysisUsage &AU) const { //grab any outstanding profiler, or get the null one AU.addRequired(); } -bool FunctionProfilerRS::runOnModule(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); - - // 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 - IncrementCounterInBlock(I->begin(), i++, Counters); - - // Add the initialization call to main. - InsertProfilingInitCall(Main, "llvm_start_func_profiling", Counters); - return true; -} - -bool BlockProfilerRS::runOnModule(Module &M) { - Function *Main = M.getMainFunction(); - if (Main == 0) { - std::cerr << "WARNING: cannot insert block profiling into a module" - << " with no main function!\n"; - return false; // No main, no instrumentation! - } - - unsigned NumBlocks = 0; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - NumBlocks += I->size(); - - const Type *ATy = ArrayType::get(Type::UIntTy, NumBlocks); - GlobalVariable *Counters = - new GlobalVariable(ATy, false, GlobalValue::InternalLinkage, - Constant::getNullValue(ATy), "BlockProfCounters", &M); - - // Instrument all of the blocks... - unsigned i = 0; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB) - // Insert counter at the start of the block - IncrementCounterInBlock(BB, i++, Counters); - - // Add the initialization call to main. - InsertProfilingInitCall(Main, "llvm_start_block_profiling", Counters); - return true; -} - /////////////////////////////////////// // RS Framework /////////////////////////////////////// @@ -421,7 +352,8 @@ Value* ProfilerRS::Translate(Value* v) { if (bb == &bb->getParent()->getEntryBlock()) TransCache[bb] = bb; //don't translate entry block else - TransCache[bb] = new BasicBlock("dup_" + bb->getName(), bb->getParent(), NULL); + TransCache[bb] = new BasicBlock("dup_" + bb->getName(), bb->getParent(), + NULL); return TransCache[bb]; } else if (Instruction* i = dyn_cast(v)) { //we have already translated this @@ -510,13 +442,14 @@ void ProfilerRS::ProcessBackEdge(BasicBlock* src, BasicBlock* dst, Function& F) //a: BasicBlock* bbC = new BasicBlock("choice", &F, src->getNext() ); //ChoicePoints.insert(bbC); - BasicBlock* bbCp = new BasicBlock("choice", &F, cast(Translate(src))->getNext() ); + BasicBlock* bbCp = + new BasicBlock("choice", &F, cast(Translate(src))->getNext() ); ChoicePoints.insert(bbCp); //b: - //new BranchInst(dst, cast(Translate(dst)), ConstantBool::get(true), bbC); new BranchInst(cast(Translate(dst)), bbC); - new BranchInst(dst, cast(Translate(dst)), ConstantBool::get(true), bbCp); + new BranchInst(dst, cast(Translate(dst)), + ConstantBool::get(true), bbCp); //c: { TerminatorInst* iB = src->getTerminator(); @@ -537,7 +470,8 @@ void ProfilerRS::ProcessBackEdge(BasicBlock* src, BasicBlock* dst, Function& F) //thus collapse those edges int the Phi CollapsePhi(dst, bbC); //f: - ReplacePhiPred(cast(Translate(dst)),cast(Translate(src)),bbCp); + ReplacePhiPred(cast(Translate(dst)), + cast(Translate(src)),bbCp); CollapsePhi(cast(Translate(dst)), bbCp); //g: for(BasicBlock::iterator ib = dst->begin(), ie = dst->end(); ib != ie; @@ -546,7 +480,8 @@ void ProfilerRS::ProcessBackEdge(BasicBlock* src, BasicBlock* dst, Function& F) for(unsigned x = 0; x < phi->getNumIncomingValues(); ++x) if(bbC == phi->getIncomingBlock(x)) { phi->addIncoming(Translate(phi->getIncomingValue(x)), bbCp); - cast(Translate(phi))->addIncoming(phi->getIncomingValue(x), bbC); + cast(Translate(phi))->addIncoming(phi->getIncomingValue(x), + bbC); } phi->removeIncomingValue(bbC); } @@ -558,23 +493,19 @@ bool ProfilerRS::runOnFunction(Function& F) { RSProfilers& LI = getAnalysis(); getBackEdges(F, BackEdges); - DEBUG( - for (std::set >::iterator ii = BackEdges.begin(); - ii != BackEdges.end(); ++ii) - std::cerr << ii->first->getName() << " -> " << ii->second->getName() << "\n"; - ); Duplicate(F, LI); //assume that stuff worked. now connect the duplicated basic blocks //with the originals in such a way as to preserve ssa. yuk! - for (std::set >::iterator ib = BackEdges.begin(), - ie = BackEdges.end(); ib != ie; ++ib) + for (std::set >::iterator + ib = BackEdges.begin(), ie = BackEdges.end(); ib != ie; ++ib) ProcessBackEdge(ib->first, ib->second, F); - //oh, and add the edge from the reg2mem created entry node to the duplicated second node + //oh, and add the edge from the reg2mem created entry node to the + //duplicated second node TerminatorInst* T = F.getEntryBlock().getTerminator(); ReplaceInstWithInst(T, new BranchInst(T->getSuccessor(0), - cast(Translate(T->getSuccessor(0))), - ConstantBool::get(true))); + cast(Translate(T->getSuccessor(0))), + ConstantBool::get(true))); //do whatever is needed now that the function is duplicated c->PrepFunction(&F); @@ -582,8 +513,8 @@ bool ProfilerRS::runOnFunction(Function& F) { //add entry node to choice points ChoicePoints.insert(&F.getEntryBlock()); - for (std::set::iterator ii = ChoicePoints.begin(), ie = ChoicePoints.end(); - ii != ie; ++ii) + for (std::set::iterator + ii = ChoicePoints.begin(), ie = ChoicePoints.end(); ii != ie; ++ii) c->ProcessChoicePoint(*ii); ChoicePoints.clear(); @@ -636,7 +567,7 @@ static void CollapsePhi(BasicBlock* btarget, BasicBlock* bsrc) { std::map counter; for(unsigned i = 0; i < phi->getNumIncomingValues(); ) { if (counter[phi->getIncomingBlock(i)]) { - assert (phi->getIncomingValue(i) == counter[phi->getIncomingBlock(i)]); + assert(phi->getIncomingValue(i) == counter[phi->getIncomingBlock(i)]); phi->removeIncomingValue(i, false); } else { counter[phi->getIncomingBlock(i)] = phi->getIncomingValue(i); @@ -686,14 +617,6 @@ static void getBackEdges(Function& F, T& BackEdges) { //Creation functions -ModulePass* llvm::createBlockProfilerRSPass() { - return new BlockProfilerRS(); -} - -ModulePass* llvm::createFunctionProfilerRSPass() { - return new FunctionProfilerRS(); -} - ModulePass* llvm::createNullProfilerRSPass() { return new NullProfilerRS(); } diff --git a/lib/Transforms/Instrumentation/RSProfiling.h b/lib/Transforms/Instrumentation/RSProfiling.h index 3ab125493b9..304ce08f7b3 100644 --- a/lib/Transforms/Instrumentation/RSProfiling.h +++ b/lib/Transforms/Instrumentation/RSProfiling.h @@ -1,4 +1,4 @@ -//===- RSProfiling.cpp - Various profiling using random sampling ----------===// +//===- RSProfiling.h - Various profiling using random sampling ----------===// // // The LLVM Compiler Infrastructure // @@ -10,18 +10,19 @@ // See notes in RSProfiling.cpp // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/RSProfiling.h" namespace llvm { - // By default, we provide some convienence stuff to clients, so they - // can just store the instructions they create to do profiling. - // also, handle all chaining issues. - // a client is free to overwrite these, as long as it implements the - // chaining itself. - struct RSProfilers : public ModulePass { + /// RSProfilers_std - a simple support class for profilers that handles most + /// of the work of chaining and tracking inserted code. + struct RSProfilers_std : public RSProfilers { std::set profcode; + // Lookup up values in profcode virtual bool isProfiling(Value* v); - virtual ~RSProfilers() {} + // handles required chaining virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // places counter updates in basic blocks and recordes added instructions in + // profcode void IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, GlobalValue *CounterArray); }; -- 2.34.1