From 0495f895a20e4d9c343f8a573fee32dc859441c9 Mon Sep 17 00:00:00 2001 From: foreman Date: Tue, 13 Sep 2016 16:16:35 -0400 Subject: [PATCH] P4 to Git Change 1313945 by wchau@wchau_OCL_boltzmann on 2016/09/13 15:57:45 SWDEV-94605 - [OCL-LC-ROCm] ability to load offline (and online) generated binaries using the HSA code object format Affected files ... ... //depot/stg/opencl/drivers/opencl/runtime/device/device.cpp#203 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompiler.cpp#17 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#35 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.hpp#14 edit ... //depot/stg/opencl/drivers/opencl/runtime/platform/program.cpp#83 edit --- rocclr/runtime/device/device.cpp | 23 +++- rocclr/runtime/device/rocm/roccompiler.cpp | 2 +- rocclr/runtime/device/rocm/rocprogram.cpp | 138 ++++++++++++++------- rocclr/runtime/device/rocm/rocprogram.hpp | 1 + rocclr/runtime/platform/program.cpp | 19 ++- 5 files changed, 128 insertions(+), 55 deletions(-) diff --git a/rocclr/runtime/device/device.cpp b/rocclr/runtime/device/device.cpp index 943dc516de..4e7b26fdfc 100644 --- a/rocclr/runtime/device/device.cpp +++ b/rocclr/runtime/device/device.cpp @@ -1304,6 +1304,27 @@ Program::setBinary(char* binaryIn, size_t size) clBinary()->loadCompileOptions(compileOptions_); clBinary()->loadLinkOptions(linkOptions_); +#if defined(WITH_LIGHTNING_COMPILER) + //TODO: Remove this once BIF is no longer used as we should have a machinasm in + // place to get the binary type correctly from above. + // It is a workaround for executable build from the library. The code object + // binary does not have the type information. + + char *sect = NULL; + size_t sz = 0; + if (clBinary()->elfIn()->getSection(amd::OclElf::TEXT, §, &sz) && sect && sz > 0) { + setType(TYPE_EXECUTABLE); + } + + sect = NULL; + sz = 0; + if (type != ET_DYN && // binary is not a library + (clBinary()->elfIn()->getSection(amd::OclElf::LLVMIR, §, &sz) && sect && sz > 0)) + { + setType(TYPE_COMPILED); + } + +#endif clBinary()->resetElfIn(); return true; } @@ -1312,7 +1333,7 @@ bool Program::createBIFBinary(aclBinary* bin) { #if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_Wilkin"); + assert(!"createBIFBinary() should not be called when using LC"); return false; #else // defined(WITH_LIGHTNING_COMPILER) acl_error err; diff --git a/rocclr/runtime/device/rocm/roccompiler.cpp b/rocclr/runtime/device/rocm/roccompiler.cpp index c094e473c9..fc2c4cfa5e 100644 --- a/rocclr/runtime/device/rocm/roccompiler.cpp +++ b/rocclr/runtime/device/rocm/roccompiler.cpp @@ -213,7 +213,7 @@ HSAILProgram::compileImpl_LC( bool ret = C->CompileToLLVMBitcode(inputs, output, params); buildLog_ += C->Output(); if (!ret) { - buildLog_ += "Error while compiling opencl source: Compiling CL to IR"; + buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n"; return false; } diff --git a/rocclr/runtime/device/rocm/rocprogram.cpp b/rocclr/runtime/device/rocm/rocprogram.cpp index 8347e0b44a..2668557ccb 100644 --- a/rocclr/runtime/device/rocm/rocprogram.cpp +++ b/rocclr/runtime/device/rocm/rocprogram.cpp @@ -225,40 +225,33 @@ HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStage size_t boolSize = sizeof(bool); //! @todo Should we also check for ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT? // Checking llvmir in .llvmir section - bool containsLlvmirText = true; -#if defined(WITH_LIGHTNING_COMPILER) - // TODO:FIXME_Wilkin - Query - bool containsOpts = false; bool containsHsailText = false; bool containsBrig = false; -#else // !defined(WITH_LIGHTNING_COMPILER) + bool containsLlvmirText = (type() == TYPE_COMPILED); + bool containsShaderIsa = (type() == TYPE_EXECUTABLE); + bool containsOpts = !(compileOptions_.empty() && linkOptions_.empty()); +#if !defined(WITH_LIGHTNING_COMPILER) // !defined(WITH_LIGHTNING_COMPILER) errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_LLVMIR, NULL, &containsLlvmirText, &boolSize); if (errorCode != ACL_SUCCESS) { containsLlvmirText = false; } // Checking compile & link options in .comment section - bool containsOpts = true; errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_OPTIONS, NULL, &containsOpts, &boolSize); if (errorCode != ACL_SUCCESS) { containsOpts = false; } - if (containsLlvmirText && containsOpts) { - completeStages.push_back(from); - from = ACL_TYPE_LLVMIR_BINARY; - } // Checking HSAIL in .cg section - bool containsHsailText = true; + containsHsailText = true; errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_HSAIL, NULL, &containsHsailText, &boolSize); if (errorCode != ACL_SUCCESS) { containsHsailText = false; } // Checking BRIG sections - bool containsBrig = true; + containsBrig = true; errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_BRIG, NULL, &containsBrig, &boolSize); if (errorCode != ACL_SUCCESS) { containsBrig = false; } -#endif // !defined(WITH_LIGHTNING_COMPILER) if (containsBrig) { completeStages.push_back(from); from = ACL_TYPE_HSAIL_BINARY; @@ -277,17 +270,16 @@ HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStage completeStages.push_back(from); from = ACL_TYPE_HSAIL_TEXT; } - // Checking ISA in .text section - bool containsShaderIsa = true; -#if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_Wilkin"); - errorCode = ACL_ERROR; -#else // !defined(WITH_LIGHTNING_COMPILER) errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_ISA, NULL, &containsShaderIsa, &boolSize); -#endif // !defined(WITH_LIGHTNING_COMPILER) if (errorCode != ACL_SUCCESS) { containsShaderIsa = false; } +#endif // !defined(WITH_LIGHTNING_COMPILER) + + if (containsLlvmirText && containsOpts) { + completeStages.push_back(from); + from = ACL_TYPE_LLVMIR_BINARY; + } if (containsShaderIsa) { completeStages.push_back(from); from = ACL_TYPE_ISA; @@ -316,6 +308,7 @@ HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStage if (curOptions.oVariables->BinLLVMIR || !containsLlvmirText || !containsOpts) { needOptionsCheck = false; } +#if !defined(WITH_LIGHTNING_COMPILER) if (containsBrig && containsHsailText && curOptions.oVariables->BinHSAIL) { needOptionsCheck = false; // recompile from prev. stage, if BRIG || HSAIL are absent @@ -324,6 +317,7 @@ HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStage completeStages.pop_back(); needOptionsCheck = true; } +#endif break; // recompilation might be needed case ACL_TYPE_LLVMIR_BINARY: @@ -341,25 +335,38 @@ HSAILProgram::getNextCompilationStageFromBinary(amd::option::Options* options) binary_t binary = this->binary(); // If the binary already exists if ((binary.first != NULL) && (binary.second > 0)) { +#if defined(WITH_LIGHTNING_COMPILER) + hsa_status_t status = hsa_code_object_deserialize( (void *) binary.first, + binary.second, NULL, &hsaProgramCodeObject_ ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Deserialize code object failed.\n"; + return continueCompileFrom; + } + void *mem = reinterpret_cast(hsaProgramCodeObject_.handle); +#else // !defined(WITH_LIGHTNING_COMPILER) void *mem = const_cast(binary.first); acl_error errorCode; -#if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_lmoriche: deserialize the code object, extract the metadata"); -#else // !defined(WITH_LIGHTNING_COMPILER) binaryElf_ = g_complibApi._aclReadFromMem(mem, binary.second, &errorCode); if (errorCode != ACL_SUCCESS) { buildLog_ += "Error while BRIG Codegen phase: aclReadFromMem failure \n" ; return continueCompileFrom; } #endif // !defined(WITH_LIGHTNING_COMPILER) + + // save the current options + std::string sCurCompileOptions = compileOptions_; + std::string sCurLinkOptions = linkOptions_; + std::string sCurOptions = compileOptions_ + linkOptions_; + + // Saving binary in the interface class, + // which also load compile & link options from binary + setBinary(static_cast(mem), binary.second); + // Calculate the next stage to compile from, based on sections in binaryElf_; // No any validity checks here std::vector completeStages; bool needOptionsCheck = true; continueCompileFrom = getCompilationStagesFromBinary(completeStages, needOptionsCheck); - // Saving binary in the interface class, - // which also load compile & link options from binary - setBinary(static_cast(mem), binary.second); if (!options || !needOptionsCheck) { return continueCompileFrom; } @@ -373,23 +380,27 @@ HSAILProgram::getNextCompilationStageFromBinary(amd::option::Options* options) // If compile options are absent in binary, do not compare and recompile if (compileOptions_.empty()) break; + +#if defined(WITH_LIGHTNING_COMPILER) + std::string sBinOptions = compileOptions_ + linkOptions_; +#else // !defined(WITH_LIGHTNING_COMPILER) const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symOpenclCompilerOptions); assert(symbol && "symbol not found"); std::string symName = std::string(symbol->str[bif::PRE]) + std::string(symbol->str[bif::POST]); size_t symSize = 0; -#if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_Wilkin"); - const void *opts = NULL; -#else // !defined(WITH_LIGHTNING_COMPILER) + const void *opts = g_complibApi._aclExtractSymbol(device().compiler(), binaryElf_, &symSize, aclCOMMENT, symName.c_str(), &errorCode); if (errorCode != ACL_SUCCESS) { recompile = true; break; } -#endif // !defined(WITH_LIGHTNING_COMPILER) std::string sBinOptions = std::string((char*)opts, symSize); - std::string sCurOptions = compileOptions_ + linkOptions_; +#endif // !defined(WITH_LIGHTNING_COMPILER) + + compileOptions_ = sCurCompileOptions; + linkOptions_ = sCurLinkOptions; + amd::option::Options curOptions, binOptions; if (!amd::option::parseAllOptions(sBinOptions, binOptions)) { buildLog_ += binOptions.optionsLog(); @@ -445,12 +456,22 @@ HSAILProgram::saveBinaryAndSetType(type_t type) void *rawBinary = NULL; size_t size = 0; #if defined(WITH_LIGHTNING_COMPILER) - hsa_callback_data_t allocData = {0}; - if (hsa_code_object_serialize(hsaProgramCodeObject_, - allocFunc, allocData, - NULL, &rawBinary, &size) != HSA_STATUS_SUCCESS) { - buildLog_ += "Failed to write binary to memory \n"; - return false; + if (type == TYPE_EXECUTABLE) { // handle code object binary + hsa_callback_data_t allocData = {0}; + if (hsa_code_object_serialize(hsaProgramCodeObject_, + allocFunc, allocData, + NULL, &rawBinary, &size) != HSA_STATUS_SUCCESS) { + buildLog_ += "ERROR: Failed to write code object binary to memory \n"; + return false; + } + } + else { // handle LLVM binary + if (llvmBinary_.empty()) { + buildLog_ += "ERROR: Tried to save emtpy LLVM binary \n"; + return false; + } + rawBinary = (void*) llvmBinary_.data(); + size = llvmBinary_.size(); } #else // !defined(WITH_LIGHTNING_COMPILER) if (g_complibApi._aclWriteToMem(binaryElf_, &rawBinary, &size) @@ -462,12 +483,15 @@ HSAILProgram::saveBinaryAndSetType(type_t type) clBinary()->saveBIFBinary((char*)rawBinary, size); //Set the type of binary setType(type); + //Free memory containing rawBinary -#if !defined(WITH_LIGHTNING_COMPILER) +#if defined(WITH_LIGHTNING_COMPILER) + if (type == TYPE_EXECUTABLE) { // handle code object binary + free(rawBinary); + } +#else binaryElf_->binOpts.dealloc(rawBinary); -#else // defined(WITH_LIGHTNING_COMPILER) - free(rawBinary); -#endif // defined(WITH_LIGHTNING_COMPILER) +#endif return true; } @@ -517,6 +541,9 @@ HSAILProgram::linkImpl_LC( return false; } + // release elfIn() for the program + program->clBinary()->resetElfIn(); + inputs.push_back(input); } @@ -554,7 +581,7 @@ HSAILProgram::linkImpl_LC( if (!createBinary(options)) { buildLog_ += "Internal error: creating OpenCL binary failed\n"; return false; - } + } return true; } @@ -935,10 +962,14 @@ HSAILProgram::linkImpl_LC(amd::option::Options *options) } } + return setKernels_LC( options, out_exec->Buf().data(), out_exec->Size() ); +} + +bool +HSAILProgram::setKernels_LC(amd::option::Options *options, void* binary, size_t binSize) +{ hsa_status_t status; - status = hsa_code_object_deserialize( out_exec->Buf().data(), - out_exec->Size(), - NULL, &hsaProgramCodeObject_ ); + status = hsa_code_object_deserialize( binary, binSize, NULL, &hsaProgramCodeObject_ ); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: Failed to deserialize the AMD HSA Code Object: "; buildLog_ += hsa_strerror(status); @@ -977,7 +1008,7 @@ HSAILProgram::linkImpl_LC(amd::option::Options *options) } // load the runtime metadata - amd::OclElf elf(ELFCLASS64, out_exec->Buf().data(), out_exec->Size(), NULL, ELF_C_READ); + amd::OclElf elf(ELFCLASS64, (char*) binary, binSize, NULL, ELF_C_READ); char* data; size_t size; @@ -1155,9 +1186,20 @@ HSAILProgram::linkImpl(amd::option::Options *options) } case ACL_TYPE_CG: break; - case ACL_TYPE_ISA: + case ACL_TYPE_ISA: { +#if defined(WITH_LIGHTNING_COMPILER) + binary_t isaBinary = binary(); + if ((isaBinary.first != NULL) && (isaBinary.second > 0)) { + return setKernels_LC(options, (void*) isaBinary.first, isaBinary.second ); + } + else { + buildLog_ += "Error: code object is empty \n" ; + return false; + } +#endif // !defined(WITH_LIGHTNING_COMPILER) finalize = false; break; + } default: buildLog_ += "Error while BRIG Codegen phase: the binary is incomplete \n" ; return false; diff --git a/rocclr/runtime/device/rocm/rocprogram.hpp b/rocclr/runtime/device/rocm/rocprogram.hpp index b5780a484e..5bd1396df1 100644 --- a/rocclr/runtime/device/rocm/rocprogram.hpp +++ b/rocclr/runtime/device/rocm/rocprogram.hpp @@ -96,6 +96,7 @@ protected: virtual bool linkImpl(amd::option::Options* options); #if defined(WITH_LIGHTNING_COMPILER) virtual bool linkImpl_LC(amd::option::Options* options); + bool setKernels_LC(amd::option::Options* options, void *binary, size_t binSize); #endif // defined(WITH_LIGHTNING_COMPILER) //! Link the device programs. diff --git a/rocclr/runtime/platform/program.cpp b/rocclr/runtime/platform/program.cpp index 53ec74dc90..ab90eca979 100644 --- a/rocclr/runtime/platform/program.cpp +++ b/rocclr/runtime/platform/program.cpp @@ -78,11 +78,8 @@ Program::addDeviceProgram(Device& device, const void* image, size_t length, options = &emptyOpts; emptyOptions = true; } -#if defined(WITH_LIGHTNING_COMPILER) - if (image != NULL && length != 0 && amd::isElfMagic((const char *) image)) { - // TODO: Wilkin: extract compiler options from the .comment section - } -#else // !defined(WITH_LIGHTNING_COMPILER) + +#if !defined(WITH_LIGHTNING_COMPILER) if (image != NULL && length != 0 && aclValidateBinaryImage(image, length, BINARY_TYPE_ELF)) { acl_error errorCode; aclBinary *binary = aclReadFromMem(image, length, &errorCode); @@ -133,6 +130,18 @@ Program::addDeviceProgram(Device& device, const void* image, size_t length, delete program; return CL_INVALID_BINARY; } + +#if defined(WITH_LIGHTNING_COMPILER) + // load the compiler options from the binary if it is not provided + std::string sBinOptions = program->compileOptions(); + if (!sBinOptions.empty() && emptyOptions) { + if (!amd::option::parseAllOptions(sBinOptions, *options)) { + programLog_ = options->optionsLog(); + LogError("Parsing compilation options from binary failed."); + return CL_INVALID_COMPILER_OPTIONS; + } + } +#endif } devicePrograms_[&rootDev] = program;