[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