[Beignet] [PATCH 03/19] Backend: Add ProfilingInserter and a new function pass.
Yang, Rong R
rong.r.yang at intel.com
Tue Nov 3 04:39:38 PST 2015
One comment.
> -----Original Message-----
> From: Beignet [mailto:beignet-bounces at lists.freedesktop.org] On Behalf Of
> junyan.he at inbox.com
> Sent: Wednesday, September 9, 2015 8:01
> To: beignet at lists.freedesktop.org
> Subject: [Beignet] [PATCH 03/19] Backend: Add ProfilingInserter and a new
> function pass.
>
> From: Junyan He <junyan.he at 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.he at linux.intel.com>
> Signed-off-by: Bai Yannan <yannan.bai at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet
More information about the Beignet
mailing list