Files
rocm-systems/rocclr/runtime/device/gpu/gpucompiler.cpp
T
foreman 14179df14f P4 to Git Change 1228972 by smekhano@stas-nova-hsa on 2016/01/19 14:21:26
SWDEV-85602 - rename hsail-64 arch to hsail64
	This is to match other existing llvm targets, such as spir64 and amdil64, as well as to match behavior of open source HSAIL BE.
	For legacy users there is alias "-hsail-64" provided in the aoc2 only.

	Testing: smoke, precheckin
	Reviewed by Matthew Arsenault, Evgeny Mankov and Nikolay Haustov

Affected files ...

... //depot/stg/opencl/drivers/opencl/compiler/legacy-lib/backends/common/codegen.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/compiler/legacy-lib/backends/common/frontend.cpp#4 edit
... //depot/stg/opencl/drivers/opencl/compiler/legacy-lib/utils/v0_8/target_mappings.h#5 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/codegen.cpp#66 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/frontend.cpp#37 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/utils/v0_8/target_mappings.h#37 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/Target/HSAIL/HSAILTargetMachine.cpp#53 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/Target/HSAIL/TargetInfo/HSAILTargetInfo.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/tools/aacl/aa.h#2 edit
... //depot/stg/opencl/drivers/opencl/compiler/tools/aoc2/aoc2.cpp#80 edit
... //depot/stg/opencl/drivers/opencl/library/hsa/amp_libm/build/Makefile.amp_libm#4 edit
... //depot/stg/opencl/drivers/opencl/library/hsa/gcn/build/Makefile.gcn#20 edit
... //depot/stg/opencl/drivers/opencl/library/hsa/gcndev/build/Makefile.gcndev#3 edit
... //depot/stg/opencl/drivers/opencl/library/hsa/hsail/build/Makefile.hsail#44 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucompiler.cpp#153 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#222 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/hsa_foundation/hsacompiler.cpp#5 edit
... //depot/stg/opencl/drivers/opencl/tests/hsa/bin/test_driver.pl#25 edit
... //depot/stg/opencl/drivers/opencl/tests/hsa/tlst/complib.tlst#21 edit
... //depot/stg/opencl/drivers/opencl/tests/hsa/tlst/ocl_debug.tlst#9 edit
... //depot/stg/opencl/drivers/opencl/tests/hsa/tlst/ocl_regression.tlst#25 edit
... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/spir/SPIRBase.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/spir/SPIRVBasic.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/tests/ocltst/module/spir/SPIRVDropIn.cpp#5 edit
2016-01-19 14:31:59 -05:00

463 строки
15 KiB
C++

