One comment. > -----Original Message----- > From: Beignet [mailto:beignet-boun...@lists.freedesktop.org] On Behalf Of > junyan...@inbox.com > Sent: Wednesday, September 9, 2015 8:01 > To: beignet@lists.freedesktop.org > Subject: [Beignet] [PATCH 03/19] Backend: Add ProfilingInserter and a new > function pass. > > From: Junyan He <junyan...@linux.intel.com> > > When user enables profiling feature, we need to insert extra instructions to > record and store the timestamps. > By now, the function pass will just insert the requred instructions at the > head > of first 20 blocks. Later, we will support to insert timestamps at any point > in > the code. > > Signed-off-by: Junyan He <junyan...@linux.intel.com> > Signed-off-by: Bai Yannan <yannan....@intel.com> > --- > backend/src/CMakeLists.txt | 1 + > backend/src/llvm/llvm_profiling.cpp | 210 > +++++++++++++++++++++++++++++++++++ > 2 files changed, 211 insertions(+) > create mode 100644 backend/src/llvm/llvm_profiling.cpp > > diff --git a/backend/src/CMakeLists.txt b/backend/src/CMakeLists.txt index > daab320..e56df5e 100644 > --- a/backend/src/CMakeLists.txt > +++ b/backend/src/CMakeLists.txt > @@ -87,6 +87,7 @@ set (GBE_SRC > llvm/llvm_intrinsic_lowering.cpp > llvm/llvm_barrier_nodup.cpp > llvm/llvm_printf_parser.cpp > + llvm/llvm_profiling.cpp > llvm/ExpandConstantExpr.cpp > llvm/ExpandUtils.cpp > llvm/PromoteIntegers.cpp > diff --git a/backend/src/llvm/llvm_profiling.cpp > b/backend/src/llvm/llvm_profiling.cpp > new file mode 100644 > index 0000000..c52e241 > --- /dev/null > +++ b/backend/src/llvm/llvm_profiling.cpp > @@ -0,0 +1,210 @@ > +/* > + * Copyright © 2012 Intel Corporation > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > <http://www.gnu.org/licenses/>. > + * > + */ > + > +/** > + * \file llvm_profiling.cpp > + * This file will insert some instructions for each profiling point. > + * > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > + > +#include "llvm/Config/llvm-config.h" > +#if LLVM_VERSION_MINOR <= 2 > +#include "llvm/Function.h" > +#include "llvm/InstrTypes.h" > +#include "llvm/Instructions.h" > +#include "llvm/IntrinsicInst.h" > +#include "llvm/Module.h" > +#else > +#include "llvm/IR/Function.h" > +#include "llvm/IR/InstrTypes.h" > +#include "llvm/IR/Instructions.h" > +#include "llvm/IR/IntrinsicInst.h" > +#include "llvm/IR/Module.h" > +#endif /* LLVM_VERSION_MINOR <= 2 */ > +#include "llvm/Pass.h" > +#if LLVM_VERSION_MINOR <= 1 > +#include "llvm/Support/IRBuilder.h" > +#elif LLVM_VERSION_MINOR == 2 > +#include "llvm/IRBuilder.h" > +#else > +#include "llvm/IR/IRBuilder.h" > +#endif /* LLVM_VERSION_MINOR <= 1 */ > + > +#if LLVM_VERSION_MINOR >= 5 > +#include "llvm/IR/CallSite.h" > +#include "llvm/IR/CFG.h" > +#else > +#include "llvm/Support/CallSite.h" > +#include "llvm/Support/CFG.h" > +#endif > + > +#include "llvm/Support/raw_ostream.h" > +#include "llvm/IR/Attributes.h" > + > +#include "llvm/llvm_gen_backend.hpp" > +#include "sys/map.hpp" > + > +#include <iostream> > +#include <vector> > + > + > +using namespace llvm; > +using std::vector; > + > + > +namespace gbe > +{ > + using namespace ir; > + > + class ProfilingInserter : public FunctionPass { > + public: > + static char ID; > + Module* module; > + IRBuilder<>* builder; > + Type* intTy; > + Type *ptrTy; > + int profilingType; > + > + ProfilingInserter(int profiling) : FunctionPass(ID), > profilingType(profiling) > + { > + module = NULL; > + builder = NULL; > + intTy = NULL; > + ptrTy = NULL; > + } > + > + ~ProfilingInserter(void) > + { > + } > + > + virtual const char *getPassName() const > + { > + return "Timestamp Parser"; > + } > + > + virtual bool runOnFunction(llvm::Function &F); }; > + > + bool ProfilingInserter::runOnFunction(llvm::Function &F) { > + bool changed = false; > + int pointNum = 0; > + > + switch (F.getCallingConv()) { > +#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 > + case CallingConv::PTX_Device: > + return false; > + case CallingConv::PTX_Kernel: > +#else > + case CallingConv::C: > + case CallingConv::Fast: > + case CallingConv::SPIR_KERNEL: > +#endif > + break; > + default: > + GBE_ASSERTM(false, "Unsupported calling convention"); > + } > + > + // As we inline all function calls, so skip non-kernel functions > + bool bKernel = isKernelFunction(F); > + if (!bKernel) return changed; > + > + module = F.getParent(); > + intTy = IntegerType::get(module->getContext(), 32); > + ptrTy = Type::getInt32PtrTy(module->getContext(), 1); > + builder = new IRBuilder<>(module->getContext()); > + > + /* alloc a new buffer ptr to collect the timestamps. */ > + builder->SetInsertPoint(F.begin()->begin()); > + 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); > + } > + > + changed = true; > + > + for (llvm::Function::iterator B = F.begin(), BE = F.end(); B != BE; B++) > { > + /* Skip the empty blocks. */ > + if (B->empty()) > + continue; > + > + BasicBlock::iterator instI = B->begin(); > + for ( ; instI != B->end(); instI++) { > + if (dyn_cast<llvm::PHINode>(instI)) > + 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; > + } > + break; > + } > + > + if (instI == B->end()) > + continue; > + > + if (pointNum >= 20) // To many timestamp. > + continue; > + > + // Insert the first one at beginning of not PHI. > + builder->SetInsertPoint(instI); > + /* Add the timestamp store function call. */ > + // __gen_ocl_store_timestamp(int nth, int type); > + builder->CreateCall2(cast<llvm::Function>(module- > >getOrInsertFunction( > + "__gen_ocl_calc_timestamp", Type::getVoidTy(module- > >getContext()), > + IntegerType::getInt32Ty(module->getContext()), > + IntegerType::getInt32Ty(module->getContext()), > + NULL)), > + /* the args */ ConstantInt::get(intTy, pointNum++), > ConstantInt::get(intTy, profilingType)); > + } > + /* At the end and before return, we want to store the profiling info. */ > + llvm::Function::iterator BE = F.end(); > + BE--; > + BasicBlock::iterator retInst = BE->end(); > + retInst--; > + GBE_ASSERT(dyn_cast<llvm::ReturnInst>(retInst)); It is not correct assume the last instruction of last BB is ReturnInst, because beignet support goto. Can't assert here.
> + builder->SetInsertPoint(retInst); > + builder->CreateCall2(cast<llvm::Function>(module->getOrInsertFunction( > + "__gen_ocl_store_profiling", Type::getVoidTy(module- > >getContext()), > + ptrTy, > + IntegerType::getInt32Ty(module->getContext()), > + NULL)), > + /* the args */profilingBuf, ConstantInt::get(intTy, > + profilingType)); > + > + delete builder; > + return changed; > + } > + > + FunctionPass* createProfilingInserterPass(int profilingType) { > + return new ProfilingInserter(profilingType); } char > + ProfilingInserter::ID = 0; > + > +} // end namespace > -- > 1.7.9.5 > > > > _______________________________________________ > Beignet mailing list > Beignet@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/beignet _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/beignet