P4 to Git Change 1611613 by gandryey@gera-w8 on 2018/09/27 12:54:08
SWDEV-79445 - OCL generic changes and code clean-up Program compilation clean-up. Step#5: - Move the first linkImpl() method to the abstraciton layer. Utilize the new method in GPU/PAL/ROCr backends Affected files ... ... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.cpp#7 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.hpp#5 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#244 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.hpp#77 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.cpp#78 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.hpp#34 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#90 edit ... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.hpp#39 edit
Этот коммит содержится в:
@@ -481,6 +481,203 @@ bool Program::compileImplHSAIL(const std::string& sourceCode,
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::linkImpl(const std::vector<device::Program*>& inputPrograms,
|
||||
amd::option::Options* options, bool createLibrary) {
|
||||
if (isLC()) {
|
||||
return linkImplLC(inputPrograms, options, createLibrary);
|
||||
}
|
||||
else {
|
||||
return linkImplHSAIL(inputPrograms, options, createLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::linkImplHSAIL(const std::vector<Program*>& inputPrograms,
|
||||
amd::option::Options* options, bool createLibrary) {
|
||||
#if defined(WITH_COMPILER_LIB) || !defined(WITH_LIGHTNING_COMPILER)
|
||||
acl_error errorCode;
|
||||
|
||||
// For each program we need to extract the LLVMIR and create
|
||||
// aclBinary for each
|
||||
std::vector<aclBinary*> binaries_to_link;
|
||||
|
||||
for (auto program : inputPrograms) {
|
||||
// Check if the program was created with clCreateProgramWIthBinary
|
||||
binary_t binary = program->binary();
|
||||
if ((binary.first != nullptr) && (binary.second > 0)) {
|
||||
// Binary already exists -- we can also check if there is no
|
||||
// opencl source code
|
||||
// Need to check if LLVMIR exists in the binary
|
||||
// If LLVMIR does not exist then is it valid
|
||||
// We need to pull out all the compiled kernels
|
||||
// We cannot do this at present because we need at least
|
||||
// Hsail text to pull the kernels oout
|
||||
void* mem = const_cast<void*>(binary.first);
|
||||
binaryElf_ = aclReadFromMem(mem, binary.second, &errorCode);
|
||||
if (errorCode != ACL_SUCCESS) {
|
||||
LogWarning("Error while linking : Could not read from raw binary");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// At this stage each Program contains a valid binary_elf
|
||||
// Check if LLVMIR is in the binary
|
||||
size_t boolSize = sizeof(bool);
|
||||
bool containsLLLVMIR = false;
|
||||
errorCode = aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_LLVMIR,
|
||||
nullptr, &containsLLLVMIR, &boolSize);
|
||||
|
||||
if (errorCode != ACL_SUCCESS || !containsLLLVMIR) {
|
||||
bool spirv = false;
|
||||
size_t boolSize = sizeof(bool);
|
||||
errorCode = aclQueryInfo(
|
||||
device().compiler(), binaryElf_, RT_CONTAINS_SPIRV, nullptr, &spirv, &boolSize);
|
||||
if (errorCode != ACL_SUCCESS) {
|
||||
spirv = false;
|
||||
}
|
||||
if (spirv) {
|
||||
errorCode = aclCompile(
|
||||
device().compiler(), binaryElf_, options->origOptionStr.c_str(),
|
||||
ACL_TYPE_SPIRV_BINARY, ACL_TYPE_LLVMIR_BINARY, nullptr);
|
||||
buildLog_ += aclGetCompilerLog(device().compiler());
|
||||
if (errorCode != ACL_SUCCESS) {
|
||||
buildLog_ += "Error while linking: Could not load SPIR-V";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
buildLog_ += "Error while linking : Invalid binary (Missing LLVMIR section)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Create a new aclBinary for each LLVMIR and save it in a list
|
||||
aclBIFVersion ver = aclBinaryVersion(binaryElf_);
|
||||
aclBinary* bin = aclCreateFromBinary(binaryElf_, ver);
|
||||
binaries_to_link.push_back(bin);
|
||||
}
|
||||
|
||||
errorCode = aclLink(device().compiler(), binaries_to_link[0], binaries_to_link.size() - 1,
|
||||
binaries_to_link.size() > 1 ? &binaries_to_link[1] : nullptr,
|
||||
ACL_TYPE_LLVMIR_BINARY, "-create-library", nullptr);
|
||||
if (errorCode != ACL_SUCCESS) {
|
||||
buildLog_ += aclGetCompilerLog(device().compiler());
|
||||
buildLog_ += "Error while linking : aclLink failed";
|
||||
return false;
|
||||
}
|
||||
// Store the newly linked aclBinary for this program.
|
||||
binaryElf_ = binaries_to_link[0];
|
||||
// Free all the other aclBinaries
|
||||
for (size_t i = 1; i < binaries_to_link.size(); i++) {
|
||||
aclBinaryFini(binaries_to_link[i]);
|
||||
}
|
||||
if (createLibrary) {
|
||||
saveBinaryAndSetType(TYPE_LIBRARY);
|
||||
buildLog_ += aclGetCompilerLog(device().compiler());
|
||||
return true;
|
||||
}
|
||||
// Now call linkImpl with the new options
|
||||
return linkImpl(options);
|
||||
#else
|
||||
return false;
|
||||
#endif // defined(WITH_COMPILER_LIB) || !defined(WITH_LIGHTNING_COMPILER)
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::linkImplLC(const std::vector<Program*>& inputPrograms,
|
||||
amd::option::Options* options, bool createLibrary) {
|
||||
#if defined(WITH_LIGHTNING_COMPILER)
|
||||
using namespace amd::opencl_driver;
|
||||
std::unique_ptr<Compiler> C(newCompilerInstance());
|
||||
|
||||
std::vector<Data*> inputs;
|
||||
for (auto program : inputPrograms) {
|
||||
if (program->llvmBinary_.empty()) {
|
||||
if (program->clBinary() == NULL) {
|
||||
buildLog_ += "Internal error: Input program not compiled!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are using CL binary directly.
|
||||
// Setup elfIn() and try to load llvmIR from binary
|
||||
// This elfIn() will be released at the end of build by finiBuild().
|
||||
if (!program->clBinary()->setElfIn()) {
|
||||
buildLog_ += "Internal error: Setting input OCL binary failed!\n";
|
||||
return false;
|
||||
}
|
||||
if (!program->clBinary()->loadLlvmBinary(program->llvmBinary_, program->elfSectionType_)) {
|
||||
buildLog_ += "Internal error: Failed loading compiled binary!\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (program->elfSectionType_ != amd::OclElf::LLVMIR) {
|
||||
buildLog_ += "Error: Input binary format is not supported\n.";
|
||||
return false;
|
||||
}
|
||||
|
||||
Data* input = C->NewBufferReference(DT_LLVM_BC, (const char*)program->llvmBinary_.data(),
|
||||
program->llvmBinary_.size());
|
||||
|
||||
if (!input) {
|
||||
buildLog_ += "Internal error: Failed to open the compiled programs.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// release elfIn() for the program
|
||||
program->clBinary()->resetElfIn();
|
||||
|
||||
inputs.push_back(input);
|
||||
}
|
||||
|
||||
// open the linked output
|
||||
amd::opencl_driver::Buffer* output = C->NewBuffer(DT_LLVM_BC);
|
||||
|
||||
if (!output) {
|
||||
buildLog_ += "Error: Failed to open the linked program.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> linkOptions;
|
||||
|
||||
// NOTE: The params is also used to identy cached code object. This parameter
|
||||
// should not contain any dyanamically generated filename.
|
||||
bool ret = device().cacheCompilation()->linkLLVMBitcode(
|
||||
C.get(), inputs, output, linkOptions, buildLog_);
|
||||
buildLog_ += C->Output();
|
||||
if (!ret) {
|
||||
buildLog_ += "Error: Linking bitcode failed: linking source & IR libraries.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
llvmBinary_.assign(output->Buf().data(), output->Size());
|
||||
elfSectionType_ = amd::OclElf::LLVMIR;
|
||||
|
||||
if (clBinary()->saveLLVMIR()) {
|
||||
clBinary()->elfOut()->addSection(amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(),
|
||||
false);
|
||||
// store the original link options
|
||||
clBinary()->storeLinkOptions(linkOptions_);
|
||||
// store the original compile options
|
||||
clBinary()->storeCompileOptions(compileOptions_);
|
||||
}
|
||||
|
||||
// skip the rest if we are building an opencl library
|
||||
if (createLibrary) {
|
||||
setType(TYPE_LIBRARY);
|
||||
if (!createBinary(options)) {
|
||||
buildLog_ += "Internal error: creating OpenCL binary failed\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return linkImpl(options);
|
||||
#else
|
||||
return false;
|
||||
#endif // defined(WITH_LIGHTNING_COMPILER)
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::initClBinary() {
|
||||
if (clBinary_ == nullptr) {
|
||||
|
||||
Ссылка в новой задаче
Block a user