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));