[Mesa-dev] [PATCH v7 2/7] clover: make use of llvm_ir_compiler

Serge Martin edb+mesa at sigluy.net
Sat Feb 13 22:08:36 UTC 2016


---
 .../state_trackers/clover/llvm/invocation.cpp      | 234 ++-------------------
 1 file changed, 23 insertions(+), 211 deletions(-)

diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 4d11c24..d3347de 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -21,6 +21,7 @@
 //
 
 #include "core/compiler.hpp"
+#include "llvm/ir_compiler.hpp"
 
 #include <clang/Frontend/CompilerInstance.h>
 #include <clang/Frontend/TextDiagnosticBuffer.h>
@@ -130,149 +131,6 @@ namespace {
        }
    }
 
-   llvm::Module *
-   compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source,
-                const header_map &headers,
-                const std::string &name, const std::string &triple,
-                const std::string &processor, const std::string &opts,
-                clang::LangAS::Map& address_spaces, unsigned &optimization_level,
-                std::string &r_log) {
-
-      clang::CompilerInstance c;
-      clang::EmitLLVMOnlyAction act(&llvm_ctx);
-      std::string log;
-      llvm::raw_string_ostream s_log(log);
-      std::string libclc_path = LIBCLC_LIBEXECDIR + processor + "-"
-                                                  + triple + ".bc";
-
-      // Parse the compiler options:
-      std::vector<std::string> opts_array;
-      std::istringstream ss(opts);
-
-      while (!ss.eof()) {
-         std::string opt;
-         getline(ss, opt, ' ');
-         opts_array.push_back(opt);
-      }
-
-      opts_array.push_back(name);
-
-      std::vector<const char *> opts_carray;
-      for (unsigned i = 0; i < opts_array.size(); i++) {
-         opts_carray.push_back(opts_array.at(i).c_str());
-      }
-
-      llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID;
-      llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts;
-      clang::TextDiagnosticBuffer *DiagsBuffer;
-
-      DiagID = new clang::DiagnosticIDs();
-      DiagOpts = new clang::DiagnosticOptions();
-      DiagsBuffer = new clang::TextDiagnosticBuffer();
-
-      clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
-      bool Success;
-
-      Success = clang::CompilerInvocation::CreateFromArgs(c.getInvocation(),
-                                        opts_carray.data(),
-                                        opts_carray.data() + opts_carray.size(),
-                                        Diags);
-      if (!Success) {
-         throw error(CL_INVALID_COMPILER_OPTIONS);
-      }
-      c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
-      c.getHeaderSearchOpts().UseBuiltinIncludes = true;
-      c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
-      c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR;
-
-      // Add libclc generic search path
-      c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
-                                      clang::frontend::Angled,
-                                      false, false
-                                      );
-
-      // Add libclc include
-      c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
-
-      // clc.h requires that this macro be defined:
-      c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers");
-
-      c.getLangOpts().NoBuiltin = true;
-      c.getTargetOpts().Triple = triple;
-      c.getTargetOpts().CPU = processor;
-
-      // This is a workaround for a Clang bug which causes the number
-      // of warnings and errors to be printed to stderr.
-      // http://www.llvm.org/bugs/show_bug.cgi?id=19735
-      c.getDiagnosticOpts().ShowCarets = false;
-      c.getInvocation().setLangDefaults(c.getLangOpts(), clang::IK_OpenCL,
-                                        clang::LangStandard::lang_opencl11);
-      c.createDiagnostics(
-                          new clang::TextDiagnosticPrinter(
-                                 s_log,
-                                 &c.getDiagnosticOpts()));
-
-#if HAVE_LLVM >= 0x0306
-      c.getPreprocessorOpts().addRemappedFile(name,
-                                              llvm::MemoryBuffer::getMemBuffer(source).release());
-#else
-      c.getPreprocessorOpts().addRemappedFile(name,
-                                      llvm::MemoryBuffer::getMemBuffer(source));
-#endif
-
-      if (headers.size()) {
-         const std::string tmp_header_path = "/tmp/clover/";
-
-         c.getHeaderSearchOpts().AddPath(tmp_header_path,
-                                         clang::frontend::Angled,
-                                         false, false
-                                         );
-
-         for (header_map::const_iterator it = headers.begin();
-              it != headers.end(); ++it) {
-            const std::string path = tmp_header_path + std::string(it->first);
-            c.getPreprocessorOpts().addRemappedFile(path,
-#if HAVE_LLVM >= 0x0306
-                    llvm::MemoryBuffer::getMemBuffer(it->second.c_str()).release());
-#else
-                    llvm::MemoryBuffer::getMemBuffer(it->second.c_str()));
-#endif
-         }
-      }
-
-      // Setting this attribute tells clang to link this file before
-      // performing any optimizations.  This is required so that
-      // we can replace calls to the OpenCL C barrier() builtin
-      // with calls to target intrinsics that have the noduplicate
-      // attribute.  This attribute will prevent Clang from creating
-      // illegal uses of barrier() (e.g. Moving barrier() inside a conditional
-      // that is no executed by all threads) during its optimizaton passes.
-#if HAVE_LLVM >= 0x0308
-      c.getCodeGenOpts().LinkBitcodeFiles.emplace_back(llvm::Linker::Flags::None,
-                                                       libclc_path);
-#else
-      c.getCodeGenOpts().LinkBitcodeFile = libclc_path;
-#endif
-      optimization_level = c.getCodeGenOpts().OptimizationLevel;
-
-      // Compile the code
-      bool ExecSuccess = c.ExecuteAction(act);
-      r_log = log;
-
-      if (!ExecSuccess)
-         throw compile_error();
-
-      // Get address spaces map to be able to find kernel argument address space
-      memcpy(address_spaces, c.getTarget().getAddressSpaceMap(),
-                                                        sizeof(address_spaces));
-
-#if HAVE_LLVM >= 0x0306
-      return act.takeModule().release();
-#else
-      return act.takeModule();
-#endif
-   }
-
    std::vector<llvm::Function *>
    find_kernels(const llvm::Module *mod) {
       const llvm::NamedMDNode *kernel_node =
@@ -297,57 +155,6 @@ namespace {
       return kernels;
    }
 
-   void
-   optimize(llvm::Module *mod, unsigned optimization_level) {
-
-#if HAVE_LLVM >= 0x0307
-      llvm::legacy::PassManager PM;
-#else
-      llvm::PassManager PM;
-#endif
-
-      const std::vector<llvm::Function *> kernels = find_kernels(mod);
-
-      // Add a function internalizer pass.
-      //
-      // By default, the function internalizer pass will look for a function
-      // called "main" and then mark all other functions as internal.  Marking
-      // functions as internal enables the optimizer to perform optimizations
-      // like function inlining and global dead-code elimination.
-      //
-      // When there is no "main" function in a module, the internalize pass will
-      // treat the module like a library, and it won't internalize any functions.
-      // Since there is no "main" function in our kernels, we need to tell
-      // the internalizer pass that this module is not a library by passing a
-      // list of kernel functions to the internalizer.  The internalizer will
-      // 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(),
-                                                         E = kernels.end();
-                                                         I != E; ++I) {
-         llvm::Function *kernel = *I;
-         export_list.push_back(kernel->getName().data());
-      }
-#if HAVE_LLVM < 0x0306
-      PM.add(new llvm::DataLayoutPass(mod));
-#elif HAVE_LLVM < 0x0307
-      PM.add(new llvm::DataLayoutPass());
-#endif
-      PM.add(llvm::createInternalizePass(export_list));
-
-      llvm::PassManagerBuilder PMB;
-      PMB.OptLevel = optimization_level;
-#if HAVE_LLVM < 0x0307
-      PMB.LibraryInfo = new llvm::TargetLibraryInfo(
-#else
-      PMB.LibraryInfo = new llvm::TargetLibraryInfoImpl(
-#endif
-            llvm::Triple(mod->getTargetTriple()));
-      PMB.populateModulePassManager(PM);
-      PM.run(*mod);
-   }
-
    // Kernel metadata
 
    struct kernel_arg_md {
@@ -844,26 +651,28 @@ clover::compile_program_llvm(const std::string &source,
 
    init_targets();
 
-   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,
-                      target.size() - processor_str_len - 1);
-   clang::LangAS::Map address_spaces;
    llvm::LLVMContext llvm_ctx;
-   unsigned optimization_level;
 
    llvm_ctx.setDiagnosticHandler(diagnostic_handler, &r_log);
 
    if (get_debug_flags() & DBG_CLC)
       debug_log("// Build options: " + opts + '\n' + source, ".cl");
 
-   // The input file name must have the .cl extension in order for the
-   // CompilerInvocation class to recognize it as an OpenCL source file.
-   llvm::Module *mod = compile_llvm(llvm_ctx, source, headers, "input.cl",
-                                    triple, processor, opts, address_spaces,
-                                    optimization_level, r_log);
+   llvm_ir_compiler c(&llvm_ctx);
+
+   try {
+      c.parse_args(target, opts);
+      c.compile(source, headers);
+   } catch (const error &) {
+      r_log = c.get_log();
+      throw;
+   }
+
+   c.optimize();
+
+   r_log = c.get_log();
 
-   optimize(mod, optimization_level);
+   llvm::Module *mod = c.get_module();
 
    if (get_debug_flags() & DBG_LLVM) {
       std::string log;
@@ -873,6 +682,11 @@ clover::compile_program_llvm(const std::string &source,
       debug_log(log, ".ll");
     }
 
+   const clang::TargetInfo &info = c.get_info();
+   // Get address spaces map to be able to find kernel argument address space
+   clang::LangAS::Map address_spaces;
+   memcpy(address_spaces, info.getAddressSpaceMap(), sizeof(address_spaces));
+
    module m;
    // Build the clover::module
    switch (ir) {
@@ -885,17 +699,15 @@ clover::compile_program_llvm(const std::string &source,
          m = build_module_llvm(mod, address_spaces);
          break;
       case PIPE_SHADER_IR_NATIVE: {
-         std::vector<char> code = compile_native(mod, triple, processor,
+         std::vector<char> code = compile_native(mod,
+                                                 info.getTargetOpts().Triple,
+                                                 info.getTargetOpts().CPU,
                                                  get_debug_flags() & DBG_ASM,
                                                  r_log);
          m = build_module_native(code, mod, address_spaces, r_log);
          break;
       }
    }
-#if HAVE_LLVM >= 0x0306
-   // LLVM 3.6 and newer, the user takes ownership of the module.
-   delete mod;
-#endif
 
    return m;
 }
-- 
2.5.0



More information about the mesa-dev mailing list