diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/state_trackers/clover/llvm/invocation.cpp | 173 |
1 files changed, 92 insertions, 81 deletions
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 212b4e48f62..41f1d6a47bf 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -293,23 +293,13 @@ namespace { PM.run(*mod); } - module - build_module_llvm(llvm::Module *mod, - const std::vector<llvm::Function *> &kernels, - clang::LangAS::Map& address_spaces) { + compat::vector<module::argument> + get_kernel_args(const llvm::Module *mod, const std::string &kernel_name, + const clang::LangAS::Map &address_spaces) { - module m; - struct pipe_llvm_program_header header; - - llvm::SmallVector<char, 1024> llvm_bitcode; - llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode); - llvm::BitstreamWriter writer(llvm_bitcode); - llvm::WriteBitcodeToFile(mod, bitcode_ostream); - bitcode_ostream.flush(); + compat::vector<module::argument> args; + llvm::Function *kernel_func = mod->getFunction(kernel_name); - for (unsigned i = 0; i < kernels.size(); ++i) { - llvm::Function *kernel_func = kernels[i]; - const std::string kernel_name = kernel_func->getName(); #if HAVE_LLVM < 0x0302 llvm::TargetData TD(kernel_func->getParent()); #elif HAVE_LLVM < 0x0305 @@ -317,88 +307,109 @@ namespace { #else llvm::DataLayout TD(mod); #endif - compat::vector<module::argument> args; - for (llvm::Function::arg_iterator I = kernel_func->arg_begin(), + for (llvm::Function::const_arg_iterator I = kernel_func->arg_begin(), E = kernel_func->arg_end(); I != E; ++I) { - llvm::Argument &arg = *I; - llvm::Type *arg_type = arg.getType(); - const unsigned arg_store_size = TD.getTypeStoreSize(arg_type); - - // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data - // type that is not a power of two bytes in size must be - // aligned to the next larger power of two". We need this - // alignment for three element vectors, which have - // non-power-of-2 store size. - const unsigned arg_api_size = - util_next_power_of_two(arg_store_size); - - llvm::Type *target_type = arg_type->isIntegerTy() ? + const llvm::Argument &arg = *I; + + llvm::Type *arg_type = arg.getType(); + const unsigned arg_store_size = TD.getTypeStoreSize(arg_type); + + // OpenCL 1.2 specification, Ch. 6.1.5: "A built-in data + // type that is not a power of two bytes in size must be + // aligned to the next larger power of two". We need this + // alignment for three element vectors, which have + // non-power-of-2 store size. + const unsigned arg_api_size = util_next_power_of_two(arg_store_size); + + llvm::Type *target_type = arg_type->isIntegerTy() ? TD.getSmallestLegalIntType(mod->getContext(), arg_store_size * 8) : arg_type; - unsigned target_size = TD.getTypeStoreSize(target_type); - unsigned target_align = TD.getABITypeAlignment(target_type); + unsigned target_size = TD.getTypeStoreSize(target_type); + unsigned target_align = TD.getABITypeAlignment(target_type); - if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) { - arg_type = + if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) { + arg_type = llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType(); - } + } - if (arg_type->isPointerTy()) { - unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace(); - if (address_space == address_spaces[clang::LangAS::opencl_local + if (arg_type->isPointerTy()) { + unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace(); + if (address_space == address_spaces[clang::LangAS::opencl_local - clang::LangAS::Offset]) { - args.push_back(module::argument(module::argument::local, - arg_api_size, target_size, - target_align, - module::argument::zero_ext)); - } else { - // XXX: Correctly handle constant address space. There is no - // way for r600g to pass a handle for constant buffers back - // to clover like it can for global buffers, so - // creating constant arguments will break r600g. For now, - // continue treating constant buffers as global buffers - // until we can come up with a way to create handles for - // constant buffers. - args.push_back(module::argument(module::argument::global, - arg_api_size, target_size, - target_align, - module::argument::zero_ext)); - } - + args.push_back(module::argument(module::argument::local, + arg_api_size, target_size, + target_align, + module::argument::zero_ext)); } else { - llvm::AttributeSet attrs = kernel_func->getAttributes(); - enum module::argument::ext_type ext_type = + // XXX: Correctly handle constant address space. There is no + // way for r600g to pass a handle for constant buffers back + // to clover like it can for global buffers, so + // creating constant arguments will break r600g. For now, + // continue treating constant buffers as global buffers + // until we can come up with a way to create handles for + // constant buffers. + args.push_back(module::argument(module::argument::global, + arg_api_size, target_size, + target_align, + module::argument::zero_ext)); + } + + } else { + llvm::AttributeSet attrs = kernel_func->getAttributes(); + enum module::argument::ext_type ext_type = (attrs.hasAttribute(arg.getArgNo() + 1, llvm::Attribute::SExt) ? module::argument::sign_ext : module::argument::zero_ext); - args.push_back( - module::argument(module::argument::scalar, arg_api_size, - target_size, target_align, ext_type)); - } + args.push_back( + module::argument(module::argument::scalar, arg_api_size, + target_size, target_align, ext_type)); } + } + + // Append implicit arguments. XXX - The types, ordering and + // vector size of the implicit arguments should depend on the + // target according to the selected calling convention. + llvm::Type *size_type = + TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * 8); + + args.push_back( + module::argument(module::argument::scalar, sizeof(cl_uint), + TD.getTypeStoreSize(size_type), + TD.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::grid_dimension)); + + args.push_back( + module::argument(module::argument::scalar, sizeof(cl_uint), + TD.getTypeStoreSize(size_type), + TD.getABITypeAlignment(size_type), + module::argument::zero_ext, + module::argument::grid_offset)); + + return args; + } + + module + build_module_llvm(llvm::Module *mod, + const std::vector<llvm::Function *> &kernels, + clang::LangAS::Map& address_spaces) { + + module m; + struct pipe_llvm_program_header header; - // Append implicit arguments. XXX - The types, ordering and - // vector size of the implicit arguments should depend on the - // target according to the selected calling convention. - llvm::Type *size_type = - TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * 8); - - args.push_back( - module::argument(module::argument::scalar, sizeof(cl_uint), - TD.getTypeStoreSize(size_type), - TD.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::grid_dimension)); - - args.push_back( - module::argument(module::argument::scalar, sizeof(cl_uint), - TD.getTypeStoreSize(size_type), - TD.getABITypeAlignment(size_type), - module::argument::zero_ext, - module::argument::grid_offset)); + llvm::SmallVector<char, 1024> llvm_bitcode; + llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode); + llvm::BitstreamWriter writer(llvm_bitcode); + llvm::WriteBitcodeToFile(mod, bitcode_ostream); + bitcode_ostream.flush(); + + for (unsigned i = 0; i < kernels.size(); ++i) { + std::string kernel_name = kernels[i]->getName(); + compat::vector<module::argument> args = + get_kernel_args(mod, kernel_name, address_spaces); m.syms.push_back(module::symbol(kernel_name, 0, i, args )); } |