diff options
Diffstat (limited to 'src/gallium/drivers/radeon/R600KernelParameters.cpp')
-rw-r--r-- | src/gallium/drivers/radeon/R600KernelParameters.cpp | 259 |
1 files changed, 149 insertions, 110 deletions
diff --git a/src/gallium/drivers/radeon/R600KernelParameters.cpp b/src/gallium/drivers/radeon/R600KernelParameters.cpp index 3fdf48a2bf2..53bfebc7364 100644 --- a/src/gallium/drivers/radeon/R600KernelParameters.cpp +++ b/src/gallium/drivers/radeon/R600KernelParameters.cpp @@ -1,4 +1,4 @@ -//===-- R600KernelParameters.cpp - TODO: Add brief description -------===// +//===-- R600KernelParameters.cpp - Lower kernel function arguments --------===// // // The LLVM Compiler Infrastructure // @@ -7,89 +7,83 @@ // //===----------------------------------------------------------------------===// // -// TODO: Add full description +// This pass lowers kernel function arguments to loads from the vertex buffer. +// +// Kernel arguemnts are stored in the vertex buffer at an offset of 9 dwords, +// so arg0 needs to be loaded from VTX_BUFFER[9] and arg1 is loaded from +// VTX_BUFFER[10], etc. // //===----------------------------------------------------------------------===// -#include <llvm-c/Core.h> -#include "R600KernelParameters.h" -#include "R600OpenCLUtils.h" +#include "AMDGPU.h" +#include "AMDIL.h" +#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Constants.h" +#include "llvm/Function.h" #include "llvm/Intrinsics.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetData.h" #include "llvm/Support/IRBuilder.h" #include "llvm/Support/TypeBuilder.h" -// #include "llvm/CodeGen/Function.h" - -namespace AMDILAS { -enum AddressSpaces { - PRIVATE_ADDRESS = 0, // Address space for private memory. - GLOBAL_ADDRESS = 1, // Address space for global memory (RAT0, VTX0). - CONSTANT_ADDRESS = 2, // Address space for constant memory. - LOCAL_ADDRESS = 3, // Address space for local memory. - REGION_ADDRESS = 4, // Address space for region memory. - ADDRESS_NONE = 5, // Address space for unknown memory. - PARAM_D_ADDRESS = 6, // Address space for direct addressible parameter memory (CONST0) - PARAM_I_ADDRESS = 7, // Address space for indirect addressible parameter memory (VTX1) - LAST_ADDRESS = 8 -}; -} - #include <map> #include <set> using namespace llvm; -using namespace std; + +namespace { #define CONSTANT_CACHE_SIZE_DW 127 -class R600KernelParameters : public llvm::FunctionPass +class R600KernelParameters : public FunctionPass { - const llvm::TargetData * TD; + const TargetData * TD; LLVMContext* Context; Module *mod; - + struct param { - param() : val(NULL), ptr_val(NULL), offset_in_dw(0), size_in_dw(0), indirect(false), specialID(0) {} - - llvm::Value* val; - llvm::Value* ptr_val; + param() : val(NULL), ptr_val(NULL), offset_in_dw(0), size_in_dw(0), + indirect(false), specialID(0) {} + + Value* val; + Value* ptr_val; int offset_in_dw; int size_in_dw; bool indirect; - - string specialType; + + std::string specialType; int specialID; - + int end() { return offset_in_dw + size_in_dw; } - /* The first 9 dwords are reserved for the grid sizes. */ + // The first 9 dwords are reserved for the grid sizes. int get_rat_offset() { return 9 + offset_in_dw; } }; std::vector<param> params; - int getLastSpecialID(const string& TypeName); - + bool isOpenCLKernel(const Function* fun); + int getLastSpecialID(const std::string& TypeName); + int getListSize(); - void AddParam(llvm::Argument* arg); - int calculateArgumentSize(llvm::Argument* arg); - void RunAna(llvm::Function* fun); - void Replace(llvm::Function* fun); - bool isIndirect(Value* val, set<Value*>& visited); - void Propagate(llvm::Function* fun); - void Propagate(llvm::Value* v, const llvm::Twine& name, bool indirect = false); + void AddParam(Argument* arg); + int calculateArgumentSize(Argument* arg); + void RunAna(Function* fun); + void Replace(Function* fun); + bool isIndirect(Value* val, std::set<Value*>& visited); + void Propagate(Function* fun); + void Propagate(Value* v, const Twine& name, bool indirect = false); Value* ConstantRead(Function* fun, param& p); Value* handleSpecial(Function* fun, param& p); bool isSpecialType(Type*); - string getSpecialTypeName(Type*); + std::string getSpecialTypeName(Type*); public: static char ID; R600KernelParameters() : FunctionPass(ID) {}; - R600KernelParameters(const llvm::TargetData* TD) : FunctionPass(ID), TD(TD) {} -// bool runOnFunction (llvm::Function &F); - bool runOnFunction (llvm::Function &F); + R600KernelParameters(const TargetData* TD) : FunctionPass(ID), TD(TD) {} + bool runOnFunction (Function &F); void getAnalysisUsage(AnalysisUsage &AU) const; const char *getPassName() const; bool doInitialization(Module &M); @@ -98,13 +92,42 @@ public: char R600KernelParameters::ID = 0; -static RegisterPass<R600KernelParameters> X("kerparam", "OpenCL Kernel Parameter conversion", false, false); +static RegisterPass<R600KernelParameters> X("kerparam", + "OpenCL Kernel Parameter conversion", false, false); -int R600KernelParameters::getLastSpecialID(const string& TypeName) +bool R600KernelParameters::isOpenCLKernel(const Function* fun) +{ + Module *mod = const_cast<Function*>(fun)->getParent(); + NamedMDNode * md = mod->getOrInsertNamedMetadata("opencl.kernels"); + + if (!md or !md->getNumOperands()) + { + return false; + } + + for (int i = 0; i < int(md->getNumOperands()); i++) + { + if (!md->getOperand(i) or !md->getOperand(i)->getOperand(0)) + { + continue; + } + + assert(md->getOperand(i)->getNumOperands() == 1); + + if (md->getOperand(i)->getOperand(0)->getName() == fun->getName()) + { + return true; + } + } + + return false; +} + +int R600KernelParameters::getLastSpecialID(const std::string& TypeName) { int lastID = -1; - - for (vector<param>::iterator i = params.begin(); i != params.end(); i++) + + for (std::vector<param>::iterator i = params.begin(); i != params.end(); i++) { if (i->specialType == TypeName) { @@ -125,7 +148,7 @@ int R600KernelParameters::getListSize() return params.back().end(); } -bool R600KernelParameters::isIndirect(Value* val, set<Value*>& visited) +bool R600KernelParameters::isIndirect(Value* val, std::set<Value*>& visited) { if (isa<LoadInst>(val)) { @@ -144,7 +167,7 @@ bool R600KernelParameters::isIndirect(Value* val, set<Value*>& visited) } visited.insert(val); - + if (isa<GetElementPtrInst>(val)) { GetElementPtrInst* GEP = dyn_cast<GetElementPtrInst>(val); @@ -158,7 +181,7 @@ bool R600KernelParameters::isIndirect(Value* val, set<Value*>& visited) } } } - + for (Value::use_iterator i = val->use_begin(); i != val->use_end(); i++) { Value* v2 = dyn_cast<Value>(*i); @@ -175,24 +198,24 @@ bool R600KernelParameters::isIndirect(Value* val, set<Value*>& visited) return false; } -void R600KernelParameters::AddParam(llvm::Argument* arg) +void R600KernelParameters::AddParam(Argument* arg) { param p; - + p.val = dyn_cast<Value>(arg); p.offset_in_dw = getListSize(); p.size_in_dw = calculateArgumentSize(arg); if (isa<PointerType>(arg->getType()) and arg->hasByValAttr()) { - set<Value*> visited; + std::set<Value*> visited; p.indirect = isIndirect(p.val, visited); } - + params.push_back(p); } -int R600KernelParameters::calculateArgumentSize(llvm::Argument* arg) +int R600KernelParameters::calculateArgumentSize(Argument* arg) { Type* t = arg->getType(); @@ -200,16 +223,16 @@ int R600KernelParameters::calculateArgumentSize(llvm::Argument* arg) { t = dyn_cast<PointerType>(t)->getElementType(); } - + int store_size_in_dw = (TD->getTypeStoreSize(t) + 3)/4; assert(store_size_in_dw); - + return store_size_in_dw; } -void R600KernelParameters::RunAna(llvm::Function* fun) +void R600KernelParameters::RunAna(Function* fun) { assert(isOpenCLKernel(fun)); @@ -220,7 +243,7 @@ void R600KernelParameters::RunAna(llvm::Function* fun) } -void R600KernelParameters::Replace(llvm::Function* fun) +void R600KernelParameters::Replace(Function* fun) { for (std::vector<param>::iterator i = params.begin(); i != params.end(); i++) { @@ -237,11 +260,11 @@ void R600KernelParameters::Replace(llvm::Function* fun) if (new_val) { i->val->replaceAllUsesWith(new_val); - } + } } } -void R600KernelParameters::Propagate(llvm::Function* fun) +void R600KernelParameters::Propagate(Function* fun) { for (std::vector<param>::iterator i = params.begin(); i != params.end(); i++) { @@ -256,8 +279,8 @@ void R600KernelParameters::Propagate(Value* v, const Twine& name, bool indirect) { LoadInst* load = dyn_cast<LoadInst>(v); GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(v); - - unsigned addrspace; + + unsigned addrspace; if (indirect) { @@ -274,49 +297,54 @@ void R600KernelParameters::Propagate(Value* v, const Twine& name, bool indirect) if (dyn_cast<PointerType>(op->getType())->getAddressSpace() != addrspace) { - op = new BitCastInst(op, PointerType::get(dyn_cast<PointerType>(op->getType())->getElementType(), addrspace), name, dyn_cast<Instruction>(v)); + op = new BitCastInst(op, PointerType::get(dyn_cast<PointerType>( + op->getType())->getElementType(), addrspace), + name, dyn_cast<Instruction>(v)); } - vector<Value*> params(GEP->idx_begin(), GEP->idx_end()); - - GetElementPtrInst* GEP2 = GetElementPtrInst::Create(op, params, name, dyn_cast<Instruction>(v)); + std::vector<Value*> params(GEP->idx_begin(), GEP->idx_end()); + + GetElementPtrInst* GEP2 = GetElementPtrInst::Create(op, params, name, + dyn_cast<Instruction>(v)); GEP2->setIsInBounds(GEP->isInBounds()); v = dyn_cast<Value>(GEP2); GEP->replaceAllUsesWith(GEP2); GEP->eraseFromParent(); load = NULL; } - + if (load) { - if (load->getPointerAddressSpace() != addrspace) ///normally at this point we have the right address space + ///normally at this point we have the right address space + if (load->getPointerAddressSpace() != addrspace) { Value *orig_ptr = load->getPointerOperand(); PointerType *orig_ptr_type = dyn_cast<PointerType>(orig_ptr->getType()); - - Type* new_ptr_type = PointerType::get(orig_ptr_type->getElementType(), addrspace); + + Type* new_ptr_type = PointerType::get(orig_ptr_type->getElementType(), + addrspace); Value* new_ptr = orig_ptr; - + if (orig_ptr->getType() != new_ptr_type) { new_ptr = new BitCastInst(orig_ptr, new_ptr_type, "prop_cast", load); } - + Value* new_load = new LoadInst(new_ptr, name, load); load->replaceAllUsesWith(new_load); load->eraseFromParent(); } - + return; } - vector<User*> users(v->use_begin(), v->use_end()); - + std::vector<User*> users(v->use_begin(), v->use_end()); + for (int i = 0; i < int(users.size()); i++) { Value* v2 = dyn_cast<Value>(users[i]); - + if (v2) { Propagate(v2, name, indirect); @@ -327,7 +355,7 @@ void R600KernelParameters::Propagate(Value* v, const Twine& name, bool indirect) Value* R600KernelParameters::ConstantRead(Function* fun, param& p) { assert(fun->front().begin() != fun->front().end()); - + Instruction *first_inst = fun->front().begin(); IRBuilder <> builder (first_inst); /* First 3 dwords are reserved for the dimmension info */ @@ -346,43 +374,54 @@ Value* R600KernelParameters::ConstantRead(Function* fun, param& p) { addrspace = AMDILAS::PARAM_D_ADDRESS; } - + Argument *arg = dyn_cast<Argument>(p.val); Type * argType = p.val->getType(); PointerType * argPtrType = dyn_cast<PointerType>(p.val->getType()); - + if (argPtrType and arg->hasByValAttr()) { - Value* param_addr_space_ptr = ConstantPointerNull::get(PointerType::get(Type::getInt32Ty(*Context), addrspace)); - Value* param_ptr = GetElementPtrInst::Create(param_addr_space_ptr, ConstantInt::get(Type::getInt32Ty(*Context), p.get_rat_offset()), arg->getName(), first_inst); - param_ptr = new BitCastInst(param_ptr, PointerType::get(argPtrType->getElementType(), addrspace), arg->getName(), first_inst); + Value* param_addr_space_ptr = ConstantPointerNull::get( + PointerType::get(Type::getInt32Ty(*Context), + addrspace)); + Value* param_ptr = GetElementPtrInst::Create(param_addr_space_ptr, + ConstantInt::get(Type::getInt32Ty(*Context), + p.get_rat_offset()), arg->getName(), + first_inst); + param_ptr = new BitCastInst(param_ptr, + PointerType::get(argPtrType->getElementType(), + addrspace), + arg->getName(), first_inst); p.ptr_val = param_ptr; return param_ptr; } else { - Value* param_addr_space_ptr = ConstantPointerNull::get(PointerType::get(argType, addrspace)); - + Value* param_addr_space_ptr = ConstantPointerNull::get(PointerType::get( + argType, addrspace)); + Value* param_ptr = builder.CreateGEP(param_addr_space_ptr, - ConstantInt::get(Type::getInt32Ty(*Context), p.get_rat_offset()), arg->getName()); - + ConstantInt::get(Type::getInt32Ty(*Context), p.get_rat_offset()), + arg->getName()); + Value* param_value = builder.CreateLoad(param_ptr, arg->getName()); - + return param_value; } } Value* R600KernelParameters::handleSpecial(Function* fun, param& p) { - string name = getSpecialTypeName(p.val->getType()); + std::string name = getSpecialTypeName(p.val->getType()); int ID; assert(!name.empty()); - + if (name == "image2d_t" or name == "image3d_t") { - int lastID = max(getLastSpecialID("image2d_t"), getLastSpecialID("image3d_t")); - + int lastID = std::max(getLastSpecialID("image2d_t"), + getLastSpecialID("image3d_t")); + if (lastID == -1) { ID = 2; ///ID0 and ID1 are used internally by the driver @@ -403,20 +442,22 @@ Value* R600KernelParameters::handleSpecial(Function* fun, param& p) else { ID = lastID + 1; - } + } } else { ///TODO: give some error message return NULL; } - + p.specialType = name; p.specialID = ID; Instruction *first_inst = fun->front().begin(); - return new IntToPtrInst(ConstantInt::get(Type::getInt32Ty(*Context), p.specialID), p.val->getType(), "resourceID", first_inst); + return new IntToPtrInst(ConstantInt::get(Type::getInt32Ty(*Context), + p.specialID), p.val->getType(), + "resourceID", first_inst); } @@ -425,7 +466,7 @@ bool R600KernelParameters::isSpecialType(Type* t) return !getSpecialTypeName(t).empty(); } -string R600KernelParameters::getSpecialTypeName(Type* t) +std::string R600KernelParameters::getSpecialTypeName(Type* t) { PointerType *pt = dyn_cast<PointerType>(t); StructType *st = NULL; @@ -437,9 +478,9 @@ string R600KernelParameters::getSpecialTypeName(Type* t) if (st) { - string prefix = "struct.opencl_builtin_type_"; - - string name = st->getName().str(); + std::string prefix = "struct.opencl_builtin_type_"; + + std::string name = st->getName().str(); if (name.substr(0, prefix.length()) == prefix) { @@ -458,19 +499,15 @@ bool R600KernelParameters::runOnFunction (Function &F) return false; } -// F.dump(); - RunAna(&F); Replace(&F); Propagate(&F); - - mod->dump(); + return false; } void R600KernelParameters::getAnalysisUsage(AnalysisUsage &AU) const { -// AU.addRequired<FunctionAnalysis>(); FunctionPass::getAnalysisUsage(AU); AU.setPreservesAll(); } @@ -484,7 +521,7 @@ bool R600KernelParameters::doInitialization(Module &M) { Context = &M.getContext(); mod = &M; - + return false; } @@ -493,10 +530,12 @@ bool R600KernelParameters::doFinalization(Module &M) return false; } -llvm::FunctionPass* createR600KernelParametersPass(const llvm::TargetData* TD) +} // End anonymous namespace + +FunctionPass* llvm::createR600KernelParametersPass(const TargetData* TD) { FunctionPass *p = new R600KernelParameters(TD); - + return p; } |