//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include "os/os.hpp"
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpuprogram.hpp"
#include "device/gpu/gpukernel.hpp"
#include "utils/options.hpp"
#include <cstdio>
//CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);
namespace gpu {
static int programsCount = 0;
bool
NullProgram::compileImpl(const std::string& src,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options)
{
std::string sourceCode = src;
if (dev().settings().debugFlags_ & Settings::CheckForILSource) {
size_t inc = sourceCode.find("il_cs_", 0);
if (inc != std::string::npos) {
// CL program is an IL program
ilProgram_ = sourceCode;
return true;
}
}
std::string tempFolder = amd::Os::getTempPath();
std::string tempFileName = amd::Os::getTempFileName();
if (dev().settings().debugFlags_ & Settings::StubCLPrograms) {
std::stringstream fileName;
std::fstream stubRead;
// Dump the IL function
fileName << "program_" << programsCount++ << ".cl";
stubRead.open(fileName.str().c_str(), (std::fstream::in | std::fstream::binary));
// Check if we have OpenCL program
if (stubRead.is_open()) {
// Find the stream size
stubRead.seekg(0, std::fstream::end);
size_t size = stubRead.tellg();
stubRead.seekg(0, std::ios::beg);
char* data = new char[size];
stubRead.read(data, size);
stubRead.close();
sourceCode.assign(data, size);
delete[] data;
}
else {
std::fstream stubWrite;
stubWrite.open(fileName.str().c_str(),
(std::fstream::out | std::fstream::binary));
stubWrite << sourceCode;
stubWrite.close();
}
}
std::fstream f;
std::vector<std::string> headerFileNames(headers.size());
std::vector<std::string> newDirs;
for (size_t i = 0; i < headers.size(); ++i) {
std::string headerPath = tempFolder;
std::string headerIncludeName(headerIncludeNames[i]);
// replace / in path with current os's file separator
if ( amd::Os::fileSeparator() != '/') {
for (std::string::iterator it = headerIncludeName.begin(),
end = headerIncludeName.end();
it != end;
++it) {
if (*it == '/') *it = amd::Os::fileSeparator();
}
}
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
if (pos != std::string::npos) {
headerPath += amd::Os::fileSeparator();
headerPath += headerIncludeName.substr(0, pos);
headerIncludeName = headerIncludeName.substr(pos+1);
}
if (!amd::Os::pathExists(headerPath)) {
bool ret = amd::Os::createPath(headerPath);
assert(ret && "failed creating path!");
newDirs.push_back(headerPath);
}
std::string headerFullName
= headerPath + amd::Os::fileSeparator() + headerIncludeName;
headerFileNames[i] = headerFullName;
f.open(headerFullName.c_str(), std::fstream::out);
assert(!f.fail() && "failed creating header file!");
f.write(headers[i]->c_str(), headers[i]->length());
f.close();
}
acl_error err;
const aclTargetInfo& targInfo = info();
aclBinaryOptions binOpts = {0};
binOpts.struct_size = sizeof(binOpts);
binOpts.elfclass = targInfo.arch_id == aclAMDIL64 ? ELFCLASS64 : ELFCLASS32;
binOpts.bitness = ELFDATA2LSB;
binOpts.alloc = &::malloc;
binOpts.dealloc = &::free;
aclBinary* bin
= aclBinaryInit(sizeof(aclBinary), &targInfo, &binOpts, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclBinaryInit failed");
return false;
}
if (ACL_SUCCESS != aclInsertSection(dev().compiler(), bin,
sourceCode.c_str(), sourceCode.size(), aclSOURCE)) {
LogWarning("aclInsertSection failed");
aclBinaryFini(bin);
return false;
}
// temporary solution to synchronize buildNo between runtime and complib
// until we move runtime inside complib
((amd::option::Options*)bin->options)->setBuildNo(options->getBuildNo());
std::stringstream opts;
std::string token;
opts << options->origOptionStr.c_str();
if (options->origOptionStr.find("-cl-std=CL") == std::string::npos) {
switch(dev().settings().oclVersion_) {
case OpenCL10: opts << " -cl-std=CL1.0"; break;
case OpenCL11: opts << " -cl-std=CL1.1"; break;
case OpenCL20: default:
case OpenCL12: opts << " -cl-std=CL1.2"; break;
}
}
// FIXME: Should we prefix everything with -Wf,?
std::istringstream iss(options->clcOptions);
while (getline(iss, token, ' ')) {
if (!token.empty()) {
// Check if this is a -D option
if (token.compare("-D") == 0) {
// It is, skip payload
getline(iss, token, ' ');
continue;
}
opts << " -Wf," << token;
}
}
if (!headers.empty()) {
opts << " -I" << tempFolder;
}
if (!dev().settings().imageSupport_) {
opts << " -fno-image-support";
}
if (dev().settings().reportFMAF_) {
opts << " -mfast-fmaf";
}
if (dev().settings().reportFMA_) {
opts << " -mfast-fma";
}
iss.clear();
iss.str(device().info().extensions_);
while (getline(iss, token, ' ')) {
if (!token.empty()) {
opts << " -D" << token << "=1";
}
}
std::string newOpt = opts.str();
size_t pos = newOpt.find("-fno-bin-llvmir");
while (pos != std::string::npos) {
newOpt.erase(pos, 15);
pos = newOpt.find("-fno-bin-llvmir");
}
err = aclCompile(dev().compiler(), bin, newOpt.c_str(),
ACL_TYPE_OPENCL, ACL_TYPE_LLVMIR_BINARY, NULL);
buildLog_ += aclGetCompilerLog(dev().compiler());
if (err != ACL_SUCCESS) {
LogWarning("aclCompile failed");
aclBinaryFini(bin);
return false;
}
size_t len = 0;
const void* ir = aclExtractSection(dev().compiler(), bin,
&len, aclLLVMIR, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclExtractSection failed");
aclBinaryFini(bin);
return false;
}
llvmBinary_.assign(reinterpret_cast<const char*>(ir), len);
elfSectionType_ = amd::OclElf::LLVMIR;
aclBinaryFini(bin);
for (size_t i = 0; i < headerFileNames.size(); ++i) {
amd::Os::unlink(headerFileNames[i].c_str());
}
for (size_t i = 0; i < newDirs.size(); ++i) {
amd::Os::removePath(newDirs[i]);
}
#ifdef _WIN32
amd::Os::unlink(tempFileName);
#endif
if (clBinary()->saveSOURCE()) {
clBinary()->elfOut()->addSection(
amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
}
if (clBinary()->saveLLVMIR()) {
clBinary()->elfOut()->addSection(
amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false);
// store the original compile options
clBinary()->storeCompileOptions(compileOptions_);
}
return true;
}
int
NullProgram::compileBinaryToIL(amd::option::Options* options)
{
acl_error err;
const aclTargetInfo& targInfo = info();
aclBinaryOptions binOpts = {0};
binOpts.struct_size = sizeof(binOpts);
binOpts.elfclass = targInfo.arch_id == aclAMDIL64 ? ELFCLASS64 : ELFCLASS32;
binOpts.bitness = ELFDATA2LSB;
binOpts.alloc = &::malloc;
binOpts.dealloc = &::free;
aclBinary* bin
= aclBinaryInit(sizeof(aclBinary), &targInfo, &binOpts, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclBinaryInit failed");
return CL_BUILD_PROGRAM_FAILURE;
}
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)) {
LogWarning("aclInsertSection failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
// pass kernel argument alignment info to compiler lib through option str
std::string optionStr = options->origOptionStr;
if (options->origOptionStr.find("kernel-arg-alignment")
== std::string::npos) {
char s[256];
sprintf(s, " -Wb,-kernel-arg-alignment=%d",
dev().info().memBaseAddrAlign_ / 8);
optionStr += s;
}
// temporary solution to synchronize buildNo between runtime and complib
// until we move runtime inside complib
((amd::option::Options*)bin->options)->setBuildNo(options->getBuildNo());
aclType type = ACL_TYPE_CG ;
// If option bin-bif30 is set, generate BIF 3.0 binary
if (options->oVariables->BinBIF30) {
type = ACL_TYPE_ISA;
}
err = aclCompile(dev().compiler(), bin, optionStr.c_str(),
aclTypeBinaryUsed, type, NULL);
buildLog_ += aclGetCompilerLog(dev().compiler());
if (err != ACL_SUCCESS) {
LogWarning("aclCompile failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
if (options->oVariables->BinBIF30) {
if (!createBIFBinary(bin)) {
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
}
size_t len = 0;
const void* amdil = aclExtractSection(dev().compiler(), bin,
&len, aclCODEGEN, &err);
if (err != ACL_SUCCESS) {
LogWarning("aclExtractSection failed");
aclBinaryFini(bin);
return CL_BUILD_PROGRAM_FAILURE;
}
ilProgram_.assign(reinterpret_cast<const char*>(amdil), len);
aclBinaryFini(bin);
return CL_SUCCESS;
}
bool
HSAILProgram::compileImpl(
const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options)
{
acl_error errorCode;
aclTargetInfo target;
std::string arch = "hsail";
if (dev().settings().use64BitPtr_) {
arch += "64";
}
target = aclGetTargetInfo(arch.c_str(),
dev().info().name_, &errorCode);
// end if asic info is ready
// We dump the source code for each program (param: headers)
// into their filenames (headerIncludeNames) into the TEMP
// folder specific to the OS and add the include path while
// compiling
// Find the temp folder for the OS
std::string tempFolder = amd::Os::getTempPath();
std::string tempFileName = amd::Os::getTempFileName();
// Iterate through each source code and dump it into tmp
std::fstream f;
std::vector<std::string> headerFileNames(headers.size());
std::vector<std::string> newDirs;
for (size_t i = 0; i < headers.size(); ++i) {
std::string headerPath = tempFolder;
std::string headerIncludeName(headerIncludeNames[i]);
// replace / in path with current os's file separator
if (amd::Os::fileSeparator() != '/') {
for (std::string::iterator it = headerIncludeName.begin(),
end = headerIncludeName.end(); it != end; ++it) {
if (*it == '/') *it = amd::Os::fileSeparator();
}
}
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
if (pos != std::string::npos) {
headerPath += amd::Os::fileSeparator();
headerPath += headerIncludeName.substr(0, pos);
headerIncludeName = headerIncludeName.substr(pos+1);
}
if (!amd::Os::pathExists(headerPath)) {
bool ret = amd::Os::createPath(headerPath);
assert(ret && "failed creating path!");
newDirs.push_back(headerPath);
}
std::string headerFullName =
headerPath + amd::Os::fileSeparator() + headerIncludeName;
headerFileNames[i] = headerFullName;
f.open(headerFullName.c_str(), std::fstream::out);
// Should we allow asserts
assert(!f.fail() && "failed creating header file!");
f.write(headers[i]->c_str(), headers[i]->length());
f.close();
}
// Create Binary
binaryElf_ = aclBinaryInit(sizeof(aclBinary),
&target, &binOpts_, &errorCode);
if (errorCode != ACL_SUCCESS) {
buildLog_ += "Error: aclBinary init failure\n";
LogWarning("aclBinaryInit failed");
return false;
}
// Insert opencl into binary
errorCode = aclInsertSection(dev().hsaCompiler(), binaryElf_,
sourceCode.c_str(), strlen(sourceCode.c_str()), aclSOURCE);
if (errorCode != ACL_SUCCESS) {
buildLog_ += "Error: Inserting openCl Source to binary\n";
}
// Set the options for the compiler
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
compileOptions_.append(" -I");
compileOptions_.append(tempFolder);
}
//Add only for CL2.0 and above
if (options->oVariables->CLStd[2] >= '2') {
std::stringstream opts;
opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
<< device().info().maxGlobalVariableSize_;
compileOptions_.append(opts.str());
}
#if !defined(_LP64) && defined(ATI_OS_LINUX)
if (options->origOptionStr.find("-cl-std=CL2.0") != std::string::npos && !dev().settings().force32BitOcl20_) {
errorCode = ACL_UNSUPPORTED;
LogWarning("aclCompile failed");
return false;
}
#endif
// Compile source to IR
compileOptions_.append(hsailOptions());
errorCode = aclCompile(dev().hsaCompiler(), binaryElf_, compileOptions_.c_str(),
ACL_TYPE_OPENCL, ACL_TYPE_LLVMIR_BINARY, NULL);
buildLog_ += aclGetCompilerLog(dev().hsaCompiler());
if (errorCode != ACL_SUCCESS) {
LogWarning("aclCompile failed");
buildLog_ += "Error: Compiling CL to IR\n";
return false;
}
clBinary()->storeCompileOptions(compileOptions_);
// Save the binary in the interface class
size_t size = 0;
void* mem = NULL;
aclWriteToMem(binaryElf_, &mem, &size);
setBinary(static_cast<char*>(mem), size);
// Save the binary inside the program
// The FSAILProgram will be responsible to free it during destruction
rawBinary_ = mem;
return true;
}
} // namespace gpu