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
このコミットが含まれているのは:
foreman
2014-08-15 08:23:45 -04:00
コミット c2967ef855
3個のファイルの変更230行の追加102行の削除
+146 -17
ファイルの表示
@@ -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<amd::option::Options*>(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<amdcl::HSAIL*>(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<amd::option::Options*>(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<const char*>(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<const char*>(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
+80 -84
ファイルの表示
@@ -1893,11 +1893,14 @@ HSAILProgram::linkImpl(
}
aclType
HSAILProgram::getNextCompilationStageFromBinary()
HSAILProgram::getNextCompilationStageFromBinary(std::vector<aclType>& 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<void *>(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<aclType> 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<char*>(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
+4 -1
ファイルの表示
@@ -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<aclType>& complete_stages);
/*! \brief Compiles LLVM binary to FSAIL code (compiler backend: link+opt+codegen)
*