From 26be0530887d9d59bf4ca7d2e3f6ffe2192d4d0e Mon Sep 17 00:00:00 2001 From: foreman Date: Tue, 15 Dec 2015 16:09:35 -0500 Subject: [PATCH] P4 to Git Change 1221147 by ashi1@ashi1_win50 on 2015/12/15 15:58:09 SWDEV-83467 - [SPIRV] Add support of SPIRV to CPU Modifying runtime and compile time to allow SPIRV binaries to run on CPU since it only runs on HSAIL GPU Added changes to allow conversion of CPU's llvmBinaryIsSpir boolean into compiler library's oclElfSections enum Cpuprogram.cpp's llvmBinaryIsSpir flag renamed to elfSectionType will now support LLVMIR, SPIR, and SPIRV Added SPIRV to compiler lib's elf as new oclElfSections enum cpuprogram.cpp changes also made to gpuprogram.cpp's NullProgram to allow compilation Affected files ... ... //depot/stg/opencl/drivers/opencl/compiler/lib/loaders/elf/elf.cpp#33 edit ... //depot/stg/opencl/drivers/opencl/compiler/lib/loaders/elf/elf.hpp#22 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpuprogram.cpp#69 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/device.cpp#191 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/device.hpp#266 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucompiler.cpp#152 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#217 edit --- rocclr/compiler/lib/loaders/elf/elf.cpp | 2 + rocclr/compiler/lib/loaders/elf/elf.hpp | 1 + rocclr/runtime/device/cpu/cpuprogram.cpp | 61 ++++++++++++++++------- rocclr/runtime/device/device.cpp | 35 +++++++++---- rocclr/runtime/device/device.hpp | 6 ++- rocclr/runtime/device/gpu/gpucompiler.cpp | 27 +++++++--- rocclr/runtime/device/gpu/gpuprogram.cpp | 38 +++++++++----- 7 files changed, 120 insertions(+), 50 deletions(-) diff --git a/rocclr/compiler/lib/loaders/elf/elf.cpp b/rocclr/compiler/lib/loaders/elf/elf.cpp index 7580d876fb..39d4fdf011 100644 --- a/rocclr/compiler/lib/loaders/elf/elf.cpp +++ b/rocclr/compiler/lib/loaders/elf/elf.cpp @@ -105,6 +105,8 @@ namespace { "Internal usage" }, { OclElf::SPIR, ".spir", ELF_T_BYTE, 1, SHT_PROGBITS, 0, "Vendor/Device-independent LLVM IR" }, + { OclElf::SPIRV, ".spirv", ELF_T_BYTE, 1, SHT_PROGBITS, 0, + "SPIR-V Binary" }, }; // index 0 is reserved and must be there (NULL section) diff --git a/rocclr/compiler/lib/loaders/elf/elf.hpp b/rocclr/compiler/lib/loaders/elf/elf.hpp index 03b92f19cf..a72f6340b6 100644 --- a/rocclr/compiler/lib/loaders/elf/elf.hpp +++ b/rocclr/compiler/lib/loaders/elf/elf.hpp @@ -113,6 +113,7 @@ public: TEXT, INTERNAL, SPIR, + SPIRV, OCL_ELF_SECTIONS_LAST } oclElfSections; diff --git a/rocclr/runtime/device/cpu/cpuprogram.cpp b/rocclr/runtime/device/cpu/cpuprogram.cpp index 2bcadc35e8..7f56866dac 100644 --- a/rocclr/runtime/device/cpu/cpuprogram.cpp +++ b/rocclr/runtime/device/cpu/cpuprogram.cpp @@ -536,11 +536,23 @@ Program::compileBinaryToISA(amd::option::Options* options) return false; } - bool spirFlag = std::string::npos != options->clcOptions.find("--spir") - || llvmBinaryIsSpir_; + aclSections_0_8 spirFlag; + _acl_type_enum_0_8 aclTypeBinaryUsed; + if (std::string::npos != options->clcOptions.find("--spirv") + || elfSectionType_ == amd::OclElf::SPIRV) { + spirFlag = aclSPIRV; + aclTypeBinaryUsed = ACL_TYPE_SPIRV_BINARY; + } else if (std::string::npos != options->clcOptions.find("--spir") + || elfSectionType_ == amd::OclElf::SPIR) { + spirFlag = aclSPIR; + aclTypeBinaryUsed = ACL_TYPE_SPIR_BINARY; + } else { + spirFlag = aclLLVMIR; + aclTypeBinaryUsed = ACL_TYPE_LLVMIR_BINARY; + } + if (ACL_SUCCESS != aclInsertSection(compiler(), bin, - llvmBinary_.data(), llvmBinary_.size(), - spirFlag ? aclSPIR : aclLLVMIR )) { + llvmBinary_.data(), llvmBinary_.size(), spirFlag)) { LogWarning("aclInsertSection failed"); aclBinaryFini(bin); return false; @@ -551,8 +563,7 @@ Program::compileBinaryToISA(amd::option::Options* options) ((amd::option::Options*)bin->options)->setBuildNo(options->getBuildNo()); err = aclCompile(compiler(), bin, options->origOptionStr.c_str(), - spirFlag ? ACL_TYPE_SPIR_BINARY : ACL_TYPE_LLVMIR_BINARY, - ACL_TYPE_ISA, NULL); + aclTypeBinaryUsed, ACL_TYPE_ISA, NULL); buildLog_ += aclGetCompilerLog(compiler()); @@ -865,7 +876,7 @@ Program::compileImpl( } llvmBinary_.assign(reinterpret_cast(llvmir), size); - llvmBinaryIsSpir_ = false; + elfSectionType_ = amd::OclElf::LLVMIR; aclBinaryFini(bin); if (clBinary()->saveSOURCE()) { @@ -1001,7 +1012,7 @@ Program::linkImpl(amd::option::Options* options) } // Need to try recompile, check to see if if LLVM IR is present - if (clBinary()->loadLlvmBinary(llvmBinary_, llvmBinaryIsSpir_) && + if (clBinary()->loadLlvmBinary(llvmBinary_, elfSectionType_) && clBinary()->isRecompilable(llvmBinary_, amd::OclElf::CPU_PLATFORM)) { // Copy both .source and .llvmir into the elfout_ char *section; @@ -1014,7 +1025,7 @@ Program::linkImpl(amd::option::Options* options) } if (clBinary()->saveLLVMIR()) { - clBinary()->elfOut()->addSection(llvmBinaryIsSpir_?amd::OclElf::SPIR:amd::OclElf::LLVMIR, + clBinary()->elfOut()->addSection(elfSectionType_, llvmBinary_.data(), llvmBinary_.size(), false); } @@ -1063,7 +1074,7 @@ Program::linkImpl( { #if defined(WITH_ONLINE_COMPILER) std::vector llvmBinaries(inputPrograms.size()); - std::vector llvmBinaryIsSpir(inputPrograms.size()); + std::vector elfSectionType(inputPrograms.size()); std::vector::const_iterator it = inputPrograms.begin(); std::vector::const_iterator itEnd @@ -1091,7 +1102,7 @@ Program::linkImpl( } // Need to try recompile, check to see if if LLVM IR is present - if (program->clBinary()->loadLlvmBinary(program->llvmBinary_, program->llvmBinaryIsSpir_) && + if (program->clBinary()->loadLlvmBinary(program->llvmBinary_, program->elfSectionType_) && program->clBinary()->isRecompilable(program->llvmBinary_, amd::OclElf::CPU_PLATFORM)) { // Copy both .source and .llvmir into the elfout_ @@ -1117,7 +1128,7 @@ Program::linkImpl( } llvmBinaries[i] = &program->llvmBinary_; - llvmBinaryIsSpir[i] = program->llvmBinaryIsSpir_; + elfSectionType[i] = program->elfSectionType_; } acl_error err = ACL_SUCCESS; @@ -1139,9 +1150,17 @@ Program::linkImpl( break; } + _bif_sections_enum_0_8 aclTypeUsed; + if (elfSectionType[i] == amd::OclElf::SPIRV) { + aclTypeUsed = aclSPIRV; + } else if (elfSectionType[i] == amd::OclElf::SPIR) { + aclTypeUsed = aclSPIR; + } else { + aclTypeUsed = aclLLVMIR; + } err = aclInsertSection(compiler(), libs[i], - llvmBinaries[i]->data(), llvmBinaries[i]->size(), - llvmBinaryIsSpir[i]?aclSPIR:aclLLVMIR); + llvmBinaries[i]->data(), llvmBinaries[i]->size(), aclTypeUsed); + if (err != ACL_SUCCESS) { LogWarning("aclInsertSection failed"); break; @@ -1155,7 +1174,7 @@ Program::linkImpl( if (libs.size() > 0 && err == ACL_SUCCESS) do { unsigned int numLibs = libs.size() - 1; - bool resultIsSPIR = (llvmBinaryIsSpir[0] && numLibs == 0); + if (numLibs > 0) { err = aclLink(compiler(), libs[0], libs.size() - 1, &libs[1], ACL_TYPE_LLVMIR_BINARY, "-create-library", NULL); @@ -1169,8 +1188,16 @@ Program::linkImpl( } size_t size = 0; + _bif_sections_enum_0_8 aclTypeUsed; + if (elfSectionType[0] == amd::OclElf::SPIRV && numLibs == 0) { + aclTypeUsed = aclSPIRV; + } else if (elfSectionType[0] == amd::OclElf::SPIR && numLibs == 0) { + aclTypeUsed = aclSPIR; + } else { + aclTypeUsed = aclLLVMIR; + } const void* llvmir = aclExtractSection(compiler(), libs[0], - &size, resultIsSPIR?aclSPIR:aclLLVMIR, &err); + &size, aclTypeUsed, &err); if (err != ACL_SUCCESS) { LogWarning("aclExtractSection failed"); break; @@ -1187,7 +1214,7 @@ Program::linkImpl( } if (clBinary()->saveLLVMIR()) { - clBinary()->elfOut()->addSection(llvmBinaryIsSpir_?amd::OclElf::SPIR:amd::OclElf::LLVMIR, + clBinary()->elfOut()->addSection(elfSectionType_, llvmBinary_.data(), llvmBinary_.size(), false); diff --git a/rocclr/runtime/device/device.cpp b/rocclr/runtime/device/device.cpp index 132e884720..20b6bbdd21 100644 --- a/rocclr/runtime/device/device.cpp +++ b/rocclr/runtime/device/device.cpp @@ -604,7 +604,7 @@ Program::Program(amd::Device& device) , type_(TYPE_NONE) , clBinary_(NULL) , llvmBinary_() - , llvmBinaryIsSpir_(false) + , elfSectionType_(amd::OclElf::LLVMIR) , compileOptions_() , linkOptions_() , lastBuildOptionsArg_() @@ -1143,7 +1143,7 @@ Program::setBinary(char* binaryIn, size_t size) } case ET_REL: { - if (clBinary()->isSPIR()) { + if (clBinary()->isSPIR() || clBinary()->isSPIRV()) { setType(TYPE_INTERMEDIATE); } else { setType(TYPE_COMPILED); @@ -1552,19 +1552,20 @@ void ClBinary::resetElfOut() } bool -ClBinary::loadLlvmBinary(std::string& llvmBinary, bool& llvmBinaryIsSpir) const +ClBinary::loadLlvmBinary(std::string& llvmBinary, amd::OclElf::oclElfSections& elfSectionType) const { // Check if current binary already has LLVMIR char *section = NULL; size_t sz = 0; - if (elfIn_->getSection(amd::OclElf::LLVMIR, §ion, &sz) && section && sz > 0) { - llvmBinary.append(section, sz); - llvmBinaryIsSpir = false; - return true; - } else if (elfIn_->getSection(amd::OclElf::SPIR, §ion, &sz) && section && sz > 0) { - llvmBinary.append(section, sz); - llvmBinaryIsSpir = true; - return true; + const amd::OclElf::oclElfSections SectionTypes[] = + {amd::OclElf::LLVMIR, amd::OclElf::SPIR, amd::OclElf::SPIRV}; + + for (int i = 0; i < 3; ++i){ + if (elfIn_->getSection(SectionTypes[i], §ion, &sz) && section && sz > 0) { + llvmBinary.append(section, sz); + elfSectionType = SectionTypes[i]; + return true; + } } return false; @@ -1628,6 +1629,18 @@ ClBinary::isSPIR() const return false; } +bool +ClBinary::isSPIRV() const +{ + char *section = NULL; + size_t sz = 0; + + if (elfIn_->getSection(amd::OclElf::SPIRV, §ion, &sz) && section && sz > 0) { + return true; + } + return false; +} + cl_device_partition_property PartitionType::toCL() const { diff --git a/rocclr/runtime/device/device.hpp b/rocclr/runtime/device/device.hpp index 45ef0bfabe..7bc494d8c0 100644 --- a/rocclr/runtime/device/device.hpp +++ b/rocclr/runtime/device/device.hpp @@ -1012,7 +1012,7 @@ private: protected: ClBinary* clBinary_; //!< The CL program binary file std::string llvmBinary_; //!< LLVM IR binary code - bool llvmBinaryIsSpir_; //!< LLVM IR binary code is in SPIR format + amd::OclElf::oclElfSections elfSectionType_; //!< LLVM IR binary code is in SPIR format std::string compileOptions_;//!< compile/build options. std::string linkOptions_; //!< link options. //!< the option arg passed in to clCompileProgram(), clLinkProgram(), @@ -1212,7 +1212,7 @@ public: //! Loads llvmir binary from OCL binary file bool loadLlvmBinary( std::string& llvmBinary, //!< LLVMIR binary code - bool& llvmBinaryIsSpir //!< LLVMIR binary is in SPIR format + amd::OclElf::oclElfSections& elfSectionType //!< LLVMIR binary is in SPIR format ) const; //! Loads compile options from OCL binary file @@ -1275,6 +1275,8 @@ public: // Returns TRUE of binary file is SPIR bool isSPIR() const; + // Returns TRUE of binary file is SPIRV + bool isSPIRV() const; protected: enum Flags { BinaryAllocated = 0x1, //!< Binary was created diff --git a/rocclr/runtime/device/gpu/gpucompiler.cpp b/rocclr/runtime/device/gpu/gpucompiler.cpp index d75b732872..d70118eb26 100644 --- a/rocclr/runtime/device/gpu/gpucompiler.cpp +++ b/rocclr/runtime/device/gpu/gpucompiler.cpp @@ -213,7 +213,7 @@ NullProgram::compileImpl(const std::string& src, } llvmBinary_.assign(reinterpret_cast(ir), len); - llvmBinaryIsSpir_ = false; + elfSectionType_ = amd::OclElf::LLVMIR; aclBinaryFini(bin); for (size_t i = 0; i < headerFileNames.size(); ++i) { @@ -260,11 +260,23 @@ NullProgram::compileBinaryToIL(amd::option::Options* options) LogWarning("aclBinaryInit failed"); return CL_BUILD_PROGRAM_FAILURE; } - bool spirFlag = std::string::npos != options->clcOptions.find("--spir") - || llvmBinaryIsSpir_; + aclSections_0_8 spirFlag; + _acl_type_enum_0_8 aclTypeBinaryUsed; + if (std::string::npos != options->clcOptions.find("--spirv") + || elfSectionType_ == amd::OclElf::SPIRV) { + spirFlag = aclSPIRV; + aclTypeBinaryUsed = ACL_TYPE_SPIRV_BINARY; + } else if (std::string::npos != options->clcOptions.find("--spir") + || elfSectionType_ == amd::OclElf::SPIR) { + spirFlag = aclSPIR; + aclTypeBinaryUsed = ACL_TYPE_SPIR_BINARY; + } else { + spirFlag = aclLLVMIR; + aclTypeBinaryUsed = ACL_TYPE_LLVMIR_BINARY; + } + if (ACL_SUCCESS != aclInsertSection(dev().compiler(), bin, - llvmBinary_.data(), llvmBinary_.size(), - spirFlag ? aclSPIR : aclLLVMIR)) { + llvmBinary_.data(), llvmBinary_.size(), spirFlag)) { LogWarning("aclInsertSection failed"); aclBinaryFini(bin); return CL_BUILD_PROGRAM_FAILURE; @@ -289,10 +301,9 @@ NullProgram::compileBinaryToIL(amd::option::Options* options) if (options->oVariables->BinBIF30) { type = ACL_TYPE_ISA; } - err = aclCompile(dev().compiler(), bin, optionStr.c_str(), - spirFlag ? ACL_TYPE_SPIR_BINARY : ACL_TYPE_LLVMIR_BINARY, - type, NULL); + err = aclCompile(dev().compiler(), bin, optionStr.c_str(), + aclTypeBinaryUsed, type, NULL); buildLog_ += aclGetCompilerLog(dev().compiler()); if (err != ACL_SUCCESS) { diff --git a/rocclr/runtime/device/gpu/gpuprogram.cpp b/rocclr/runtime/device/gpu/gpuprogram.cpp index 3b915235b4..78e8442c53 100644 --- a/rocclr/runtime/device/gpu/gpuprogram.cpp +++ b/rocclr/runtime/device/gpu/gpuprogram.cpp @@ -223,8 +223,8 @@ NullProgram::linkImpl(amd::option::Options* options) clBinary()->elfOut()->addSection(amd::OclElf::SOURCE, section, sz); } if (clBinary()->saveLLVMIR()) { - if (clBinary()->loadLlvmBinary(llvmBinary_, llvmBinaryIsSpir_) && (!llvmBinary_.empty())) { - clBinary()->elfOut()->addSection(llvmBinaryIsSpir_?amd::OclElf::SPIR:amd::OclElf::LLVMIR, + if (clBinary()->loadLlvmBinary(llvmBinary_, elfSectionType_) && (!llvmBinary_.empty())) { + clBinary()->elfOut()->addSection(elfSectionType_, llvmBinary_.data(), llvmBinary_.size(), false); } } @@ -243,7 +243,7 @@ NullProgram::linkImpl(amd::option::Options* options) } return true; } - else if (clBinary()->loadLlvmBinary(llvmBinary_, llvmBinaryIsSpir_) && + else if (clBinary()->loadLlvmBinary(llvmBinary_, elfSectionType_) && clBinary()->isRecompilable(llvmBinary_, amd::OclElf::CAL_PLATFORM)) { char *section; size_t sz; @@ -260,7 +260,7 @@ NullProgram::linkImpl(amd::option::Options* options) clBinary()->elfOut()->addSection(amd::OclElf::SOURCE, section, sz); } if (clBinary()->saveLLVMIR()) { - clBinary()->elfOut()->addSection(llvmBinaryIsSpir_?amd::OclElf::SPIR:amd::OclElf::LLVMIR, + clBinary()->elfOut()->addSection(elfSectionType_, llvmBinary_.data(), llvmBinary_.size(), false); } } @@ -509,7 +509,7 @@ NullProgram::linkImpl(const std::vector& inputPrograms, bool createLibrary) { std::vector llvmBinaries(inputPrograms.size()); - std::vector llvmBinaryIsSpir(inputPrograms.size()); + std::vector elfSectionType(inputPrograms.size()); std::vector::const_iterator it = inputPrograms.begin(); std::vector::const_iterator itEnd @@ -533,7 +533,7 @@ NullProgram::linkImpl(const std::vector& inputPrograms, return false; } if (!program->clBinary()->loadLlvmBinary(program->llvmBinary_, - program->llvmBinaryIsSpir_)) { + program->elfSectionType_)) { buildLog_ += "Internal error: Failed loading compiled binary!\n"; LogError("Bad OCL Binary"); @@ -560,7 +560,7 @@ NullProgram::linkImpl(const std::vector& inputPrograms, } llvmBinaries[i] = &program->llvmBinary_; - llvmBinaryIsSpir[i] = program->llvmBinaryIsSpir_; + elfSectionType[i] = program->elfSectionType_; } acl_error err; @@ -580,9 +580,16 @@ NullProgram::linkImpl(const std::vector& inputPrograms, break; } + _bif_sections_enum_0_8 aclTypeUsed; + if (elfSectionType[i] == amd::OclElf::SPIRV) { + aclTypeUsed = aclSPIRV; + } else if (elfSectionType[i] == amd::OclElf::SPIR) { + aclTypeUsed = aclSPIR; + } else { + aclTypeUsed = aclLLVMIR; + } err = aclInsertSection(dev().compiler(), libs[i], - llvmBinaries[i]->data(), llvmBinaries[i]->size(), - llvmBinaryIsSpir[i]?aclSPIR:aclLLVMIR); + llvmBinaries[i]->data(), llvmBinaries[i]->size(), aclTypeUsed); if (err != ACL_SUCCESS) { LogWarning("aclInsertSection failed"); break; @@ -597,7 +604,6 @@ NullProgram::linkImpl(const std::vector& inputPrograms, if (libs.size() > 0 && err == ACL_SUCCESS) do { unsigned int numLibs = libs.size() - 1; - bool resultIsSPIR = (llvmBinaryIsSpir[0] && numLibs == 0); if (numLibs > 0) { err = aclLink(dev().compiler(), libs[0], numLibs, &libs[1], @@ -612,15 +618,23 @@ NullProgram::linkImpl(const std::vector& inputPrograms, } size_t size = 0; + _bif_sections_enum_0_8 aclTypeUsed; + if (elfSectionType[0] == amd::OclElf::SPIRV && numLibs == 0) { + aclTypeUsed = aclSPIRV; + } else if (elfSectionType[0] == amd::OclElf::SPIR && numLibs == 0) { + aclTypeUsed = aclSPIR; + } else { + aclTypeUsed = aclLLVMIR; + } const void* llvmir = aclExtractSection(dev().compiler(), libs[0], - &size, resultIsSPIR?aclSPIR:aclLLVMIR, &err); + &size, aclTypeUsed, &err); if (err != ACL_SUCCESS) { LogWarning("aclExtractSection failed"); break; } llvmBinary_.assign(reinterpret_cast(llvmir), size); - llvmBinaryIsSpir_ = false; + elfSectionType_ = amd::OclElf::LLVMIR; } while(0); std::for_each(libs.begin(), libs.end(), std::ptr_fun(aclBinaryFini));