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.