More will be added to this structure in a later commit. The main purpose of this struct is to enable more efficient parsing of llvm modules. It will allow us to collect all kernel information for each function with only one pass through the module's metadata. OpenCL metadata for kernels is attached to the module and not the kernel function, so extracting this information on a per-kernel basis would require walking the metadata for the entire module. ---
I took a try at removing this struct, but the only other way I could see to implement this without a loot of code information was to pass around a map from kernel function pointer to attribute. Since we already have a map from kernel function pointer to ELF offset and new attributes would require adding additional maps, it seemed easier just to store everything in one struct. .../state_trackers/clover/llvm/invocation.cpp | 71 +++++++++++++--------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 4da62b9..28198a5 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -127,6 +127,16 @@ namespace { return module::deserialize(cs); } #endif + + struct llvm_kernel { + + llvm_kernel() : fn(NULL), offset(0) { + } + + llvm::Function *fn; + size_t offset; + }; + void debug_log(const std::string &msg, const std::string &suffix) { const char *dbg_file = debug_get_option("CLOVER_DEBUG_FILE", "stderr"); if (!strcmp("stderr", dbg_file)) { @@ -277,7 +287,7 @@ namespace { } void - find_kernels(llvm::Module *mod, std::vector<llvm::Function *> &kernels) { + find_kernels(llvm::Module *mod, std::vector<llvm_kernel> &kernels) { const llvm::NamedMDNode *kernel_node = mod->getNamedMetadata("opencl.kernels"); // This means there are no kernels in the program. The spec does not @@ -288,18 +298,20 @@ namespace { } for (unsigned i = 0; i < kernel_node->getNumOperands(); ++i) { + kernels.resize(i + 1); + llvm_kernel &kernel = kernels[i]; #if HAVE_LLVM >= 0x0306 - kernels.push_back(llvm::mdconst::dyn_extract<llvm::Function>( + kernel.fn = llvm::mdconst::dyn_extract<llvm::Function>( #else - kernels.push_back(llvm::dyn_cast<llvm::Function>( + kernel.fn = llvm::dyn_cast<llvm::Function>( #endif - kernel_node->getOperand(i)->getOperand(0))); + kernel_node->getOperand(i)->getOperand(0)); } } void optimize(llvm::Module *mod, unsigned optimization_level, - const std::vector<llvm::Function *> &kernels) { + const std::vector<llvm_kernel> &kernels) { #if HAVE_LLVM >= 0x0307 llvm::legacy::PassManager PM; @@ -322,10 +334,10 @@ namespace { // treat the functions in the list as "main" functions and internalize // all of the other functions. std::vector<const char*> export_list; - for (std::vector<llvm::Function *>::const_iterator I = kernels.begin(), + for (std::vector<llvm_kernel>::const_iterator I = kernels.begin(), E = kernels.end(); I != E; ++I) { - llvm::Function *kernel = *I; + llvm::Function *kernel = (*I).fn; export_list.push_back(kernel->getName().data()); } #if HAVE_LLVM < 0x0305 @@ -350,11 +362,11 @@ namespace { } compat::vector<module::argument> - get_kernel_args(const llvm::Module *mod, const std::string &kernel_name, + get_kernel_args(const llvm::Module *mod, const llvm_kernel &kernel, const clang::LangAS::Map &address_spaces) { compat::vector<module::argument> args; - llvm::Function *kernel_func = mod->getFunction(kernel_name); + llvm::Function *kernel_func = kernel.fn; #if HAVE_LLVM < 0x0305 llvm::DataLayout TD(kernel_func->getParent()->getDataLayout()); @@ -448,7 +460,7 @@ namespace { module build_module_llvm(llvm::Module *mod, - const std::vector<llvm::Function *> &kernels, + const std::vector<llvm_kernel> &kernels, clang::LangAS::Map& address_spaces) { module m; @@ -461,9 +473,10 @@ namespace { bitcode_ostream.flush(); for (unsigned i = 0; i < kernels.size(); ++i) { - std::string kernel_name = kernels[i]->getName(); + const llvm_kernel &kernel = kernels[i]; compat::vector<module::argument> args = - get_kernel_args(mod, kernel_name, address_spaces); + get_kernel_args(mod, kernel, address_spaces); + std::string kernel_name = kernel.fn->getName().str(); m.syms.push_back(module::symbol(kernel_name, 0, i, args )); } @@ -555,9 +568,9 @@ namespace { return code; } - std::map<std::string, unsigned> - get_kernel_offsets(std::vector<char> &code, - const std::vector<llvm::Function *> &kernels, + void + set_kernel_offsets(std::vector<char> &code, + std::vector<llvm_kernel> &kernels, compat::string &r_log) { // One of the libelf implementations @@ -602,32 +615,29 @@ namespace { GElf_Sym *symbol; GElf_Sym s; - std::map<std::string, unsigned> kernel_offsets; symtab_data = elf_getdata(symtab, symtab_data); // Determine the offsets for each kernel for (int i = 0; (symbol = gelf_getsym(symtab_data, i, &s)); i++) { char *name = elf_strptr(elf, symtab_header.sh_link, symbol->st_name); - for (std::vector<llvm::Function*>::const_iterator it = kernels.begin(), - e = kernels.end(); it != e; ++it) { - llvm::Function *f = *it; - if (f->getName() == std::string(name)) - kernel_offsets[f->getName()] = symbol->st_value; + for (unsigned kern_idx = 0, kern_end = kernels.size(); + kern_idx != kern_end; ++kern_idx) { + llvm_kernel& kernel = kernels[kern_idx]; + if (kernel.fn->getName() == std::string(name)) + kernel.offset = symbol->st_value; } } elf_end(elf); - return kernel_offsets; } module build_module_native(std::vector<char> &code, const llvm::Module *mod, - const std::vector<llvm::Function *> &kernels, + std::vector<llvm_kernel> &kernels, const clang::LangAS::Map &address_spaces, compat::string &r_log) { - std::map<std::string, unsigned> kernel_offsets = - get_kernel_offsets(code, kernels, r_log); + set_kernel_offsets(code, kernels, r_log); // Begin building the clover module module m; @@ -641,11 +651,12 @@ namespace { m.secs.push_back(module::section(0, module::section::text, header.num_bytes, data)); - for (std::map<std::string, unsigned>::iterator i = kernel_offsets.begin(), - e = kernel_offsets.end(); i != e; ++i) { + for (std::vector<llvm_kernel>::const_iterator i = kernels.begin(), + e = kernels.end(); i != e; ++i) { compat::vector<module::argument> args = - get_kernel_args(mod, i->first, address_spaces); - m.syms.push_back(module::symbol(i->first, 0, i->second, args )); + get_kernel_args(mod, *i, address_spaces); + std::string kernel_name = (*i).fn->getName().str(); + m.syms.push_back(module::symbol(kernel_name, 0, (*i).offset, args )); } return m; @@ -712,7 +723,7 @@ clover::compile_program_llvm(const compat::string &source, init_targets(); - std::vector<llvm::Function *> kernels; + std::vector<llvm_kernel> kernels; size_t processor_str_len = std::string(target).find_first_of("-"); std::string processor(target, 0, processor_str_len); std::string triple(target, processor_str_len + 1, -- 2.0.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev