From: Junyan He <[email protected]> We now can insert profiling point based on the line number.
Signed-off-by: Junyan He <[email protected]> --- backend/src/llvm/llvm_profiling.cpp | 204 +++++++++++++++++++++++++++++------- 1 file changed, 166 insertions(+), 38 deletions(-) diff --git a/backend/src/llvm/llvm_profiling.cpp b/backend/src/llvm/llvm_profiling.cpp index 7c672e8..914b4a7 100644 --- a/backend/src/llvm/llvm_profiling.cpp +++ b/backend/src/llvm/llvm_profiling.cpp @@ -63,19 +63,87 @@ #include "llvm/llvm_gen_backend.hpp" #include "sys/map.hpp" #include "ir/unit.hpp" +#include "ir/profiling.hpp" +#include "sys/cvar.hpp" #include <iostream> #include <vector> - +#include <sstream> +#include <stdlib.h> using namespace llvm; using std::vector; - namespace gbe { using namespace ir; + SVAR(OCL_PROFILING_LINES, ""); + + inline bool line_cmp(const std::pair<uint32_t, bool>& l0, const std::pair<uint32_t, bool>& l1) + { + return l0.first < l1.first; + } + + static void parseProfilingLines(std::vector<std::pair<uint32_t, bool> >& profLines, + std::string& profKernel, uint32_t& profilingType) + { + profKernel = ""; + profilingType = ProfilingInfo::ProfilingNone; + + if (OCL_PROFILING_LINES == "") + return; + + char* profstr = (char *)malloc(OCL_PROFILING_LINES.size() + 1); + strcpy(profstr, OCL_PROFILING_LINES.c_str()); + std::string str; + + char* kernel_name = strtok(profstr, ":"); + if (!kernel_name) { + printf("Wrong profiling format, should be KERNEL_NAME:PROFILING_MODE:" + "LINE_NUMBER0,LINE_NUMBER1,LINE_NUMBER2,..."); + GBE_ASSERT(0); + } + char* prof_mode = strtok(NULL,":"); + if (!prof_mode) { + printf("Wrong profiling format, should be KERNEL_NAME:PROFILING_MODE:" + "LINE_NUMBER0,LINE_NUMBER1,LINE_NUMBER2,..."); + GBE_ASSERT(0); + } + char* lines = strtok(NULL,":"); + if (!lines) { + printf("Wrong profiling format, should be KERNEL_NAME:PROFILING_MODE:" + "LINE_NUMBER0,LINE_NUMBER1,LINE_NUMBER2,..."); + GBE_ASSERT(0); + } + + profKernel = kernel_name; + uint32_t mode = std::atoi(prof_mode); + if (mode <= ProfilingInfo::ProfilingVerbose) + profilingType = mode; + + if (profilingType == ProfilingInfo::ProfilingNone) { + printf("Wrong profiling format, should be KERNEL_NAME:PROFILING_MODE:" + "LINE_NUMBER0,LINE_NUMBER1,LINE_NUMBER2,..."); + GBE_ASSERT(0); + } + + std::istringstream lineStream(lines); + while (std::getline(lineStream, str, ',')) { + uint32_t line = std::atoi(str.c_str()); + profLines.push_back(std::pair<uint32_t, bool>(line, false)); + } + std::sort(profLines.begin(), profLines.end(), line_cmp); + + printf("Prof kernels is %s, \tin mode %d, \tprofiling points are: ", profKernel.c_str(), profilingType); + for (auto & l : profLines) { + printf("%d ", l.first); + } + printf("\n"); + free(profstr); + } + + class ProfilingInserter : public FunctionPass { public: @@ -90,11 +158,13 @@ namespace gbe ir::Unit &unit; const char* source; - ProfilingInserter(ir::Unit &u, const char* s) : FunctionPass(ID), unit(u), source(s) { + ProfilingInserter(ir::Unit &u, const char* s) : FunctionPass(ID), unit(u), source(s) + { module = NULL; builder = NULL; intTy = NULL; ptrTy = NULL; + parseProfilingLines(profLines, profKernel, profilingType); } ~ProfilingInserter(void) @@ -112,7 +182,6 @@ namespace gbe bool ProfilingInserter::runOnFunction(llvm::Function &F) { bool changed = false; - int pointNum = 0; switch (F.getCallingConv()) { #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 @@ -131,7 +200,14 @@ namespace gbe // As we inline all function calls, so skip non-kernel functions bool bKernel = isKernelFunction(F); - if (!bKernel) return changed; + if (F.getName() != profKernel) + return changed; + if (!bKernel) + return changed; + + if (profLines.size() == 0) + return changed; + module = F.getParent(); intTy = IntegerType::get(module->getContext(), 32); @@ -143,52 +219,96 @@ namespace gbe llvm::Constant *profilingBuf = module->getGlobalVariable("__gen_ocl_profiling_buf"); if (!profilingBuf) { profilingBuf = new GlobalVariable(*module, intTy, false, - GlobalVariable::ExternalLinkage, nullptr, StringRef("__gen_ocl_profiling_buf"), - nullptr, GlobalVariable::NotThreadLocal, 1); + GlobalVariable::ExternalLinkage, nullptr, StringRef("__gen_ocl_profiling_buf"), + nullptr, GlobalVariable::NotThreadLocal, 1); } - changed = true; - + /* Some line of source code like: + int i = 0x20; + Compiler may just record the imm value of var i if it is not used as a dst. + Such code line does not have a llvm::Instruction, and so we need to set the + profiling point to the next lines. We need to build up a line-instruction map + to find the suitable profiling point. */ + std::map<uint32_t, llvm::Instruction*> lineInstMap; for (llvm::Function::iterator B = F.begin(), BE = F.end(); B != BE; B++) { /* Skip the empty blocks. */ if (B->empty()) continue; + uint32_t line; + BasicBlock::iterator instI = B->begin(); for ( ; instI != B->end(); instI++) { - if (dyn_cast<llvm::PHINode>(instI)) + if (dyn_cast<llvm::PHINode>(instI)) // not insert before PHI. continue; - if (dyn_cast<llvm::ReturnInst>(instI)) { - instI++; - GBE_ASSERT(instI == B->end()); - break; - } - if (dyn_cast<llvm::BranchInst>(instI)) { - instI++; - GBE_ASSERT(instI == B->end()); - break; + + DebugLoc dbgLoc = instI->getDebugLoc(); + line = dbgLoc.getLine(); + if (line == 0) // Some instruction inserted. + continue; + + if (lineInstMap.find(line) == lineInstMap.end()) { + lineInstMap.insert(std::pair<uint32_t, llvm::Instruction*>(line, instI)); } - break; } + } - if (instI == B->end()) - continue; + if (lineInstMap.size() == 0) {// Nothing to insert. + delete builder; + return changed; + } + + uint32_t inserted = 0; + std::map<uint32_t, uint32_t> profPoints; + + std::vector<std::pair<uint32_t, llvm::Instruction*> > lineInstVect; + for (auto& e : lineInstMap) { + lineInstVect.push_back(e); + } + std::sort(lineInstVect.begin(), lineInstVect.end(), line_cmp); - if (pointNum >= 20) // To many timestamp. + for (auto& l : profLines) { + if (inserted >= ProfilingInfo::MaxTimestampProfilingPoints) + break; + + if (l.first < lineInstVect.begin()->first || l.first > lineInstVect.rbegin()->first) { + // Not belong to this kernel. continue; + } + + l.second = true; + std::vector<std::pair<uint32_t, llvm::Instruction*> >::iterator instPoint; + instPoint = std::lower_bound(lineInstVect.begin(), lineInstVect.end(), l, line_cmp); - // Insert the first one at beginning of not PHI. - builder->SetInsertPoint(instI); + builder->SetInsertPoint(instPoint->second); /* Add the timestamp store function call. */ // __gen_ocl_store_timestamp(int nth, int type); - Value *Args[2] = {ConstantInt::get(intTy, pointNum++), ConstantInt::get(intTy, profilingType)}; - builder->CreateCall(cast<llvm::Function>(module->getOrInsertFunction( - "__gen_ocl_calc_timestamp", Type::getVoidTy(module->getContext()), - IntegerType::getInt32Ty(module->getContext()), - IntegerType::getInt32Ty(module->getContext()), - NULL)), - ArrayRef<Value*>(Args)); + Value *Args[2] = { ConstantInt::get(intTy, inserted), ConstantInt::get(intTy, profilingType) }; + CallInst* callTS = builder->CreateCall(cast<llvm::Function>(module->getOrInsertFunction( + "__gen_ocl_calc_timestamp", Type::getVoidTy(module->getContext()), + IntegerType::getInt32Ty(module->getContext()), + IntegerType::getInt32Ty(module->getContext()), + NULL)), + ArrayRef<Value*>(Args)); + callTS->setDebugLoc(DebugLoc()); + + profPoints.insert(std::pair<uint32_t, uint32_t>(inserted, l.first)); + inserted++; + changed = true; + } + + if (inserted == 0) { // Nothing to insert. + delete builder; + return changed; } + + for (auto& l : profLines) { + if (l.second == false) { + printf("Warning: for kernel %s,\tprofiling point for line %d is not applied.\n", + std::string(F.getName()).c_str(), l.first); + } + } + /* We insert one store_profiling at the end of the last block to hold the place. */ llvm::Function::iterator BE = F.end(); BE--; @@ -197,12 +317,20 @@ namespace gbe builder->SetInsertPoint(retInst); Value *Args2[2] = {profilingBuf, ConstantInt::get(intTy, profilingType)}; - builder->CreateCall(cast<llvm::Function>(module->getOrInsertFunction( - "__gen_ocl_store_profiling", Type::getVoidTy(module->getContext()), - ptrTy, - IntegerType::getInt32Ty(module->getContext()), - NULL)), - ArrayRef<Value*>(Args2)); + CallInst* callStorePF = builder->CreateCall(cast<llvm::Function>(module->getOrInsertFunction( + "__gen_ocl_store_profiling", Type::getVoidTy(module->getContext()), + ptrTy, + IntegerType::getInt32Ty(module->getContext()), + NULL)), + ArrayRef<Value*>(Args2)); + callStorePF->setDebugLoc(DebugLoc()); + + + ProfilingInfo profInfo; + profInfo.setprofPoints(profPoints); + profInfo.setProfilingType(profilingType); + profInfo.setSource(source); + unit.setProfilingInfoForKernel(profKernel, profInfo); delete builder; return changed; -- 1.9.1 _______________________________________________ Beignet mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/beignet
