From c2967ef855d99f820590263d0ce4ef2f7b699895 Mon Sep 17 00:00:00 2001
From: foreman
Date: Fri, 15 Aug 2014 08:23:45 -0400
Subject: [PATCH] P4 to Git Change 1066820 by emankov@em-hsa-amd on 2014/08/15
08:16:18
ECR #333753 - Compiler Lib/RT: added compilation from HSAIL & BRIG
Added support for the following compilations:
ACL_TYPE_HSAIL_TEXT -> ACL_TYPE_HSAIL_BINARY
ACL_TYPE_HSAIL_TEXT -> ACL_TYPE_CG
ACL_TYPE_HSAIL_TEXT -> ACL_TYPE_ISA
ACL_TYPE_HSAIL_BINARY -> ACL_TYPE_HSAIL_TEXT
ACL_TYPE_HSAIL_BINARY -> ACL_TYPE_CG
ACL_TYPE_HSAIL_BINARY -> ACL_TYPE_ISA
Testing: smoke, smoke_clang, pre check-in, ocl conformance api, compiler
Reviewers: Nikolay Haustov, Matthew Arsenault, German Andryeyev
Affected files ...
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/v0_8/if_acl.cpp#45 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/gpu/hsail_be.cpp#30 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/gpu/hsail_be.hpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#173 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.hpp#53 edit
---
.../lib/backends/common/v0_8/if_acl.cpp | 163 +++++++++++++++--
rocclr/runtime/device/gpu/gpuprogram.cpp | 164 +++++++++---------
rocclr/runtime/device/gpu/gpuprogram.hpp | 5 +-
3 files changed, 230 insertions(+), 102 deletions(-)
diff --git a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
index 14608bb8e8..8cb38c4a67 100644
--- a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
+++ b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp
@@ -1113,7 +1113,7 @@ aclCompileInternal(
if (error_code != ACL_SUCCESS) {
goto internal_compile_failure;
}
- } else if (useLinker || useOpt || useCG) {
+ } else if (useLinker || useOpt) {
// Load a temp frontend object to convert from string LLVM-IR to LLVM Module.
ald = cl->feAPI.init(cl, bin, compile_callback, &error_code);
module = cl->feAPI.toModule(ald, data, data_size, context, &error_code);
@@ -1155,23 +1155,39 @@ aclCompileInternal(
bHsailTextInput = true;
if (bin && bin->options) {
amd::option::Options* Opts = reinterpret_cast(bin->options);
- // Verify that the internal (blit) kernel is not being compiled
+ // Verify that the internal (blit) kernel is not being compiled
size_t ifind = Opts->origOptionStr.find("-cl-internal-kernel");
if (ifind != std::string::npos)
bHsailTextInput = false;
}
}
- if (!bHsailTextInput)
- {
- std::string* output = (std::string*) cl->cgAPI.codegen(ald, module, context, &error_code);
-
- if (error_code != ACL_SUCCESS) {
- goto internal_compile_failure;
- }
-
+ if (!bHsailTextInput) {
amdcl::HSAIL *acl = reinterpret_cast(ald);
- if (acl == NULL || !acl->insertBRIG(*output)) {
- assert(!"Inserting BRIG failed\n");
+ assert(acl && "Inserting BRIG failed\n");
+ // from ACL_TYPE_HSAIL_BINARY
+ if (!useFE && !useLinker && !useOpt) {
+ int result = 0;
+ HSAIL_ASM::BrigContainer c;
+ // BRIG is in aclSOURCE section
+ if (data) {
+ result = HSAIL_ASM::BrigStreamer::load(c, data, data_size);
+ // BRIG is in its corresponding BIF sections
+ } else {
+ if (!acl->extractBRIG(c)) {
+ error_code = ACL_CODEGEN_ERROR;
+ goto internal_compile_failure;
+ }
+ }
+ if (result != 0 || !acl->insertBRIG(c)) {
+ error_code = ACL_CODEGEN_ERROR;
+ goto internal_compile_failure;
+ }
+ } else {
+ std::string* output = (std::string*) cl->cgAPI.codegen(ald, module, context, &error_code);
+ if (error_code != ACL_SUCCESS || !acl->insertBRIG(*output)) {
+ error_code = ACL_CODEGEN_ERROR;
+ goto internal_compile_failure;
+ }
}
}
else
@@ -1371,17 +1387,32 @@ if_aclCompile(aclCompiler *cl,
if ((from == ACL_TYPE_AMDIL_TEXT
|| from == ACL_TYPE_AMDIL_BINARY
- || from == ACL_TYPE_HSAIL_TEXT
- || from == ACL_TYPE_HSAIL_BINARY
|| from == ACL_TYPE_X86_TEXT
|| from == ACL_TYPE_X86_BINARY)
&& to != ACL_TYPE_ISA) {
return ACL_INVALID_ARG;
}
+ if ((from == ACL_TYPE_HSAIL_TEXT
+ || from == ACL_TYPE_HSAIL_BINARY)
+ && (to != ACL_TYPE_CG && to != ACL_TYPE_ISA)) {
+ return ACL_INVALID_ARG;
+ }
+
+ if (from == ACL_TYPE_HSAIL_TEXT) {
+ amd::option::Options* Opts = reinterpret_cast(bin->options);
+ const char *kernel = Opts->oVariables->Kernel;
+ error_code = aclConvertType(cl, bin, kernel, from);
+ if (error_code != ACL_SUCCESS)
+ return error_code;
+ if (to == ACL_TYPE_CG)
+ return ACL_SUCCESS;
+ from = ACL_TYPE_CG;
+ }
+
bool stages[5] = {false};
uint8_t sectable[ACL_TYPE_LAST] =
- { 0, 0, 1, 1, 1, 1, 0, 6, 0, 4, 4, 4, 4, 0, 5, 0, 1 };
+ { 0, 0, 1, 1, 1, 1, 0, 6, 0, 3, 4, 4, 4, 0, 5, 0, 1 };
aclSections d_section[7] =
{ aclSOURCE, aclLLVMIR, aclSPIR, aclSOURCE, aclCODEGEN, aclTEXT, aclINTERNAL };
uint8_t start = sectable[from];
@@ -1411,6 +1442,14 @@ if_aclCompile(aclCompiler *cl,
else if (from == ACL_TYPE_RSLLVMIR_BINARY) {
data = cl->clAPI.extSec(cl, bin, &data_size, aclLLVMIR, &error_code);
}
+ else if (from == ACL_TYPE_HSAIL_BINARY) {
+ data = cl->clAPI.extSec(cl, bin, &data_size, aclSOURCE, &error_code);
+ // if for ACL_TYPE_HSAIL_BINARY stage BRIG (data) is not presented in aclSOURCE (.source) section of BIF,
+ // then it should be in multiple corresponding .brig_ sections in BIF, so continue to compile
+ if (error_code == ACL_ELF_ERROR) {
+ error_code = ACL_SUCCESS;
+ }
+ }
else {
data = cl->clAPI.extSec(cl, bin, &data_size, d_section[start], &error_code);
}
@@ -1799,11 +1838,75 @@ if_aclConvertType(aclCompiler *cl,
break;
}
case ACL_TYPE_HSAIL_TEXT:
+ {
to = ACL_TYPE_HSAIL_BINARY;
+ const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symHSAILText);
+ assert(symbol && "symbol not found");
+ std::string symbolName = symbol->str[PRE] + std::string("main") + symbol->str[POST];
+ from_data = cl->clAPI.extSym(cl, bin, &from_data_size,
+ symbol->sections[0],
+ symbolName.c_str(), &error_code);
+ // HSAIL was inserted into bif as section only without corresponding symbol
+ if (!from_data) {
+ from_data = cl->clAPI.extSec(cl, bin, &from_data_size,
+ symbol->sections[0], &error_code);
+ }
break;
+ }
case ACL_TYPE_HSAIL_BINARY:
- to = ACL_TYPE_HSAIL_TEXT;
+ {
+#if defined(WITH_TARGET_HSAIL)
+ // BRIG to HSAIL disassembling
+ if (isHSAILTarget(bin->target)) {
+ amdcl::HSAIL *acl = new amdcl::HSAIL(cl, bin, NULL);
+ if (acl == NULL) {
+ return ACL_OUT_OF_MEM;
+ }
+ std::string hsail = acl->disassembleBRIG();
+ // If HSAIL was not disassembled from multiple .brig_ sections in BIF, then:
+ // 1. try to extract BRIG from aclSOURCE section
+ if (hsail.empty()) {
+ from_data = cl->clAPI.extSec(cl, bin, &from_data_size, aclSOURCE, &error_code);
+ HSAIL_ASM::BrigContainer c;
+ // 2. load BRIG in BrigContainer
+ int result = HSAIL_ASM::BrigStreamer::load(c,
+ reinterpret_cast(from_data), from_data_size);
+ if (result != 0) {
+ error_code = ACL_INVALID_BINARY;
+ delete acl;
+ return error_code;
+ }
+ // 3. insert BRIG into multiple .brig_ sections in BIF +
+ // insert matadata symbols for every kernel
+ if (!acl->insertBRIG(c)) {
+ assert(!"Inserting BRIG failed\n");
+ error_code = ACL_INVALID_BINARY;
+ delete acl;
+ return error_code;
+ }
+ // 4. second attempt to disassemble BRIG
+ hsail = acl->disassembleBRIG();
+ }
+ delete acl;
+ if (hsail.empty()) {
+ return ACL_ELF_ERROR;
+ }
+ const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symHSAILText);
+ assert(symbol && "symbol not found");
+ std::string symbolName = symbol->str[PRE] + std::string("main") +
+ symbol->str[POST];
+ return cl->clAPI.insSym(cl, bin, hsail.data(), hsail.size(),
+ symbol->sections[0], symbolName.c_str());
+ } else {
+ assert(!"Unsupported architecture, expect hsail.");
+ return ACL_SYS_ERROR;
+ }
+#else
+ assert(!"Cannot go down this path without HSAIL support!");
+ return ACL_SYS_ERROR;
+#endif
break;
+ }
case ACL_TYPE_X86_TEXT:
to = ACL_TYPE_X86_BINARY;
break;
@@ -1922,6 +2025,32 @@ if_aclConvertType(aclCompiler *cl,
#else
assert(!"Cannot go down this path without AMDIL support!");
return ACL_SYS_ERROR;
+#endif
+ }
+ break;
+ case ACL_TYPE_HSAIL_BINARY:
+ {
+#if defined(WITH_TARGET_HSAIL)
+ if (isHSAILTarget(bin->target)) {
+ amdcl::HSAIL *acl = new amdcl::HSAIL(cl, bin, NULL);
+ if (acl == NULL) {
+ return ACL_OUT_OF_MEM;
+ }
+ // while assembling BRIG insertion into BIF (bin) performs,
+ // so no need in any symbol/section insertion here
+ bool bRet = acl->assemble(std::string(reinterpret_cast(from_data)));
+ delete acl;
+ if (!bRet) {
+ return ACL_CODEGEN_ERROR;
+ }
+ return ACL_SUCCESS;
+ } else {
+ assert(!"Unsupported architecture, expect hsail.");
+ return ACL_SYS_ERROR;
+ }
+#else
+ assert(!"Cannot go down this path without HSAIL support!");
+ return ACL_SYS_ERROR;
#endif
}
break;
@@ -1963,7 +2092,7 @@ if_aclDisassemble(aclCompiler *cl,
if (!hsail_be) {
goto internal_disasm_failure;
}
- hsail_be->disassembleBRIG(cl, bin);
+ hsail_be->disassembleBRIG();
}
}
#endif
diff --git a/rocclr/runtime/device/gpu/gpuprogram.cpp b/rocclr/runtime/device/gpu/gpuprogram.cpp
index 4995236b64..26ea61b683 100644
--- a/rocclr/runtime/device/gpu/gpuprogram.cpp
+++ b/rocclr/runtime/device/gpu/gpuprogram.cpp
@@ -1893,11 +1893,14 @@ HSAILProgram::linkImpl(
}
aclType
-HSAILProgram::getNextCompilationStageFromBinary()
+HSAILProgram::getNextCompilationStageFromBinary(std::vector& complete_stages)
{
acl_error errorCode;
size_t secSize = 0;
+ complete_stages.clear();
aclType from = ACL_TYPE_DEFAULT;
+ //@TODO_HSA: r=emankov: Should we also check here for
+ // ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT?
// Checking llvmir in .llvmir section
bool isLlvmirText = true;
@@ -1906,7 +1909,6 @@ HSAILProgram::getNextCompilationStageFromBinary()
if (errorCode != ACL_SUCCESS) {
isLlvmirText = false;
}
-
// Checking compile & link options in .comment section
bool isOpts = true;
const void* opts = aclExtractSection(dev().hsaCompiler(),
@@ -1914,22 +1916,10 @@ HSAILProgram::getNextCompilationStageFromBinary()
if (errorCode != ACL_SUCCESS) {
isOpts = false;
}
-
- if (isLlvmirText) {
+ if (isLlvmirText && isOpts) {
+ complete_stages.push_back(from);
from = ACL_TYPE_LLVMIR_BINARY;
}
- else {
- if (!isLlvmirText) {
- buildLog_ +="Error while linking : \
- Invalid binary (Missing LLVMIR section)\n" ;
- }
- if (!isOpts) {
- buildLog_ +="Warning while linking : \
- Invalid binary (Missing COMMENT section)\n" ;
- }
- return ACL_TYPE_DEFAULT;
- }
-
bool isHsailText = true;
// Checking HSAIL in .cg section
const void *hsailText = aclExtractSection(dev().hsaCompiler(),
@@ -1958,31 +1948,26 @@ HSAILProgram::getNextCompilationStageFromBinary()
if (errorCode != ACL_SUCCESS) {
isBrigOps = false;
}
-
- if (isHsailText && isBrigStrtab && isBrigCode && isBrigOps) {
+ if (isBrigStrtab && isBrigCode && isBrigOps) {
+ complete_stages.push_back(from);
from = ACL_TYPE_HSAIL_BINARY;
+ // Here we should check that CG stage was done.
+ // Right now there are 2 criterions to check it (besides BRIG itself):
+ // 1. matadata symbols symOpenclKernel for every kernel.
+ // 2. HSAIL text in aclCODEGEN section.
+ // Unfortunately there is no appropriate way in Compiler Lib to check 1.
+ // because kernel names are unknown here, therefore 2.
+
+ //@TODO_HSA: r=emankov: Change the HSAIL section check,
+ // when the solution with kernel names appears in Compiler Lib.
+ if (isHsailText) {
+ complete_stages.push_back(from);
+ from = ACL_TYPE_CG;
+ }
}
- else if (!isHsailText && !isBrigStrtab && !isBrigCode && !isBrigOps) {
- from = ACL_TYPE_LLVMIR_BINARY;
- }
- else {
- if (!isHsailText) {
- buildLog_ +="Error while linking : \
- Invalid binary (Missing CG section)\n" ;
- }
- if (!isBrigStrtab) {
- buildLog_ +="Error while linking : \
- Invalid binary (Missing BRIG_STRTAB section)\n" ;
- }
- if (!isBrigCode) {
- buildLog_ +="Error while linking : \
- Invalid binary (Missing BRIG_CODE section)\n" ;
- }
- if (!isBrigOps) {
- buildLog_ +="Error while linking : \
- Invalid binary (Missing BRIG_OPERANDS section)\n" ;
- }
- return ACL_TYPE_DEFAULT;
+ else if (isHsailText) {
+ complete_stages.push_back(from);
+ from = ACL_TYPE_HSAIL_TEXT;
}
// Checking ISA in .text section
bool isShaderIsa = true;
@@ -1992,8 +1977,12 @@ HSAILProgram::getNextCompilationStageFromBinary()
isShaderIsa = false;
}
if (isShaderIsa && from == ACL_TYPE_LLVMIR_BINARY) {
+ complete_stages.clear();
from = ACL_TYPE_DEFAULT;
}
+ if (complete_stages.empty()) {
+ complete_stages.push_back(from);
+ }
return from;
}
@@ -2002,64 +1991,80 @@ HSAILProgram::linkImpl(amd::option::Options* options)
{
acl_error errorCode;
aclType continueCompileFrom = ACL_TYPE_LLVMIR_BINARY;
- //If the binaryElf_ is not set then program must have been created
- // using clCreateProgramWithBinary
+ // If !binaryElf_ then program must have been created using clCreateProgramWithBinary
if (!binaryElf_) {
binary_t binary = this->binary();
+ // If the binary already exists
if ((binary.first != NULL) && (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(binary.first);
binaryElf_ = aclReadFromMem(mem, binary.second, &errorCode);
if (errorCode != ACL_SUCCESS) {
- buildLog_ += "Error while converting to BRIG: aclBinary init failure \n" ;
- LogWarning("aclBinaryInit failed");
+ buildLog_ += "Error while BRIG Codegen phase: aclReadFromMem failure \n" ;
+ LogWarning("aclReadFromMem failed");
return false;
}
- // Check that all needed section also exist in binaryElf_
+ // Calculate the next stage to compile from, based on sections in binaryElf_;
// No any validity checks here
- continueCompileFrom = getNextCompilationStageFromBinary();
+ std::vector complete_stages;
+ continueCompileFrom = getNextCompilationStageFromBinary(complete_stages);
+ //@TODO_HSA: r=emankov: Should we also check here for
+ // ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT to recompile from?
if (ACL_TYPE_DEFAULT == continueCompileFrom) {
+ buildLog_ += "Error while BRIG Codegen phase: the binary is incomplete \n" ;
return false;
}
if (ACL_TYPE_HSAIL_BINARY == continueCompileFrom) {
- // Save binary in the interface class
- // Also load compile & link options from binary into Program class members:
- // compileOptions_ & linkOptions_
+ // Saving binary in the interface class,
+ // which also load compile & link options from binary
setBinary(static_cast(mem), binary.second);
- // Compare options loaded from binary with current ones
- // If they differ then recompile from ACL_TYPE_LLVMIR_BINARY
- // @TODO It is needed to compare options taking into account that:
- // 1. options are order independent;
- // 2. (may be not trivial) compare only options that affect binary
- std::string curOptions = options->origOptionStr + hsailOptions();
- if (compileOptions_ + linkOptions_ != curOptions) {
- continueCompileFrom = ACL_TYPE_LLVMIR_BINARY;
+ // Check the previous completed stage
+ if (ACL_TYPE_LLVMIR_BINARY == complete_stages.back()) {
+ // Compare options loaded from binary with current ones
+ // If they differ then recompile from ACL_TYPE_LLVMIR_BINARY
+ //@TODO_HSA: r=emankov: Should we need to check options at all?
+ std::string curOptions = options->origOptionStr + hsailOptions();
+ if (compileOptions_ + linkOptions_ != curOptions) {
+ continueCompileFrom = ACL_TYPE_LLVMIR_BINARY;
+ }
}
}
}
}
-
- // Compilation from ACL_TYPE_LLVMIR_BINARY to ACL_TYPE_CG in cases:
- // 1. if the program is not created with binary;
- // 2. if the program is created with binary and contains only .llvmir & .comment
- // 3. if the program is created with binary, contains all brig sections,
- // but the binary's compile & link options differ from current ones (recompilation);
- if (ACL_TYPE_LLVMIR_BINARY == continueCompileFrom) {
- std::string curOptions = options->origOptionStr + hsailOptions();
- errorCode = aclCompile(dev().hsaCompiler(), binaryElf_,
- curOptions.c_str(), ACL_TYPE_LLVMIR_BINARY, ACL_TYPE_CG, NULL);
+ switch (continueCompileFrom) {
+ default:
+ break;
+ // Compilation from ACL_TYPE_LLVMIR_BINARY to ACL_TYPE_CG in cases:
+ // 1. if the program is not created with binary;
+ // 2. if the program is created with binary and contains only .llvmir & .comment
+ // 3. if the program is created with binary, contains .llvmir, .comment, brig sections,
+ // but the binary's compile & link options differ from current ones (recompilation);
+ case ACL_TYPE_LLVMIR_BINARY:
+ // Compilation from ACL_TYPE_HSAIL_BINARY to ACL_TYPE_CG in cases:
+ // 1. if the program is created with binary and contains only brig sections
+ case ACL_TYPE_HSAIL_BINARY:
+ // Compilation from ACL_TYPE_HSAIL_TEXT to ACL_TYPE_CG in cases:
+ // 1. if the program is created with binary and contains only hsail text
+ case ACL_TYPE_HSAIL_TEXT:
+ {
+ std::string curOptions = options->origOptionStr + hsailOptions();
+ errorCode = aclCompile(dev().hsaCompiler(), binaryElf_,
+ curOptions.c_str(), continueCompileFrom, ACL_TYPE_CG, NULL);
+ break;
+ }
}
if (errorCode != ACL_SUCCESS) {
- buildLog_ += "Error while converting to BRIG: Compiling LLVMIR to BRIG \n" ;
+ buildLog_ += "Error while BRIG Codegen phase: compilation error \n" ;
return false;
}
+ if (!aclHsaLoader(dev().hsaCompiler(), binaryElf_, this, &AllocateGPUMemory,
+ &DmaMemoryCopy, &GetSamplerObjectParams, &InitializeSamplerObject)) {
+ buildLog_ += "Error while BRIG Codegen phase: loading BRIG globals in the ELF \n";
+ return false;
+ }
+ // We need to pull out kernels' names for finalizing kernels
+ //@TODO_HSA: r=emankov: rewrite the below code,
+ // if another way to obtain kernel names appears in the compiler library
size_t fsailSize;
const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symHSAILText);
assert(symbol && "symbol not found");
@@ -2071,20 +2076,11 @@ HSAILProgram::linkImpl(amd::option::Options* options)
symName.c_str(),
&errorCode);
if (errorCode != ACL_SUCCESS) {
- buildLog_ += "Error while reading out the HSAIL from the ELF" ;
+ buildLog_ += "Error while reading out the HSAIL from the ELF \n" ;
return false;
}
-
- if (!aclHsaLoader(dev().hsaCompiler(), binaryElf_, this, &AllocateGPUMemory,
- &DmaMemoryCopy, &GetSamplerObjectParams, &InitializeSamplerObject)) {
- buildLog_ += "Error while loading BRIG globals in the ELF";
- return false;
- }
-
std::string hsailProgram((char *)hsailText);
HSAILProgram_ = hsailProgram;
- // We pull out all the kernel names in a very ugly manner
- //! \todo check if this has been fixed in the compiler library
if (!HSAILProgram_.empty()) {
bool dynamicParallelism = false;
// Find out the name of the kernel. Works for multiple kernels
diff --git a/rocclr/runtime/device/gpu/gpuprogram.hpp b/rocclr/runtime/device/gpu/gpuprogram.hpp
index 9b6e0a8d6c..6cc151b353 100644
--- a/rocclr/runtime/device/gpu/gpuprogram.hpp
+++ b/rocclr/runtime/device/gpu/gpuprogram.hpp
@@ -419,7 +419,10 @@ protected:
amd::option::Options* options //!< compile options's object
);
- aclType getNextCompilationStageFromBinary();
+ /* \brief Return the next stage to compile from, based on sections in binary,
+ * also return completed stages in vector, which contains at least ACL_TYPE_DEFAULT
+ */
+ aclType getNextCompilationStageFromBinary(std::vector& complete_stages);
/*! \brief Compiles LLVM binary to FSAIL code (compiler backend: link+opt+codegen)
*