From 08bd8f4b3b8093a428544f16ebfd0cd468fcf44c Mon Sep 17 00:00:00 2001
From: foreman
Date: Mon, 24 Aug 2015 13:14:41 -0400
Subject: [PATCH] P4 to Git Change 1183928 by yaxunl@yaxunl_stg_win50 on
2015/08/24 13:06:02
ECR #354633 - SPIR-V: Let aoc2 load and save SPIR-V.
E.g.
aoc2 -march=hsail-64 -cl-std=CL2.0 -srctospv testReadf.cl
compile a cl to SPIR-V binary and save it as .spv
aoc2 -march=hsail-64 -cl-std=CL2.0 -spirv work_group_any.spv
load a SPIR-V binary and compiles it to ISA and save it to elf in .bin
Changed the option for round-trip translation of SPIR-V to -round-trip-spirv.
Affected files ...
... //depot/stg/opencl/drivers/opencl/compiler/lib/api/v0_8/acl.cpp#35 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/frontend_clang.cpp#22 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/linker.cpp#133 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/v0_8/if_acl.cpp#74 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/include/v0_8/aclEnums.h#22 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/utils/OPTIONS.def#129 edit
... //depot/stg/opencl/drivers/opencl/compiler/tools/aoc2/aoc2.cpp#76 edit
... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/complib/CLEnumCheck.cpp#47 edit
[ROCm/clr commit: cc13b9f1f692408bbd6979fb5bc6a81b1159d6c4]
---
.../lib/backends/common/frontend_clang.cpp | 25 +++++++
.../compiler/lib/backends/common/linker.cpp | 13 +---
.../lib/backends/common/v0_8/if_acl.cpp | 72 ++++++++++++++++++-
.../compiler/lib/include/v0_8/aclEnums.h | 3 +-
.../clr/rocclr/compiler/lib/utils/OPTIONS.def | 16 +++++
5 files changed, 116 insertions(+), 13 deletions(-)
diff --git a/projects/clr/rocclr/compiler/lib/backends/common/frontend_clang.cpp b/projects/clr/rocclr/compiler/lib/backends/common/frontend_clang.cpp
index 08690a4cdd..34e46b3675 100644
--- a/projects/clr/rocclr/compiler/lib/backends/common/frontend_clang.cpp
+++ b/projects/clr/rocclr/compiler/lib/backends/common/frontend_clang.cpp
@@ -12,8 +12,10 @@
#include "utils/options.hpp"
#include "utils/target_mappings.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SPIRV.h"
#include "llvm/ADT/StringRef.h"
#include
@@ -62,6 +64,10 @@ int amdcl::ClangOCLFrontend::compileCommand(const std::string& src) {
argsToClang.push_back ("-D__AMD__=1 ");
+ if (Options()->oVariables->FEGenSPIRV) {
+ argsToClang.push_back("-D__AMD_SPIRV__ ");
+ }
+
// Other options are passed using OptionsInfo structure.
clc2::OptionsInfo ClangOptions;
@@ -184,6 +190,25 @@ int amdcl::ClangOCLFrontend::compileCommand(const std::string& src) {
if (!ret) {
CL()->clAPI.insSec(CL(), Elf(), Source().data(), Source().size(), aclLLVMIR);
}
+
+ if (Options()->oVariables->FEGenSPIRV) {
+ std::ostringstream ss;
+ std::string err;
+
+ if (Options()->getLLVMArgc()) {
+ llvm::cl::ParseCommandLineOptions(Options()->getLLVMArgc(),
+ Options()->getLLVMArgv(), "LLVM/SPIRV converter");
+ }
+ if (WriteSPRV(llvmbinary_, ss, err)) {
+ std::string img = ss.str();
+ CL()->clAPI.insSec(CL(), Elf(), img.data(), img.size(), aclSPIRV);
+ }
+
+ if (!log_.empty())
+ log_ += std::string(" ");
+ log_ += err;
+ }
+
log_ += logFromClang;
if (isCpuTarget(Elf()->target)
&& Options()->oVariables->EnableDebug) {
diff --git a/projects/clr/rocclr/compiler/lib/backends/common/linker.cpp b/projects/clr/rocclr/compiler/lib/backends/common/linker.cpp
index 7335364dba..5185fcd804 100644
--- a/projects/clr/rocclr/compiler/lib/backends/common/linker.cpp
+++ b/projects/clr/rocclr/compiler/lib/backends/common/linker.cpp
@@ -54,6 +54,7 @@
#include "llvm/AMDPrelink.h"
#endif
+#include "llvm/AMDUtils.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Analysis/AMDLocalArrayUsage.h"
@@ -136,14 +137,6 @@ namespace {
using namespace llvm;
-#ifdef HAS_SPIRV
-// Enable drop-in bi-way translation of LLVM/SPIR-V for testing purpose.
-cl::opt TestSpirv("test-spirv",
- cl::desc("Test SPIR-V translation"),
- cl::init(false),
- cl::Hidden);
-#endif
-
// LoadFile - Read the specified bitcode file in and return it. This routine
// searches the link path for the specified file to try to find it...
//
@@ -608,12 +601,12 @@ amdcl::OCLLinker::link(llvm::Module* input, std::vector &libs)
}
#ifdef HAS_SPIRV
- if (amd::TestSpirv) {
+ if (Options()->oVariables->RoundTripSPIRV && isSPIRModule(*llvmbinary_)) {
std::string DumpSpirv;
std::string DumpLlvm;
if (Options()->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
DumpSpirv = Options()->getDumpFileName(".spv");
- DumpLlvm = Options()->getDumpFileName("_spirv.bc");
+ DumpLlvm = Options()->getDumpFileName("_fromspv.bc");
}
translateSpirv(llvmbinary_, DumpSpirv, DumpLlvm);
}
diff --git a/projects/clr/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp b/projects/clr/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
index d7da9353bd..e5e90dc7b7 100644
--- a/projects/clr/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
+++ b/projects/clr/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
@@ -409,10 +409,14 @@ SPIRVToModule(
std::string errMsg;
auto llCtx = reinterpret_cast(ctx);
llvm::Module *llMod = nullptr;
+ if (opt->getLLVMArgc()) {
+ llvm::cl::ParseCommandLineOptions(opt->getLLVMArgc(), opt->getLLVMArgv(),
+ "SPIRV/LLVM converter");
+ }
bool success = llvm::ReadSPRV(*llCtx, ss, llMod, errMsg);
if (success && llMod && opt->isDumpFlagSet(amd::option::DUMP_BC_SPIRV)) {
- auto bcDump = opt->getDumpFileName("_spirv.bc");
+ auto bcDump = opt->getDumpFileName("_fromspv.bc");
std::error_code ec;
llvm::raw_fd_ostream outS(bcDump.c_str(), ec, llvm::sys::fs::F_None);
if (!ec)
@@ -434,6 +438,62 @@ SPIRVToModule(
#endif // LEGACY_COMPLIB
}
+aclModule * ACL_API_ENTRY
+LLVMToSPIRV(
+ aclLoaderData *ald,
+ const char *source,
+ size_t data_size,
+ aclContext *ctx,
+ acl_error *error)
+{
+ auto compiler = reinterpret_cast(ald);
+#ifdef LEGACY_COMPLIB
+ llvm::report_fatal_error("SPIR-V not supported on legacy compiler lib");
+ appendLogToCL(compiler->CL(), "SPIR-V not supported on legacy compiler lib");
+ if (error != nullptr) (*error) = ACL_SPIRV_LOAD_FAIL;
+ return nullptr;
+#else
+
+ std::string errMsg;
+ auto opt = compiler->Options();
+ llvm::Module *llMod = reinterpret_cast(OCLFEToModule(
+ ald, source, data_size, ctx, error));
+ if (!llMod)
+ return nullptr;
+
+ if (opt->isDumpFlagSet(amd::option::DUMP_BC_SPIRV)) {
+ auto bcDump = opt->getDumpFileName("_tospv.bc");
+ std::error_code ec;
+ llvm::raw_fd_ostream outS(bcDump.c_str(), ec, llvm::sys::fs::F_None);
+ if (!ec)
+ WriteBitcodeToFile(llMod, outS);
+ else
+ errMsg = ec.message();
+ }
+
+ std::string spvImg;
+ std::stringstream ss(spvImg);
+ bool success = llvm::WriteSPRV(llMod, ss, errMsg);
+
+ if (opt->isDumpFlagSet(amd::option::DUMP_SPIRV)) {
+ std::ofstream ofs(opt->getDumpFileName(".spv"), std::ios::binary);
+ ofs << spvImg;
+ ofs.close();
+ }
+
+ if (!errMsg.empty()) {
+ appendLogToCL(compiler->CL(), errMsg);
+ }
+ if (!success) {
+ if (error != nullptr) (*error) = ACL_SPIRV_SAVE_FAIL;
+ return nullptr;
+ }
+
+ if (error != nullptr) (*error) = ACL_SUCCESS;
+ return reinterpret_cast(llMod);
+#endif // LEGACY_COMPLIB
+}
+
acl_error ACL_API_ENTRY
AMDILFEToISA(
aclLoaderData *ald,
@@ -1393,6 +1453,7 @@ if_aclCompile(aclCompiler *cl,
llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry();
llvm::initializeSPIRVerifierPass(Registry);
}
+ amd::option::Options* Opts = reinterpret_cast(bin->options);
// Default 'to' is ACL_TYPE_ISA
if (to == ACL_TYPE_DEFAULT) {
to = ACL_TYPE_ISA;
@@ -1409,7 +1470,6 @@ if_aclCompile(aclCompiler *cl,
(from == ACL_TYPE_LLVMIR_BINARY && to == ACL_TYPE_LLVMIR_TEXT) ||
(from == ACL_TYPE_X86_TEXT && to == ACL_TYPE_X86_BINARY) ||
(from == ACL_TYPE_X86_BINARY && to == ACL_TYPE_X86_TEXT)) {
- amd::option::Options* Opts = reinterpret_cast(bin->options);
const char *kernel = Opts->oVariables->Kernel;
error_code = aclConvertType(cl, bin, kernel, from);
// if compilation to ACL_TYPE_ISA, then continue from ACL_TYPE_CG
@@ -1425,6 +1485,14 @@ if_aclCompile(aclCompiler *cl,
(from == ACL_TYPE_HSAIL_BINARY && to != ACL_TYPE_ISA && to != ACL_TYPE_CG)) {
return ACL_INVALID_ARG;
}
+ if (to == ACL_TYPE_SPIRV_BINARY) {
+ if (from == ACL_TYPE_OPENCL) {
+ to = ACL_TYPE_LLVMIR_BINARY;
+ Opts->oVariables->FEGenSPIRV = true;
+ } else {
+ return ACL_INVALID_ARG;
+ }
+ }
uint8_t sectable[ACL_TYPE_LAST] = {0, 0, 1, 1, 1, 1, 0, 6, 0, 3, 4, 4, 4, 0,
5, 0, 1, 1};
aclSections d_section[7] = {aclSOURCE, aclLLVMIR, aclSPIR, aclSOURCE,
diff --git a/projects/clr/rocclr/compiler/lib/include/v0_8/aclEnums.h b/projects/clr/rocclr/compiler/lib/include/v0_8/aclEnums.h
index eec2bcef34..55babaf18b 100644
--- a/projects/clr/rocclr/compiler/lib/include/v0_8/aclEnums.h
+++ b/projects/clr/rocclr/compiler/lib/include/v0_8/aclEnums.h
@@ -33,7 +33,8 @@ typedef enum _acl_error_enum_0_8 {
ACL_LWVERIFY_FAIL = 25,
ACL_HWVERIFY_FAIL = 26,
ACL_SPIRV_LOAD_FAIL = 27,
- ACL_LAST_ERROR = 28
+ ACL_SPIRV_SAVE_FAIL = 28,
+ ACL_LAST_ERROR = 29
} acl_error_0_8;
typedef enum _comp_device_caps_enum_0_8 {
diff --git a/projects/clr/rocclr/compiler/lib/utils/OPTIONS.def b/projects/clr/rocclr/compiler/lib/utils/OPTIONS.def
index bd2f62ab13..80c1075249 100644
--- a/projects/clr/rocclr/compiler/lib/utils/OPTIONS.def
+++ b/projects/clr/rocclr/compiler/lib/utils/OPTIONS.def
@@ -1170,6 +1170,22 @@ FLAG(OT_BOOL, OVIS_SUPPORT, "lower-atomics", LowerAtomics, 1,\
FLAG(OT_BOOL, OVIS_SUPPORT, "lower-pipe-builtins", LowerPipeBuiltins, 1,\
"Enable/disable pass lowering OCL pipe builtin functions to internal library functions ")
+// -fe-gen-spirv
+OPTION(OT_BOOL, \
+ OA_RUNTIME|OVIS_SUPPORT|OVA_DISALLOWED, \
+ "fe-gen-spirv", NULL, \
+ FEGenSPIRV, \
+ false, 0, 0, NULL, \
+ "Let frontend generate SPIR-V.")
+
+// -round-trip-spirv
+OPTION(OT_BOOL, \
+ OA_RUNTIME|OVIS_SUPPORT|OVA_DISALLOWED, \
+ "round-trip-spirv", NULL, \
+ RoundTripSPIRV, \
+ false, 0, 0, NULL, \
+ "Do round-trip translation of SPIR-V in pre-linking for testing purpose.")
+
/*
Do not remove the following line. Any option should be
added above this line.