[Mesa-dev] [PATCH 5/6] clover: Use a structure to hold information about llvm kernel functions

Tom Stellard thomas.stellard at amd.com
Mon Mar 30 08:31:41 PDT 2015


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



More information about the mesa-dev mailing list