P4 to Git Change 1608319 by gandryey@gera-lnx-rcf-lc on 2018/09/19 16:55:11

SWDEV-79445 - OCL generic changes and code clean-up
	Program compilation clean-up. Step#2:
	- Combine PAL and ROCr implementations of compilation under common methods in device::Program for HSAIL and LC.

Affected files ...

... //depot/stg/opencl/drivers/opencl/runtime/device/device.hpp#319 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.hpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.hpp#74 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palcompiler.cpp#26 delete
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldevice.hpp#34 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.cpp#73 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.hpp#30 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompiler.cpp#46 delete
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.hpp#31 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#87 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.hpp#36 edit
Bu işleme şunda yer alıyor:
foreman
2018-09-19 17:06:20 -04:00
ebeveyn 8f2b512149
işleme e132af9cad
12 değiştirilmiş dosya ile 504 ekleme ve 872 silme
+9
Dosyayı Görüntüle
@@ -68,6 +68,7 @@ class SvmUnmapMemoryCommand;
class TransferBufferFileCommand;
class HwDebugManager;
class Device;
class CacheCompilation;
struct KernelParameterDescriptor;
struct Coord3D;
@@ -1300,6 +1301,10 @@ class Device : public RuntimeObject {
// P2P devices that are accessible from the current device
std::vector<cl_device_id> p2pDevices_;
#if defined(WITH_LIGHTNING_COMPILER)
amd::CacheCompilation* cacheCompilation() const { return cacheCompilation_.get(); }
#endif
protected:
//! Enable the specified extension
char* getExtensionString();
@@ -1310,6 +1315,10 @@ class Device : public RuntimeObject {
BlitProgram* blitProgram_; //!< Blit program info
static AppProfile appProfile_; //!< application profile
HwDebugManager* hwDebugMgr_; //!< Hardware Debug manager
#if defined(WITH_LIGHTNING_COMPILER)
//! Compilation with cache support
std::unique_ptr<amd::CacheCompilation> cacheCompilation_;
#endif
private:
bool IsTypeMatching(cl_device_type type, bool offlineDevices);
+416 -2
Dosyayı Görüntüle
@@ -11,11 +11,25 @@
#include "utils/bif_section_labels.hpp"
#include "utils/libUtils.h"
#include "spirv/spirvUtils.h"
#if defined(WITH_LIGHTNING_COMPILER)
#include "driver/AmdCompiler.h"
#include "opencl1.2-c.amdgcn.inc"
#include "opencl2.0-c.amdgcn.inc"
#endif // !defined(WITH_LIGHTNING_COMPILER)
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
#include <cstdio>
#if defined(ATI_OS_LINUX)
#include <dlfcn.h>
#include <libgen.h>
#endif // defined(ATI_OS_LINUX)
#include "spirv/spirvUtils.h"
#include "acl.h"
#if defined(WITH_LIGHTNING_COMPILER)
@@ -40,6 +54,7 @@ Program::Program(amd::Device& device)
lastBuildOptionsArg_(),
buildStatus_(CL_BUILD_NONE),
buildError_(CL_SUCCESS),
machineTarget_(nullptr),
globalVariableTotalSize_(0),
programOptions_(nullptr)
{
@@ -63,6 +78,405 @@ void Program::clear() {
kernels_.clear();
}
// ================================================================================================
bool Program::compileImpl(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
if (isLC()) {
return compileImplLC(sourceCode, headers, headerIncludeNames, options);
} else {
return compileImplHSAIL(sourceCode, headers, headerIncludeNames, options);
}
}
// ================================================================================================
#if defined(WITH_LIGHTNING_COMPILER)
static std::string llvmBin_(amd::Os::getEnvironment("LLVM_BIN"));
#if defined(ATI_OS_WIN)
static BOOL CALLBACK checkLLVM_BIN(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* lpContex) {
if (llvmBin_.empty()) {
HMODULE hm = nullptr;
if (GetModuleHandleExA(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&amd::Device::init, &hm)) {
char path[1024];
GetModuleFileNameA(hm, path, sizeof(path));
llvmBin_ = path;
size_t pos = llvmBin_.rfind('\\');
if (pos != std::string::npos) {
llvmBin_.resize(pos);
}
}
}
return TRUE;
}
#endif // defined (ATI_OS_WINDOWS)
#if defined(ATI_OS_LINUX)
static pthread_once_t once = PTHREAD_ONCE_INIT;
static void checkLLVM_BIN() {
if (llvmBin_.empty()) {
Dl_info info;
if (dladdr((const void*)&amd::Device::init, &info)) {
char* str = strdup(info.dli_fname);
if (str) {
llvmBin_ = dirname(str);
free(str);
size_t pos = llvmBin_.rfind("lib");
if (pos != std::string::npos) {
llvmBin_.replace(pos, 3, "bin");
}
}
}
}
#if defined(DEBUG)
static const std::string tools[] = { "clang", "llvm-link", "ld.lld" };
for (const std::string tool : tools) {
std::string exePath(llvmBin_ + "/" + tool);
struct stat buf;
if (stat(exePath.c_str(), &buf)) {
std::string msg(exePath + " not found");
LogWarning(msg.c_str());
}
else if ((buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
std::string msg("Cannot execute " + exePath);
LogWarning(msg.c_str());
}
}
#endif // defined(DEBUG)
}
#endif // defined(ATI_OS_LINUX)
std::unique_ptr<amd::opencl_driver::Compiler> Program::newCompilerInstance() {
#if defined(ATI_OS_WIN)
static INIT_ONCE initOnce;
InitOnceExecuteOnce(&initOnce, checkLLVM_BIN, nullptr, nullptr);
#endif // defined(ATI_OS_WIN)
#if defined(ATI_OS_LINUX)
pthread_once(&once, checkLLVM_BIN);
#endif // defined(ATI_OS_LINUX)
#if defined(DEBUG)
std::string clangExe(llvmBin_ + LINUX_SWITCH("/clang", "\\clang.exe"));
struct stat buf;
if (stat(clangExe.c_str(), &buf)) {
std::string msg("Could not find the Clang binary in " + llvmBin_);
LogWarning(msg.c_str());
}
#endif // defined(DEBUG)
return std::unique_ptr<amd::opencl_driver::Compiler>(
amd::opencl_driver::CompilerFactory().CreateAMDGPUCompiler(llvmBin_));
}
#endif // defined(WITH_LIGHTNING_COMPILER)
// ================================================================================================
bool Program::compileImplLC(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
#if defined(WITH_LIGHTNING_COMPILER)
const char* xLang = options->oVariables->XLang;
if (xLang != nullptr) {
if (strcmp(xLang, "asm") == 0) {
clBinary()->elfOut()->addSection(amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
return true;
}
else if (!strcmp(xLang, "cl")) {
buildLog_ += "Unsupported language: \"" + std::string(xLang) + "\".\n";
return false;
}
}
using namespace amd::opencl_driver;
std::unique_ptr<Compiler> C(newCompilerInstance());
std::vector<Data*> inputs;
Data* input = C->NewBufferReference(DT_CL, sourceCode.c_str(), sourceCode.length());
if (input == nullptr) {
buildLog_ += "Error while creating data from source code";
return false;
}
inputs.push_back(input);
amd::opencl_driver::Buffer* output = C->NewBuffer(DT_LLVM_BC);
if (output == nullptr) {
buildLog_ += "Error while creating buffer for the LLVM bitcode";
return false;
}
// Set the options for the compiler
// Some options are set in Clang AMDGPUToolChain (like -m64)
std::ostringstream ostrstr;
std::copy(options->clangOptions.begin(), options->clangOptions.end(),
std::ostream_iterator<std::string>(ostrstr, " "));
std::string driverOptions(ostrstr.str());
// Setting the language
driverOptions.append(" -cl-std=").append(options->oVariables->CLStd);
// Set the -O#
std::ostringstream optLevel;
optLevel << " -O" << options->oVariables->OptLevel;
driverOptions.append(optLevel.str());
// Set the machine target
driverOptions.append(" -mcpu=");
driverOptions.append(machineTarget_);
// Set xnack option if needed
if (xnackEnabled_) {
driverOptions.append(" -mxnack");
}
driverOptions.append(options->llvmOptions);
driverOptions.append(ProcessOptions(options));
// Set whole program mode
driverOptions.append(" -mllvm -amdgpu-early-inline-all -mllvm -amdgpu-prelink");
// Find the temp folder for the OS
std::string tempFolder = amd::Os::getTempPath();
// 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 (auto& it : headerIncludeName) {
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();
Data* inc = C->NewFileReference(DT_CL_HEADER, headerFileNames[i]);
if (inc == nullptr) {
buildLog_ += "Error while creating data from headers";
return false;
}
inputs.push_back(inc);
}
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
driverOptions.append(" -I");
driverOptions.append(tempFolder);
}
if (options->isDumpFlagSet(amd::option::DUMP_CL)) {
std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc);
if (f.is_open()) {
f << "/* Compiler options:\n"
"-c -emit-llvm -target amdgcn-amd-amdhsa -x cl "
<< driverOptions << " -include opencl-c.h "
<< "\n*/\n\n"
<< sourceCode;
f.close();
}
else {
buildLog_ += "Warning: opening the file to dump the OpenCL source failed.\n";
}
}
// FIXME_lmoriche: has the CL option been validated?
uint clcStd =
(options->oVariables->CLStd[2] - '0') * 100 + (options->oVariables->CLStd[4] - '0') * 10;
std::pair<const void*, size_t> hdr;
switch (clcStd) {
case 100:
case 110:
case 120:
hdr = { opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size };
break;
case 200:
hdr = { opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size };
break;
default:
buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
return false;
}
File* pch = C->NewTempFile(DT_CL_HEADER);
if (pch == nullptr || !pch->WriteData((const char*)hdr.first, hdr.second)) {
buildLog_ += "Error while opening the opencl-c header ";
return false;
}
driverOptions.append(" -include-pch " + pch->Name());
driverOptions.append(" -Xclang -fno-validate-pch");
// Tokenize the options string into a vector of strings
std::istringstream istrstr(driverOptions);
std::istream_iterator<std::string> sit(istrstr), end;
std::vector<std::string> params(sit, end);
// Compile source to IR
bool ret =
device().cacheCompilation()->compileToLLVMBitcode(C.get(), inputs, output, params, buildLog_);
buildLog_ += C->Output();
if (!ret) {
buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n";
return false;
}
llvmBinary_.assign(output->Buf().data(), output->Size());
elfSectionType_ = amd::OclElf::LLVMIR;
if (options->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
std::ofstream f(options->getDumpFileName("_original.bc").c_str(),
std::ios::binary | std::ios::trunc);
if (f.is_open()) {
f.write(llvmBinary_.data(), llvmBinary_.size());
f.close();
}
else {
buildLog_ += "Warning: opening the file to dump the compiled IR failed.\n";
}
}
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_);
}
#endif // defined(WITH_LIGHTNING_COMPILER)
return true;
}
// ================================================================================================
static void logFunction(const char* msg, size_t size) {
std::cout << "Compiler Log: " << msg << std::endl;
}
// ================================================================================================
bool Program::compileImplHSAIL(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
#if defined(WITH_COMPILER_LIB) || !defined(WITH_LIGHTNING_COMPILER)
acl_error errorCode;
aclTargetInfo target;
std::string arch = LP64_SWITCH("hsail", "hsail64");
target = aclGetTargetInfo(arch.c_str(), machineTarget_, &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();
// Iterate through each source code and dump it into tmp
std::fstream f;
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 (auto& it : headerIncludeName) {
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;
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(device().compiler(), 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);
}
#if !defined(_LP64) && defined(ATI_OS_LINUX)
if (options->origOptionStr.find("-cl-std=CL2.0") != std::string::npos) {
errorCode = ACL_UNSUPPORTED;
LogWarning("aclCompile failed");
return false;
}
#endif
// Compile source to IR
compileOptions_.append(ProcessOptions(options));
errorCode = aclCompile(device().compiler(), binaryElf_, compileOptions_.c_str(), ACL_TYPE_OPENCL,
ACL_TYPE_LLVMIR_BINARY, nullptr /* logFunction */);
buildLog_ += aclGetCompilerLog(device().compiler());
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
saveBinaryAndSetType(TYPE_COMPILED);
#endif // defined(WITH_COMPILER_LIB) || !defined(WITH_LIGHTNING_COMPILER)
return true;
}
// ================================================================================================
bool Program::initClBinary() {
if (clBinary_ == nullptr) {
+44 -13
Dosyayı Görüntüle
@@ -10,13 +10,20 @@
#include "devwavelimiter.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "driver/AmdCompiler.h"
//#include "llvm/Support/AMDGPUMetadata.h"
namespace llvm {
namespace AMDGPU {
namespace HSAMD {
namespace Kernel {
struct Metadata;
}}}}
//typedef llvm::AMDGPU::HSAMD::Metadata CodeObjectMD;
typedef llvm::AMDGPU::HSAMD::Kernel::Metadata KernelMD;
//typedef llvm::AMDGPU::HSAMD::Kernel::Arg::Metadata KernelArgMD;
#endif // defined(WITH_LIGHTNING_COMPILER)
namespace amd {
@@ -64,9 +71,8 @@ class Program : public amd::HeapObject {
//! The device target for this binary.
amd::SharedReference<amd::Device> device_;
kernels_t kernels_; //!< The kernel entry points this binary.
type_t type_; //!< type of this program
kernels_t kernels_; //!< The kernel entry points this binary.
type_t type_; //!< type of this program
protected:
union {
@@ -75,6 +81,7 @@ class Program : public amd::HeapObject {
uint32_t internal_ : 1; //!< Internal blit program
uint32_t isLC_ : 1; //!< LC was used for the program compilation
uint32_t hasGlobalStores_ : 1; //!< Program has writable program scope variables
uint32_t xnackEnabled_ : 1; //!< Xnack was enabled during compilation
};
uint32_t flags_; //!< Program flags
};
@@ -86,15 +93,16 @@ class Program : public amd::HeapObject {
std::string linkOptions_; //!< link options.
//!< the option arg passed in to clCompileProgram(), clLinkProgram(),
//! or clBuildProgram(), whichever is called last
aclBinaryOptions binOpts_; //!< Binary options to create aclBinary
aclBinary* binaryElf_; //!< Binary for the new compiler library
aclBinaryOptions binOpts_; //!< Binary options to create aclBinary
aclBinary* binaryElf_; //!< Binary for the new compiler library
std::string lastBuildOptionsArg_;
std::string buildLog_; //!< build log.
cl_int buildStatus_; //!< build status.
cl_int buildError_; //!< build error
//! The info target for this binary.
aclTargetInfo info_;
std::string buildLog_; //!< build log.
cl_int buildStatus_; //!< build status.
cl_int buildError_; //!< build error
const char* machineTarget_; //!< Machine target for this program
aclTargetInfo info_; //!< The info target for this binary.
size_t globalVariableTotalSize_;
amd::option::Options* programOptions_;
@@ -179,16 +187,32 @@ class Program : public amd::HeapObject {
bool hasGlobalStores() const { return hasGlobalStores_; }
protected:
//! Compile the device program with LC path
bool compileImplLC(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options);
//! Compile the device program with HSAIL path
bool compileImplHSAIL(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options);
//! pre-compile setup
virtual bool initBuild(amd::option::Options* options);
//! post-compile cleanup
virtual bool finiBuild(bool isBuildGood);
//! Compile the device program.
virtual bool compileImpl(const std::string& sourceCode,
/*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
*
* \return True if we successefully compiled a GPU program
*/
virtual bool compileImpl(
const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) = 0;
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
);
//! Link the device program.
virtual bool linkImpl(amd::option::Options* options) = 0;
@@ -205,6 +229,8 @@ class Program : public amd::HeapObject {
//! Initialize Binary
virtual bool initClBinary();
virtual bool saveBinaryAndSetType(type_t type) = 0;
//! Release the Binary
void releaseClBinary();
@@ -223,6 +249,11 @@ class Program : public amd::HeapObject {
void setType(type_t newType) { type_ = newType; }
#if defined(WITH_LIGHTNING_COMPILER)
//! Return a new transient compiler instance.
static std::unique_ptr<amd::opencl_driver::Compiler> newCompilerInstance();
#endif // defined(WITH_LIGHTNING_COMPILER)
private:
//! Disable default copy constructor
Program(const Program&);
+2
Dosyayı Görüntüle
@@ -265,6 +265,8 @@ class NullProgram : public device::Program {
virtual const aclTargetInfo& info(const char* str = "");
virtual bool saveBinaryAndSetType(type_t type) { return true; }
private:
//! Disable default copy constructor
NullProgram(const NullProgram&);
-404
Dosyayı Görüntüle
@@ -1,404 +0,0 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iterator>
#include "os/os.hpp"
#include "device/pal/paldevice.hpp"
#include "device/pal/palprogram.hpp"
#include "device/pal/palkernel.hpp"
#include "utils/options.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "driver/AmdCompiler.h"
#include "opencl1.2-c.amdgcn.inc"
#include "opencl2.0-c.amdgcn.inc"
#endif // !defined(WITH_LIGHTNING_COMPILER)
#include <cstdio>
#if defined(ATI_OS_LINUX)
#include <dlfcn.h>
#include <libgen.h>
#endif // defined(ATI_OS_LINUX)
#if defined(ATI_OS_WIN)
#include <windows.h>
#endif // defined(ATI_OS_WIN)
// CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = nullptr);
namespace pal {
bool HSAILProgram::compileImpl(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
#if defined(WITH_LIGHTNING_COMPILER)
assert(!"Should not reach here");
#else // !defined(WITH_LIGHTNING_COMPILER)
acl_error errorCode;
aclTargetInfo target;
std::string arch = "hsail";
if (dev().settings().use64BitPtr_) {
arch += "64";
}
target = aclGetTargetInfo(arch.c_str(), dev().hwInfo()->targetName_, &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();
// Iterate through each source code and dump it into tmp
std::fstream f;
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 (auto& it : headerIncludeName) {
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;
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().compiler(), 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);
}
#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(ProcessOptions(options));
errorCode = aclCompile(dev().compiler(), binaryElf_, compileOptions_.c_str(), ACL_TYPE_OPENCL,
ACL_TYPE_LLVMIR_BINARY, nullptr);
buildLog_ += aclGetCompilerLog(dev().compiler());
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
saveBinaryAndSetType(TYPE_COMPILED);
#endif // !defined(WITH_LIGHTNING_COMPILER)
return true;
}
#if defined(WITH_LIGHTNING_COMPILER)
static std::string llvmBin_(amd::Os::getEnvironment("LLVM_BIN"));
#if defined(ATI_OS_WIN)
static BOOL CALLBACK checkLLVM_BIN(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* lpContex) {
if (llvmBin_.empty()) {
HMODULE hm = NULL;
if (GetModuleHandleExA(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&amd::Device::init, &hm)) {
char path[1024];
GetModuleFileNameA(hm, path, sizeof(path));
llvmBin_ = path;
size_t pos = llvmBin_.rfind('\\');
if (pos != std::string::npos) {
llvmBin_.resize(pos);
}
}
}
return TRUE;
}
#endif // defined (ATI_OS_WINDOWS)
#if defined(ATI_OS_LINUX)
static pthread_once_t once = PTHREAD_ONCE_INIT;
static void checkLLVM_BIN() {
if (llvmBin_.empty()) {
Dl_info info;
if (dladdr((const void*)&amd::Device::init, &info)) {
char* str = strdup(info.dli_fname);
if (str) {
llvmBin_ = dirname(str);
free(str);
size_t pos = llvmBin_.rfind("lib");
if (pos != std::string::npos) {
llvmBin_.replace(pos, 3, "bin");
}
}
}
}
}
#endif // defined(ATI_OS_LINUX)
std::unique_ptr<amd::opencl_driver::Compiler> LightningProgram::newCompilerInstance() {
#if defined(ATI_OS_WIN)
static INIT_ONCE initOnce;
InitOnceExecuteOnce(&initOnce, checkLLVM_BIN, NULL, NULL);
#endif // defined(ATI_OS_WIN)
#if defined(ATI_OS_LINUX)
pthread_once(&once, checkLLVM_BIN);
#endif // defined(ATI_OS_LINUX)
#if defined(DEBUG)
std::string clangExe(llvmBin_ + LINUX_SWITCH("/clang", "\\clang.exe"));
struct stat buf;
if (stat(clangExe.c_str(), &buf)) {
std::string msg("Could not find the Clang binary in " + llvmBin_);
LogWarning(msg.c_str());
}
#endif // defined(DEBUG)
return std::unique_ptr<amd::opencl_driver::Compiler>(
amd::opencl_driver::CompilerFactory().CreateAMDGPUCompiler(llvmBin_));
}
bool LightningProgram::compileImpl(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
using namespace amd::opencl_driver;
std::unique_ptr<Compiler> C(newCompilerInstance());
std::vector<Data*> inputs;
Data* input = C->NewBufferReference(DT_CL, sourceCode.c_str(), sourceCode.length());
if (input == NULL) {
buildLog_ += "Error while creating data from source code";
return false;
}
inputs.push_back(input);
amd::opencl_driver::Buffer* output = C->NewBuffer(DT_LLVM_BC);
if (output == NULL) {
buildLog_ += "Error while creating buffer for the LLVM bitcode";
return false;
}
// Set the options for the compiler
// Some options are set in Clang AMDGPUToolChain (like -m64)
std::ostringstream ostrstr;
std::copy(options->clangOptions.begin(), options->clangOptions.end(),
std::ostream_iterator<std::string>(ostrstr, " "));
std::string driverOptions(ostrstr.str());
const char* xLang = options->oVariables->XLang;
if (xLang != NULL && strcmp(xLang, "cl")) {
buildLog_ += "Unsupported OpenCL language.\n";
}
// FIXME_Nikolay: the program manager should be setting the language
// driverOptions.append(" -x cl");
driverOptions.append(" -cl-std=").append(options->oVariables->CLStd);
// Set the -O#
std::ostringstream optLevel;
optLevel << " -O" << options->oVariables->OptLevel;
driverOptions.append(optLevel.str());
// Set the machine target
std::ostringstream mCPU;
mCPU << " -mcpu=gfx" << dev().hwInfo()->gfxipVersion_;
driverOptions.append(mCPU.str());
// Set xnack option if needed
if (dev().hwInfo()->xnackEnabled_) {
driverOptions.append(" -mxnack");
}
driverOptions.append(options->llvmOptions);
driverOptions.append(ProcessOptions(options));
// Set whole program mode
driverOptions.append(" -mllvm -amdgpu-early-inline-all -mllvm -amdgpu-prelink");
// Find the temp folder for the OS
std::string tempFolder = amd::Os::getEnvironment("TEMP");
if (tempFolder.empty()) {
tempFolder = amd::Os::getEnvironment("TMP");
if (tempFolder.empty()) {
tempFolder = WINDOWS_SWITCH(".", "/tmp");
;
}
}
// 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 (auto& it : headerIncludeName) {
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();
Data* inc = C->NewFileReference(DT_CL_HEADER, headerFileNames[i]);
if (inc == NULL) {
buildLog_ += "Error while creating data from headers";
return false;
}
inputs.push_back(inc);
}
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
driverOptions.append(" -I");
driverOptions.append(tempFolder);
}
if (options->isDumpFlagSet(amd::option::DUMP_CL)) {
std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc);
if (f.is_open()) {
f << "/* Compiler options:\n"
"-c -emit-llvm -target amdgcn-amd-amdhsa -x cl "
<< driverOptions << " -include opencl-c.h "
<< "\n*/\n\n"
<< sourceCode;
f.close();
} else {
buildLog_ += "Warning: opening the file to dump the OpenCL source failed.\n";
}
}
// FIXME_lmoriche: has the CL option been validated?
uint clcStd =
(options->oVariables->CLStd[2] - '0') * 100 + (options->oVariables->CLStd[4] - '0') * 10;
std::pair<const void*, size_t> hdr;
switch (clcStd) {
case 100:
case 110:
case 120:
hdr = {opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size};
break;
case 200:
hdr = {opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size};
break;
default:
buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
return false;
}
File* pch = C->NewTempFile(DT_CL_HEADER);
if (pch == NULL || !pch->WriteData((const char*)hdr.first, hdr.second)) {
buildLog_ += "Error while opening the opencl-c header ";
return false;
}
driverOptions.append(" -include-pch " + pch->Name());
driverOptions.append(" -Xclang -fno-validate-pch");
// Tokenize the options string into a vector of strings
std::istringstream istrstr(driverOptions);
std::istream_iterator<std::string> sit(istrstr), end;
std::vector<std::string> params(sit, end);
// Compile source to IR
bool ret =
dev().cacheCompilation()->compileToLLVMBitcode(C.get(), inputs, output, params, buildLog_);
buildLog_ += C->Output();
if (!ret) {
buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n";
return false;
}
llvmBinary_.assign(output->Buf().data(), output->Size());
elfSectionType_ = amd::OclElf::LLVMIR;
if (options->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
std::ofstream f(options->getDumpFileName("_original.bc").c_str(),
std::ios::binary | std::ios::trunc);
if (f.is_open()) {
f.write(llvmBinary_.data(), llvmBinary_.size());
f.close();
} else {
buildLog_ += "Warning: opening the file to dump the compiled IR failed.\n";
}
}
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;
}
#endif // defined(WITH_LIGHTNING_COMPILER)
} // namespace pal
-8
Dosyayı Görüntüle
@@ -110,10 +110,6 @@ class NullDevice : public amd::Device {
}
virtual void svmFree(void* ptr) const { return; }
#if defined(WITH_LIGHTNING_COMPILER)
amd::CacheCompilation* cacheCompilation() const { return cacheCompilation_.get(); }
#endif
void* Alloc(const Util::AllocInfo& allocInfo) { return allocator_.Alloc(allocInfo); }
void Free(const Util::FreeInfo& freeInfo) { allocator_.Free(freeInfo); }
@@ -124,10 +120,6 @@ class NullDevice : public amd::Device {
Pal::GfxIpLevel ipLevel_; //!< Device IP level
const AMDDeviceInfo* hwInfo_; //!< Device HW info structure
#if defined(WITH_LIGHTNING_COMPILER)
std::unique_ptr<amd::CacheCompilation> cacheCompilation_; //! Compilation with cache support
#endif
//! Fills OpenCL device info structure
void fillDeviceInfo(const Pal::DeviceProperties& palProp, //!< PAL device properties
const Pal::GpuMemoryHeapProperties heaps[Pal::GpuHeapCount],
+9
Dosyayı Görüntüle
@@ -143,6 +143,13 @@ HSAILProgram::HSAILProgram(Device& device)
maxScratchRegs_(0),
executable_(nullptr),
loaderContext_(this) {
xnackEnabled_ = dev().hwInfo()->xnackEnabled_;
if (dev().properties().revision == Pal::AsicRevision::Bristol) {
const static char* Carrizo = "Carrizo";
machineTarget_ = Carrizo;
} else {
machineTarget_ = dev().hwInfo()->targetName_;
}
loader_ = amd::hsa::loader::Loader::Create(&loaderContext_);
}
@@ -156,6 +163,8 @@ HSAILProgram::HSAILProgram(NullDevice& device)
executable_(nullptr),
loaderContext_(this) {
isNull_ = true;
xnackEnabled_ = dev().hwInfo()->xnackEnabled_;
machineTarget_ = dev().hwInfo()->targetName_;
loader_ = amd::hsa::loader::Loader::Create(&loaderContext_);
}
+14 -21
Dosyayı Görüntüle
@@ -181,16 +181,6 @@ class HSAILProgram : public device::Program {
//! post-compile setup for GPU
virtual bool finiBuild(bool isBuildGood);
/*! \brief Compiles GPU CL program to LLVM binary (compiler frontend)
*
* \return True if we successefully compiled a GPU program
*/
virtual bool compileImpl(const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
);
/* \brief Returns the next stage to compile from, based on sections in binary,
* also returns completeStages in a vector, which contains at least ACL_TYPE_DEFAULT,
* sets needOptionsCheck to true if options check is needed to decide whether or not to recompile
@@ -251,9 +241,21 @@ class HSAILProgram : public device::Program {
//! \class Lightning Compiler Program
class LightningProgram : public HSAILProgram {
public:
LightningProgram(NullDevice& device) : HSAILProgram(device), metadata_(nullptr) {}
LightningProgram(NullDevice& device)
: HSAILProgram(device)
, metadata_(nullptr) {
isLC_ = true;
xnackEnabled_ = dev().hwInfo()->xnackEnabled_;
machineTarget_ = dev().hwInfo()->machineTarget_;
}
LightningProgram(Device& device) : HSAILProgram(device), metadata_(nullptr) {}
LightningProgram(Device& device)
: HSAILProgram(device)
, metadata_(nullptr) {
isLC_ = true;
xnackEnabled_ = dev().hwInfo()->xnackEnabled_;
machineTarget_ = dev().hwInfo()->machineTarget_;
}
const CodeObjectMD* metadata() const { return metadata_; }
@@ -272,12 +274,6 @@ class LightningProgram : public HSAILProgram {
aclType getNextCompilationStageFromBinary(amd::option::Options* options);
protected:
virtual bool compileImpl(const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
) override;
virtual bool linkImpl(amd::option::Options* options) override;
//! Link the device programs.
@@ -288,9 +284,6 @@ class LightningProgram : public HSAILProgram {
virtual bool createBinary(amd::option::Options* options) override;
//! Return a new transient compiler instance.
static std::unique_ptr<amd::opencl_driver::Compiler> newCompilerInstance();
private:
CodeObjectMD* metadata_; //!< Runtime metadata
};
-401
Dosyayı Görüntüle
@@ -1,401 +0,0 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef WITHOUT_HSA_BACKEND
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include "os/os.hpp"
#include "rocdevice.hpp"
#include "rocprogram.hpp"
#if defined(WITH_LIGHTNING_COMPILER)
#include "opencl1.2-c.amdgcn.inc"
#include "opencl2.0-c.amdgcn.inc"
#endif // defined(WITH_LIGHTNING_COMPILER)
#include "utils/options.hpp"
#include <cstdio>
#include <iterator>
#if defined(ATI_OS_LINUX)
#include <dlfcn.h>
#include <libgen.h>
#endif // defined(ATI_OS_LINUX)
#define QUOTE(s) #s
#define STRING(s) QUOTE(s)
#define AMDGCN_TRIPLE amdgcn-amd-amdhsa
#if defined(WITH_LIGHTNING_COMPILER)
static std::string llvmBin_(amd::Os::getEnvironment("LLVM_BIN"));
#endif // defined(WITH_LIGHTNING_COMPILER)
// CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = nullptr);
namespace roc {
/* Temporary log function for the compiler library */
static void logFunction(const char* msg, size_t size) {
std::cout << "Compiler Log: " << msg << std::endl;
}
static int programsCount = 0;
#if defined(WITH_COMPILER_LIB)
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;
target = aclGetTargetInfo(LP64_SWITCH("hsail", "hsail64"),
dev().deviceInfo().complibTarget_, &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::getEnvironment("TEMP");
if (tempFolder.empty()) {
tempFolder = amd::Os::getEnvironment("TMP");
if (tempFolder.empty()) {
tempFolder = WINDOWS_SWITCH(".", "/tmp");
;
}
}
// 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 (auto& it : headerIncludeName) {
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 while compiling opencl source:\
aclBinary init failure \n";
LogWarning("aclBinaryInit failed");
return false;
}
// Insert opencl into binary
errorCode = aclInsertSection(device().compiler(), binaryElf_, sourceCode.c_str(),
strlen(sourceCode.c_str()), aclSOURCE);
if (errorCode != ACL_SUCCESS) {
buildLog_ +=
"Error while converting to BRIG: \
Inserting openCl Source \n";
}
// Set the options for the compiler
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
this->compileOptions_.append(" -I");
this->compileOptions_.append(tempFolder);
}
// Compile source to IR
this->compileOptions_.append(ProcessOptions(options));
errorCode = aclCompile(device().compiler(), binaryElf_,
//"-Wf,--support_all_extensions",
this->compileOptions_.c_str(), ACL_TYPE_OPENCL,
ACL_TYPE_LLVMIR_BINARY, logFunction);
buildLog_ += aclGetCompilerLog(device().compiler());
if (errorCode != ACL_SUCCESS) {
LogWarning("aclCompile failed");
buildLog_ +=
"Error while compiling \
opencl source: Compiling CL to IR";
return false;
}
// Save the binary in the interface class
saveBinaryAndSetType(TYPE_COMPILED);
return true;
}
#endif // defined(WITH_COMPILER_LIB)
#if defined(WITH_LIGHTNING_COMPILER)
bool LightningProgram::compileImpl(const std::string& sourceCode,
const std::vector<const std::string*>& headers,
const char** headerIncludeNames, amd::option::Options* options) {
const char* xLang = options->oVariables->XLang;
if (xLang != nullptr) {
if (strcmp(xLang,"asm") == 0) {
clBinary()->elfOut()->addSection(amd::OclElf::SOURCE, sourceCode.data(), sourceCode.size());
return true;
} else if (!strcmp(xLang,"cl")) {
buildLog_ += "Unsupported language: \"" + std::string(xLang) + "\".\n";
return false;
}
}
using namespace amd::opencl_driver;
amd::opencl_driver::DataType inputType(DT_CL);
std::unique_ptr<Compiler> C(newCompilerInstance());
std::vector<Data*> inputs;
Data* input = C->NewBufferReference(inputType, sourceCode.c_str(), sourceCode.length());
if (input == nullptr) {
buildLog_ += "Error while creating data from source code";
return false;
}
inputs.push_back(input);
Buffer* output = C->NewBuffer(DT_LLVM_BC);
if (output == nullptr) {
buildLog_ += "Error while creating buffer for the LLVM bitcode";
return false;
}
// Set the options for the compiler
// Some options are set in Clang AMDGPUToolChain (like -m64)
std::ostringstream ostrstr;
std::copy(options->clangOptions.begin(), options->clangOptions.end(),
std::ostream_iterator<std::string>(ostrstr, " "));
std::string driverOptions(ostrstr.str());
// FIXME_Nikolay: the program manager should be setting the language
// driverOptions.append(" -x cl");
driverOptions.append(" -cl-std=").append(options->oVariables->CLStd);
// Set the -O#
std::ostringstream optLevel;
optLevel << " -O" << options->oVariables->OptLevel;
driverOptions.append(optLevel.str());
// Set the machine target
driverOptions.append(" -mcpu=");
driverOptions.append(dev().deviceInfo().machineTarget_);
// Set xnack option if needed
if (dev().deviceInfo().xnackEnabled_) {
driverOptions.append(" -mxnack");
}
driverOptions.append(options->llvmOptions);
// Set whole program mode
driverOptions.append(" -mllvm -amdgpu-early-inline-all -mllvm -amdgpu-prelink");
driverOptions.append(ProcessOptions(options));
// Find the temp folder for the OS
std::string tempFolder = amd::Os::getEnvironment("TEMP");
if (tempFolder.empty()) {
tempFolder = amd::Os::getEnvironment("TMP");
if (tempFolder.empty()) {
tempFolder = WINDOWS_SWITCH(".", "/tmp");
;
}
}
// 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 (auto& it : headerIncludeName) {
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();
Data* inc = C->NewFileReference(DT_CL_HEADER, headerFileNames[i]);
if (inc == nullptr) {
buildLog_ += "Error while creating data from headers";
return false;
}
inputs.push_back(inc);
}
// Set the include path for the temp folder that contains the includes
if (!headers.empty()) {
driverOptions.append(" -I");
driverOptions.append(tempFolder);
}
if (options->isDumpFlagSet(amd::option::DUMP_CL)) {
std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc);
if (f.is_open()) {
f << "/* Compiler options:\n"
"-c -emit-llvm -target " STRING(AMDGCN_TRIPLE) " -x cl "
<< driverOptions << " -include opencl-c.h "
<< "\n*/\n\n"
<< sourceCode;
} else {
buildLog_ += "Warning: opening the file to dump the OpenCL source failed.\n";
}
}
// FIXME_lmoriche: has the CL option been validated?
uint clcStd =
(options->oVariables->CLStd[2] - '0') * 100 + (options->oVariables->CLStd[4] - '0') * 10;
std::pair<const void*, size_t> hdr;
switch (clcStd) {
case 100:
case 110:
case 120:
hdr = {opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size};
break;
case 200:
hdr = {opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size};
break;
default:
buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
return false;
}
File* pch = C->NewTempFile(DT_CL_HEADER);
if (pch == nullptr || !pch->WriteData((const char*)hdr.first, hdr.second)) {
buildLog_ += "Error while opening the opencl-c header ";
return false;
}
driverOptions.append(" -include-pch " + pch->Name());
driverOptions.append(" -Xclang -fno-validate-pch");
// Tokenize the options string into a vector of strings
std::istringstream istrstr(driverOptions);
std::istream_iterator<std::string> sit(istrstr), end;
std::vector<std::string> params(sit, end);
// Compile source to IR
bool ret =
dev().cacheCompilation()->compileToLLVMBitcode(C.get(), inputs, output, params, buildLog_);
buildLog_ += C->Output();
if (!ret) {
buildLog_ += "Error: Failed to compile opencl source (from CL to LLVM IR).\n";
return false;
}
llvmBinary_.assign(output->Buf().data(), output->Size());
elfSectionType_ = amd::OclElf::LLVMIR;
if (options->isDumpFlagSet(amd::option::DUMP_BC_ORIGINAL)) {
std::ofstream f(options->getDumpFileName("_original.bc").c_str(), std::ios::trunc);
if (f.is_open()) {
f.write(llvmBinary_.data(), llvmBinary_.size());
} else {
buildLog_ += "Warning: opening the file to dump the compiled IR failed.\n";
}
}
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;
}
#if defined(ATI_OS_LINUX)
static pthread_once_t once = PTHREAD_ONCE_INIT;
static void checkLLVM_BIN() {
if (llvmBin_.empty()) {
Dl_info info;
if (dladdr((const void*)&amd::Device::init, &info)) {
char* str = strdup(info.dli_fname);
if (str) {
llvmBin_ = dirname(str);
free(str);
size_t pos = llvmBin_.rfind("lib");
if (pos != std::string::npos) {
llvmBin_.replace(pos, 3, "bin");
}
}
}
}
#if defined(DEBUG)
static const std::string tools[] = {"clang", "llvm-link", "ld.lld"};
for (const std::string tool : tools) {
std::string exePath(llvmBin_ + "/" + tool);
struct stat buf;
if (stat(exePath.c_str(), &buf)) {
std::string msg(exePath + " not found");
LogWarning(msg.c_str());
} else if ((buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
std::string msg("Cannot execute " + exePath);
LogWarning(msg.c_str());
}
}
#endif // defined(DEBUG)
}
#endif // defined(ATI_OS_LINUX)
amd::opencl_driver::Compiler* LightningProgram::newCompilerInstance() {
#if defined(ATI_OS_LINUX)
pthread_once(&once, checkLLVM_BIN);
#endif // defined(ATI_OS_LINUX)
return amd::opencl_driver::CompilerFactory().CreateAMDGPUCompiler(llvmBin_);
}
#endif // defined(WITH_LIGHTNING_COMPILER)
} // namespace roc
#endif // WITHOUT_GPU_BACKEND
+1 -8
Dosyayı Görüntüle
@@ -176,10 +176,6 @@ class NullDevice : public amd::Device {
return false;
}
#if defined(WITH_LIGHTNING_COMPILER)
amd::CacheCompilation* cacheCompilation() const { return cacheCompilation_.get(); }
#endif
protected:
//! Initialize compiler instance and handle
static bool initCompiler(bool isOffline);
@@ -189,10 +185,7 @@ class NullDevice : public amd::Device {
static Compiler* compilerHandle_;
//! Device Id for an HsaDevice
AMDDeviceInfo deviceInfo_;
#if defined(WITH_LIGHTNING_COMPILER)
//! Compilation with cache support
std::unique_ptr<amd::CacheCompilation> cacheCompilation_;
#endif
private:
static const bool offlineDevice_;
};
+7 -1
Dosyayı Görüntüle
@@ -265,6 +265,8 @@ aclType Program::getNextCompilationStageFromBinary(amd::option::Options* options
#if defined(WITH_COMPILER_LIB)
HSAILProgram::HSAILProgram(roc::NullDevice& device) : roc::Program(device) {
xnackEnabled_ = dev().deviceInfo().xnackEnabled_;
machineTarget_ = dev().deviceInfo().complibTarget_;
}
HSAILProgram::~HSAILProgram() {
@@ -715,7 +717,11 @@ bool HSAILProgram::linkImpl(amd::option::Options* options) {
#endif // defined(WITH_COMPILER_LIB)
#if defined(WITH_LIGHTNING_COMPILER)
LightningProgram::LightningProgram(roc::NullDevice& device) : roc::Program(device) {
LightningProgram::LightningProgram(roc::NullDevice& device)
: roc::Program(device) {
isLC_ = true;
xnackEnabled_ = dev().deviceInfo().xnackEnabled_;
machineTarget_ = dev().deviceInfo().machineTarget_;
metadata_ = nullptr;
}
+2 -14
Dosyayı Görüntüle
@@ -101,12 +101,6 @@ class HSAILProgram : public roc::Program {
virtual ~HSAILProgram();
protected:
virtual bool compileImpl(const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
) final;
virtual bool linkImpl(amd::option::Options* options) final;
virtual bool linkImpl(const std::vector<device::Program*>& inputPrograms,
@@ -134,12 +128,6 @@ public:
const CodeObjectMD* metadata() const { return metadata_; }
protected:
virtual bool compileImpl(const std::string& sourceCode, //!< the program's source code
const std::vector<const std::string*>& headers,
const char** headerIncludeNames,
amd::option::Options* options //!< compile options's object
) final;
virtual bool linkImpl(amd::option::Options* options) final;
virtual bool linkImpl(const std::vector<device::Program*>& inputPrograms,
@@ -147,6 +135,8 @@ protected:
virtual bool createBinary(amd::option::Options* options) final;
bool saveBinaryAndSetType(type_t type) { return true; }
private:
bool saveBinaryAndSetType(type_t type, void* rawBinary, size_t size);
@@ -156,8 +146,6 @@ private:
bool setKernels(amd::option::Options* options, void* binary, size_t binSize);
CodeObjectMD* metadata_; //!< Runtime metadata
//! Return a new transient compiler instance.
static amd::opencl_driver::Compiler* newCompilerInstance();
};
#endif // defined(WITH_LIGHTNING_COMPILER)