[Mesa-dev] [PATCH 09/15] clover/llvm: Add functions for compiling from source to SPIR-V
Karol Herbst
kherbst at redhat.com
Sat May 11 14:07:06 UTC 2019
From: Pierre Moreau <pierre.morrow at free.fr>
Reviewed-by: Karol Herbst <kherbst at redhat.com>
---
.../state_trackers/clover/llvm/invocation.cpp | 100 +++++++++++++++---
.../state_trackers/clover/llvm/invocation.hpp | 8 ++
src/gallium/state_trackers/clover/meson.build | 2 +-
3 files changed, 92 insertions(+), 18 deletions(-)
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index 0a677ce2eaa..b4f59821323 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -30,6 +30,9 @@
#include <llvm/Support/raw_ostream.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <llvm-c/Target.h>
+#ifdef CLOVER_ALLOW_SPIRV
+#include <LLVMSPIRVLib/LLVMSPIRVLib.h>
+#endif
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Lex/PreprocessorOptions.h>
@@ -51,6 +54,9 @@
#include "llvm/invocation.hpp"
#include "llvm/metadata.hpp"
#include "llvm/util.hpp"
+#ifdef CLOVER_ALLOW_SPIRV
+#include "spirv/invocation.hpp"
+#endif
#include "util/algorithm.hpp"
@@ -182,7 +188,7 @@ namespace {
}
std::unique_ptr<clang::CompilerInstance>
- create_compiler_instance(const device &dev,
+ create_compiler_instance(const device &dev, const std::string& ir_target,
const std::vector<std::string> &opts,
std::string &r_log) {
std::unique_ptr<clang::CompilerInstance> c { new clang::CompilerInstance };
@@ -196,7 +202,7 @@ namespace {
const std::vector<const char *> copts =
map(std::mem_fn(&std::string::c_str), opts);
- const target &target = dev.ir_target();
+ const target &target = ir_target;
const std::string &device_clc_version = dev.device_clc_version();
if (!clang::CompilerInvocation::CreateFromArgs(
@@ -235,19 +241,29 @@ namespace {
compile(LLVMContext &ctx, clang::CompilerInstance &c,
const std::string &name, const std::string &source,
const header_map &headers, const device &dev,
- const std::string &opts, std::string &r_log) {
+ const std::string &opts, bool use_libclc, std::string &r_log) {
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);
+ if (use_libclc) {
+ // 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");
+ // Add libclc include
+ c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
+ } else {
+ // Add opencl-c generic search path
+ c.getHeaderSearchOpts().AddPath(CLANG_RESOURCE_DIR,
+ clang::frontend::Angled,
+ false, false);
+
+ // Add opencl include
+ c.getPreprocessorOpts().Includes.push_back("opencl-c.h");
+ }
// Add definition for the OpenCL version
c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" +
@@ -279,8 +295,9 @@ namespace {
// 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.
- compat::add_link_bitcode_file(c.getCodeGenOpts(),
- LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc");
+ if (use_libclc)
+ compat::add_link_bitcode_file(c.getCodeGenOpts(),
+ LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc");
// Compile the code
clang::EmitLLVMOnlyAction act(&ctx);
@@ -301,8 +318,10 @@ clover::llvm::compile_program(const std::string &source,
debug::log(".cl", "// Options: " + opts + '\n' + source);
auto ctx = create_context(r_log);
- auto c = create_compiler_instance(dev, tokenize(opts + " input.cl"), r_log);
- auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, r_log);
+ auto c = create_compiler_instance(dev, dev.ir_target(),
+ tokenize(opts + " input.cl"), r_log);
+ auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, true,
+ r_log);
if (has_flag(debug::llvm))
debug::log(".ll", print_module_bitcode(*mod));
@@ -363,14 +382,14 @@ namespace {
module
clover::llvm::link_program(const std::vector<module> &modules,
- const device &dev,
- const std::string &opts, std::string &r_log) {
+ const device &dev, const std::string &opts,
+ std::string &r_log) {
std::vector<std::string> options = tokenize(opts + " input.cl");
const bool create_library = count("-create-library", options);
erase_if(equals("-create-library"), options);
auto ctx = create_context(r_log);
- auto c = create_compiler_instance(dev, options, r_log);
+ auto c = create_compiler_instance(dev, dev.ir_target(), options, r_log);
auto mod = link(*ctx, *c, modules, r_log);
optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library);
@@ -384,7 +403,6 @@ clover::llvm::link_program(const std::vector<module> &modules,
if (create_library) {
return build_module_library(*mod, module::section::text_library);
-
} else if (dev.ir_format() == PIPE_SHADER_IR_NATIVE) {
if (has_flag(debug::native))
debug::log(id + ".asm", print_module_native(*mod, dev.ir_target()));
@@ -395,3 +413,51 @@ clover::llvm::link_program(const std::vector<module> &modules,
unreachable("Unsupported IR.");
}
}
+
+#ifdef CLOVER_ALLOW_SPIRV
+module
+clover::llvm::compile_to_spirv(const std::string &source,
+ const header_map &headers,
+ const device &dev,
+ const std::string &opts,
+ std::string &r_log) {
+ if (has_flag(debug::clc))
+ debug::log(".cl", "// Options: " + opts + '\n' + source);
+
+ auto ctx = create_context(r_log);
+ const std::string target = dev.address_bits() == 32u ?
+ "-spir-unknown-unknown" :
+ "-spir64-unknown-unknown";
+ auto c = create_compiler_instance(dev, target,
+ tokenize(opts + " input.cl"), r_log);
+ auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, false,
+ r_log);
+
+ if (has_flag(debug::llvm))
+ debug::log(".ll", print_module_bitcode(*mod));
+
+ std::string error_msg;
+ if (!::llvm::regularizeLlvmForSpirv(mod.get(), error_msg)) {
+ r_log += "Failed to regularize LLVM IR for SPIR-V: " + error_msg + ".\n";
+ throw error(CL_INVALID_VALUE);
+ }
+
+ std::ostringstream os;
+ if (!::llvm::writeSpirv(mod.get(), os, error_msg)) {
+ r_log += "Translation from LLVM IR to SPIR-V failed: " + error_msg + ".\n";
+ throw error(CL_INVALID_VALUE);
+ }
+
+ const std::string osContent = os.str();
+ std::vector<char> binary(osContent.begin(), osContent.end());
+ if (binary.empty()) {
+ r_log += "Failed to retrieve SPIR-V binary.\n";
+ throw error(CL_INVALID_VALUE);
+ }
+
+ if (has_flag(debug::spirv))
+ debug::log(".spvasm", spirv::print_module(binary, dev.device_version()));
+
+ return spirv::process_program(binary, dev, true, r_log);
+}
+#endif
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.hpp b/src/gallium/state_trackers/clover/llvm/invocation.hpp
index ff9caa457ca..9746928e66f 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.hpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.hpp
@@ -40,6 +40,14 @@ namespace clover {
const device &device,
const std::string &opts,
std::string &r_log);
+
+#ifdef CLOVER_ALLOW_SPIRV
+ module compile_to_spirv(const std::string &source,
+ const header_map &headers,
+ const device &dev,
+ const std::string &opts,
+ std::string &r_log);
+#endif
}
}
diff --git a/src/gallium/state_trackers/clover/meson.build b/src/gallium/state_trackers/clover/meson.build
index 461c69f54c0..4cd4012fd10 100644
--- a/src/gallium/state_trackers/clover/meson.build
+++ b/src/gallium/state_trackers/clover/meson.build
@@ -53,7 +53,7 @@ libclllvm = static_library(
dep_llvm.version(), 'include',
)),
],
- dependencies : [dep_llvm, dep_elf],
+ dependencies : [dep_llvm, dep_elf, dep_llvmspirvlib],
override_options : clover_cpp_std,
)
--
2.21.0
More information about the mesa-dev
mailing list