From e132af9cad3c1a86f1bb4c3d3b690dca049d5cf4 Mon Sep 17 00:00:00 2001 From: foreman Date: Wed, 19 Sep 2018 17:06:20 -0400 Subject: [PATCH] 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 --- rocclr/runtime/device/device.hpp | 9 + rocclr/runtime/device/devprogram.cpp | 418 ++++++++++++++++++++- rocclr/runtime/device/devprogram.hpp | 57 ++- rocclr/runtime/device/gpu/gpuprogram.hpp | 2 + rocclr/runtime/device/pal/palcompiler.cpp | 404 -------------------- rocclr/runtime/device/pal/paldevice.hpp | 8 - rocclr/runtime/device/pal/palprogram.cpp | 9 + rocclr/runtime/device/pal/palprogram.hpp | 35 +- rocclr/runtime/device/rocm/roccompiler.cpp | 401 -------------------- rocclr/runtime/device/rocm/rocdevice.hpp | 9 +- rocclr/runtime/device/rocm/rocprogram.cpp | 8 +- rocclr/runtime/device/rocm/rocprogram.hpp | 16 +- 12 files changed, 504 insertions(+), 872 deletions(-) delete mode 100644 rocclr/runtime/device/pal/palcompiler.cpp delete mode 100644 rocclr/runtime/device/rocm/roccompiler.cpp diff --git a/rocclr/runtime/device/device.hpp b/rocclr/runtime/device/device.hpp index ed5ce51a29..36dfe95d8e 100644 --- a/rocclr/runtime/device/device.hpp +++ b/rocclr/runtime/device/device.hpp @@ -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 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 cacheCompilation_; +#endif private: bool IsTypeMatching(cl_device_type type, bool offlineDevices); diff --git a/rocclr/runtime/device/devprogram.cpp b/rocclr/runtime/device/devprogram.cpp index 23c5bd697e..27875b0cd0 100644 --- a/rocclr/runtime/device/devprogram.cpp +++ b/rocclr/runtime/device/devprogram.cpp @@ -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 +#include +#include #include #include +#include + +#if defined(ATI_OS_LINUX) +#include +#include +#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& 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 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::CompilerFactory().CreateAMDGPUCompiler(llvmBin_)); +} +#endif // defined(WITH_LIGHTNING_COMPILER) + +// ================================================================================================ +bool Program::compileImplLC(const std::string& sourceCode, + const std::vector& 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 C(newCompilerInstance()); + std::vector 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(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 headerFileNames(headers.size()); + std::vector 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 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 sit(istrstr), end; + std::vector 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& 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 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) { diff --git a/rocclr/runtime/device/devprogram.hpp b/rocclr/runtime/device/devprogram.hpp index 8e358d761a..1da4767553 100644 --- a/rocclr/runtime/device/devprogram.hpp +++ b/rocclr/runtime/device/devprogram.hpp @@ -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 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& headers, + const char** headerIncludeNames, amd::option::Options* options); + + //! Compile the device program with HSAIL path + bool compileImplHSAIL(const std::string& sourceCode, + const std::vector& 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& 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 newCompilerInstance(); +#endif // defined(WITH_LIGHTNING_COMPILER) + private: //! Disable default copy constructor Program(const Program&); diff --git a/rocclr/runtime/device/gpu/gpuprogram.hpp b/rocclr/runtime/device/gpu/gpuprogram.hpp index 58d61d693a..cbbb4590cd 100644 --- a/rocclr/runtime/device/gpu/gpuprogram.hpp +++ b/rocclr/runtime/device/gpu/gpuprogram.hpp @@ -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&); diff --git a/rocclr/runtime/device/pal/palcompiler.cpp b/rocclr/runtime/device/pal/palcompiler.cpp deleted file mode 100644 index 4077ce22cc..0000000000 --- a/rocclr/runtime/device/pal/palcompiler.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// -// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved. -// - -#include -#include -#include -#include -#include - -#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 - -#if defined(ATI_OS_LINUX) -#include -#include -#endif // defined(ATI_OS_LINUX) -#if defined(ATI_OS_WIN) -#include -#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& 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 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 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::CompilerFactory().CreateAMDGPUCompiler(llvmBin_)); -} - -bool LightningProgram::compileImpl(const std::string& sourceCode, - const std::vector& headers, - const char** headerIncludeNames, amd::option::Options* options) { - using namespace amd::opencl_driver; - std::unique_ptr C(newCompilerInstance()); - std::vector 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(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 headerFileNames(headers.size()); - std::vector 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 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 sit(istrstr), end; - std::vector 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 diff --git a/rocclr/runtime/device/pal/paldevice.hpp b/rocclr/runtime/device/pal/paldevice.hpp index f3fd74fc6b..f27bbd55a7 100644 --- a/rocclr/runtime/device/pal/paldevice.hpp +++ b/rocclr/runtime/device/pal/paldevice.hpp @@ -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 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], diff --git a/rocclr/runtime/device/pal/palprogram.cpp b/rocclr/runtime/device/pal/palprogram.cpp index 324f217624..071004789b 100644 --- a/rocclr/runtime/device/pal/palprogram.cpp +++ b/rocclr/runtime/device/pal/palprogram.cpp @@ -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_); } diff --git a/rocclr/runtime/device/pal/palprogram.hpp b/rocclr/runtime/device/pal/palprogram.hpp index aed9715971..582385a6d6 100644 --- a/rocclr/runtime/device/pal/palprogram.hpp +++ b/rocclr/runtime/device/pal/palprogram.hpp @@ -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& 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& 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 newCompilerInstance(); - private: CodeObjectMD* metadata_; //!< Runtime metadata }; diff --git a/rocclr/runtime/device/rocm/roccompiler.cpp b/rocclr/runtime/device/rocm/roccompiler.cpp deleted file mode 100644 index c1011b7d35..0000000000 --- a/rocclr/runtime/device/rocm/roccompiler.cpp +++ /dev/null @@ -1,401 +0,0 @@ -// -// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved. -// -#ifndef WITHOUT_HSA_BACKEND - -#include -#include -#include -#include - -#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 -#include - -#if defined(ATI_OS_LINUX) -#include -#include -#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& 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 headerFileNames(headers.size()); - std::vector 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& 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 C(newCompilerInstance()); - std::vector 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(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 headerFileNames(headers.size()); - std::vector 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 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 sit(istrstr), end; - std::vector 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 diff --git a/rocclr/runtime/device/rocm/rocdevice.hpp b/rocclr/runtime/device/rocm/rocdevice.hpp index 7a2c811a93..7ce56222cf 100644 --- a/rocclr/runtime/device/rocm/rocdevice.hpp +++ b/rocclr/runtime/device/rocm/rocdevice.hpp @@ -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 cacheCompilation_; -#endif + private: static const bool offlineDevice_; }; diff --git a/rocclr/runtime/device/rocm/rocprogram.cpp b/rocclr/runtime/device/rocm/rocprogram.cpp index b36664a7f8..526b25ce52 100644 --- a/rocclr/runtime/device/rocm/rocprogram.cpp +++ b/rocclr/runtime/device/rocm/rocprogram.cpp @@ -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; } diff --git a/rocclr/runtime/device/rocm/rocprogram.hpp b/rocclr/runtime/device/rocm/rocprogram.hpp index 61b87659e5..182258c532 100644 --- a/rocclr/runtime/device/rocm/rocprogram.hpp +++ b/rocclr/runtime/device/rocm/rocprogram.hpp @@ -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& 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& 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& 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& 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)