mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-24 12:23:05 +08:00
Refactoring/preparation for preferred IR from FCL
NEO will be querying FCL for preferrerd IR (intermediate representation) instead of using llvm bc. Change-Id: I98316b5623557a9651da2a4c5e610ab26421c491
This commit is contained in:
committed by
sys_ocldev
parent
30777275d4
commit
b490a1331b
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -1,4 +1,4 @@
|
||||
#!groovy
|
||||
neoDependenciesRev='782940-1037'
|
||||
strategy='EQUAL'
|
||||
allowedCD=298
|
||||
allowedCD=297
|
||||
|
||||
@@ -96,7 +96,7 @@ OfflineCompiler::OfflineCompiler() = default;
|
||||
// dtor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OfflineCompiler::~OfflineCompiler() {
|
||||
delete[] llvmBinary;
|
||||
delete[] irBinary;
|
||||
delete[] genBinary;
|
||||
delete[] elfBinary;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ int OfflineCompiler::buildSourceCode() {
|
||||
CIF::RAII::UPtr_t<IGC::OclTranslationOutputTagOCL> igcOutput;
|
||||
|
||||
if (!inputFileLlvm) {
|
||||
IGC::CodeType::CodeType_t intermediateRepresentation = useLlvmText ? IGC::CodeType::llvmLl : IGC::CodeType::llvmBc;
|
||||
IGC::CodeType::CodeType_t intermediateRepresentation = useLlvmText ? IGC::CodeType::llvmLl : preferredIntermediateRepresentation;
|
||||
// sourceCode.size() returns the number of characters without null terminated char
|
||||
auto fclSrc = CIF::Builtins::CreateConstBuffer(fclMain.get(), sourceCode.c_str(), sourceCode.size() + 1);
|
||||
auto fclOptions = CIF::Builtins::CreateConstBuffer(fclMain.get(), options.c_str(), options.size());
|
||||
@@ -169,7 +169,8 @@ int OfflineCompiler::buildSourceCode() {
|
||||
break;
|
||||
}
|
||||
|
||||
storeBinary(llvmBinary, llvmBinarySize, fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw());
|
||||
storeBinary(irBinary, irBinarySize, fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw());
|
||||
isSpirV = intermediateRepresentation == IGC::CodeType::spirV;
|
||||
updateBuildLog(fclOutput->GetBuildLog()->GetMemory<char>(), fclOutput->GetBuildLog()->GetSizeRaw());
|
||||
|
||||
igcOutput = igcTranslationCtx->Translate(fclOutput->GetOutput(), fclOptions.get(),
|
||||
@@ -359,6 +360,7 @@ int OfflineCompiler::initialize(uint32_t numArgs, const char **argv) {
|
||||
}
|
||||
|
||||
fclDeviceCtx->SetOclApiVersion(hwInfo->capabilityTable.clVersionSupport * 10);
|
||||
preferredIntermediateRepresentation = IGC::CodeType::llvmBc;
|
||||
|
||||
this->igcLib.reset(OsLibrary::load(Os::igcDllName));
|
||||
if (this->igcLib == nullptr) {
|
||||
@@ -692,9 +694,9 @@ bool OfflineCompiler::generateElfBinary() {
|
||||
|
||||
if (retVal) {
|
||||
sectionNode.Name = "Intel(R) OpenCL LLVM Object";
|
||||
sectionNode.Type = CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY;
|
||||
sectionNode.pData = llvmBinary;
|
||||
sectionNode.DataSize = (uint32_t)llvmBinarySize;
|
||||
sectionNode.Type = isSpirV ? CLElfLib::SH_TYPE_SPIRV : CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY;
|
||||
sectionNode.pData = irBinary;
|
||||
sectionNode.DataSize = (uint32_t)irBinarySize;
|
||||
retVal = pElfWriter->addSection(§ionNode);
|
||||
}
|
||||
|
||||
@@ -758,31 +760,17 @@ void OfflineCompiler::writeOutAllFiles() {
|
||||
}
|
||||
}
|
||||
|
||||
if (llvmBinary) {
|
||||
std::string llvmOutputFile = (outputDirectory == "") ? "" : outputDirectory + "/";
|
||||
(useLlvmText == true) ? llvmOutputFile.append(fileBase + ".ll") : llvmOutputFile.append(fileBase + ".bc");
|
||||
|
||||
if (useOptionsSuffix) {
|
||||
std::string opts(options.c_str());
|
||||
std::replace(opts.begin(), opts.end(), ' ', '_');
|
||||
llvmOutputFile.append(opts);
|
||||
}
|
||||
if (irBinary) {
|
||||
std::string irOutputFileName = generateFilePathForIr(fileBase) + generateOptsSuffix();
|
||||
|
||||
writeDataToFile(
|
||||
llvmOutputFile.c_str(),
|
||||
llvmBinary,
|
||||
llvmBinarySize);
|
||||
irOutputFileName.c_str(),
|
||||
irBinary,
|
||||
irBinarySize);
|
||||
}
|
||||
|
||||
if (genBinary) {
|
||||
std::string genOutputFile = (outputDirectory == "") ? "" : outputDirectory + "/";
|
||||
genOutputFile.append(fileBase + ".gen");
|
||||
|
||||
if (useOptionsSuffix) {
|
||||
std::string opts(options.c_str());
|
||||
std::replace(opts.begin(), opts.end(), ' ', '_');
|
||||
genOutputFile.append(opts);
|
||||
}
|
||||
std::string genOutputFile = generateFilePath(outputDirectory, fileBase, ".gen") + generateOptsSuffix();
|
||||
|
||||
writeDataToFile(
|
||||
genOutputFile.c_str(),
|
||||
@@ -790,23 +778,14 @@ void OfflineCompiler::writeOutAllFiles() {
|
||||
genBinarySize);
|
||||
|
||||
if (useCppFile) {
|
||||
std::string cppOutputFile = (outputDirectory == "") ? "" : outputDirectory + "/";
|
||||
cppOutputFile.append(fileBase + ".cpp");
|
||||
std::string cppOutputFile = generateFilePath(outputDirectory, fileBase, ".cpp");
|
||||
std::string cpp = parseBinAsCharArray((uint8_t *)genBinary, genBinarySize, fileTrunk);
|
||||
writeDataToFile(cppOutputFile.c_str(), cpp.c_str(), cpp.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (elfBinary) {
|
||||
std::string elfOutputFile = (outputDirectory == "") ? "" : outputDirectory + "/";
|
||||
|
||||
elfOutputFile.append(fileBase + ".bin");
|
||||
|
||||
if (useOptionsSuffix) {
|
||||
std::string opts(options.c_str());
|
||||
std::replace(opts.begin(), opts.end(), ' ', '_');
|
||||
elfOutputFile.append(opts);
|
||||
}
|
||||
std::string elfOutputFile = generateFilePath(outputDirectory, fileBase, ".bin") + generateOptsSuffix();
|
||||
|
||||
writeDataToFile(
|
||||
elfOutputFile.c_str(),
|
||||
@@ -815,14 +794,7 @@ void OfflineCompiler::writeOutAllFiles() {
|
||||
}
|
||||
|
||||
if (debugDataBinary) {
|
||||
std::string debugOutputFile = (outputDirectory == "") ? "" : outputDirectory + "/";
|
||||
debugOutputFile.append(fileBase + ".dbg");
|
||||
|
||||
if (useOptionsSuffix) {
|
||||
std::string opts(options.c_str());
|
||||
std::replace(opts.begin(), opts.end(), ' ', '_');
|
||||
debugOutputFile.append(opts);
|
||||
}
|
||||
std::string debugOutputFile = generateFilePath(outputDirectory, fileBase, ".dbg") + generateOptsSuffix();
|
||||
|
||||
writeDataToFile(
|
||||
debugOutputFile.c_str(),
|
||||
@@ -856,4 +828,24 @@ bool OfflineCompiler::readOptionsFromFile(std::string &options, const std::strin
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string generateFilePath(const std::string &directory, const std::string &fileNameBase, const char *extension) {
|
||||
UNRECOVERABLE_IF(extension == nullptr);
|
||||
|
||||
if (directory.empty()) {
|
||||
return fileNameBase + extension;
|
||||
}
|
||||
|
||||
bool hasTrailingSlash = (*directory.rbegin() == '/');
|
||||
std::string ret;
|
||||
ret.reserve(directory.size() + (hasTrailingSlash ? 0 : 1) + fileNameBase.size() + strlen(extension) + 1);
|
||||
ret.append(directory);
|
||||
if (false == hasTrailingSlash) {
|
||||
ret.append("/", 1);
|
||||
}
|
||||
ret.append(fileNameBase);
|
||||
ret.append(extension);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
||||
|
||||
@@ -41,6 +41,8 @@ enum ErrorCode {
|
||||
PRINT_USAGE = -5152,
|
||||
};
|
||||
|
||||
std::string generateFilePath(const std::string &directory, const std::string &fileNameBase, const char *extension);
|
||||
|
||||
class OfflineCompiler {
|
||||
public:
|
||||
static OfflineCompiler *create(uint32_t numArgs, const char **argv, int &retVal);
|
||||
@@ -72,6 +74,16 @@ class OfflineCompiler {
|
||||
int buildSourceCode();
|
||||
void updateBuildLog(const char *pErrorString, const size_t errorStringSize);
|
||||
bool generateElfBinary();
|
||||
std::string generateFilePathForIr(const std::string &fileNameBase) {
|
||||
const char *ext = (isSpirV) ? ".spv" : ".bc";
|
||||
return generateFilePath(outputDirectory, fileNameBase, useLlvmText ? ".ll" : ext);
|
||||
}
|
||||
|
||||
std::string generateOptsSuffix() {
|
||||
std::string suffix{useOptionsSuffix ? options : ""};
|
||||
std::replace(suffix.begin(), suffix.end(), ' ', '_');
|
||||
return suffix;
|
||||
}
|
||||
void writeOutAllFiles();
|
||||
const HardwareInfo *hwInfo = nullptr;
|
||||
|
||||
@@ -95,8 +107,9 @@ class OfflineCompiler {
|
||||
size_t elfBinarySize = 0;
|
||||
char *genBinary = nullptr;
|
||||
size_t genBinarySize = 0;
|
||||
char *llvmBinary = nullptr;
|
||||
size_t llvmBinarySize = 0;
|
||||
char *irBinary = nullptr;
|
||||
size_t irBinarySize = 0;
|
||||
bool isSpirV = false;
|
||||
char *debugDataBinary = nullptr;
|
||||
size_t debugDataBinarySize = 0;
|
||||
|
||||
@@ -107,5 +120,6 @@ class OfflineCompiler {
|
||||
std::unique_ptr<OsLibrary> fclLib = nullptr;
|
||||
CIF::RAII::UPtr_t<CIF::CIFMain> fclMain = nullptr;
|
||||
CIF::RAII::UPtr_t<IGC::FclOclDeviceCtxTagOCL> fclDeviceCtx = nullptr;
|
||||
IGC::CodeType::CodeType_t preferredIntermediateRepresentation;
|
||||
};
|
||||
} // namespace OCLRT
|
||||
|
||||
@@ -72,8 +72,6 @@ cl_int CompilerInterface::build(
|
||||
highLevelCodeType = IGC::CodeType::oclC;
|
||||
if (useLlvmText == true) {
|
||||
intermediateCodeType = IGC::CodeType::llvmLl;
|
||||
} else {
|
||||
intermediateCodeType = IGC::CodeType::llvmBc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +88,10 @@ cl_int CompilerInterface::build(
|
||||
uint32_t numDevices = static_cast<uint32_t>(program.getNumDevices());
|
||||
for (uint32_t i = 0; i < numDevices; i++) {
|
||||
const auto &device = program.getDevice(i);
|
||||
UNRECOVERABLE_IF(intermediateCodeType == IGC::CodeType::undefined);
|
||||
if (intermediateCodeType == IGC::CodeType::undefined) {
|
||||
UNRECOVERABLE_IF(highLevelCodeType != IGC::CodeType::oclC);
|
||||
intermediateCodeType = getPreferredIntermediateRepresentation(device);
|
||||
}
|
||||
|
||||
bool binaryLoaded = false;
|
||||
std::string kernelFileHash;
|
||||
@@ -124,7 +125,7 @@ cl_int CompilerInterface::build(
|
||||
return CL_BUILD_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
program.storeLlvmBinary(fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw());
|
||||
program.storeIrBinary(fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw(), intermediateCodeType == IGC::CodeType::spirV);
|
||||
program.updateBuildLog(&device, fclOutput->GetBuildLog()->GetMemory<char>(), fclOutput->GetBuildLog()->GetSizeRaw());
|
||||
|
||||
fclOutput->GetOutput()->Retain(); // will be used as input to compiler
|
||||
@@ -186,14 +187,15 @@ cl_int CompilerInterface::compile(
|
||||
inType = IGC::CodeType::elf;
|
||||
if (useLlvmText == true) {
|
||||
outType = IGC::CodeType::llvmLl;
|
||||
} else {
|
||||
outType = IGC::CodeType::llvmBc;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t numDevices = static_cast<uint32_t>(program.getNumDevices());
|
||||
for (uint32_t i = 0; i < numDevices; i++) {
|
||||
const auto &device = program.getDevice(i);
|
||||
if (outType == IGC::CodeType::undefined) {
|
||||
outType = getPreferredIntermediateRepresentation(device);
|
||||
}
|
||||
|
||||
if (fromIntermediate == false) {
|
||||
auto fclSrc = CIF::Builtins::CreateConstBuffer(fclMain.get(), inputArgs.pInput, inputArgs.InputSize);
|
||||
@@ -214,13 +216,13 @@ cl_int CompilerInterface::compile(
|
||||
return CL_COMPILE_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
program.storeLlvmBinary(fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw());
|
||||
program.storeIrBinary(fclOutput->GetOutput()->GetMemory<char>(), fclOutput->GetOutput()->GetSizeRaw(), outType == IGC::CodeType::spirV);
|
||||
program.updateBuildLog(&device, fclOutput->GetBuildLog()->GetMemory<char>(), fclOutput->GetBuildLog()->GetSizeRaw());
|
||||
} else {
|
||||
char *pOutput;
|
||||
uint32_t OutputSize;
|
||||
program.getSource(pOutput, OutputSize);
|
||||
program.storeLlvmBinary(pOutput, OutputSize);
|
||||
program.storeIrBinary(pOutput, OutputSize, outType == IGC::CodeType::spirV);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,8 +251,8 @@ cl_int CompilerInterface::link(
|
||||
CIF::RAII::UPtr_t<IGC::OclTranslationOutputTagOCL> currOut;
|
||||
inSrc->Retain(); // shared with currSrc
|
||||
CIF::RAII::UPtr_t<CIF::Builtins::BufferSimple> currSrc(inSrc.get());
|
||||
|
||||
IGC::CodeType::CodeType_t translationChain[] = {IGC::CodeType::elf, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin};
|
||||
auto intermediateRepresentation = getPreferredIntermediateRepresentation(device);
|
||||
IGC::CodeType::CodeType_t translationChain[] = {IGC::CodeType::elf, intermediateRepresentation, IGC::CodeType::oclGenBin};
|
||||
constexpr size_t numTranslations = sizeof(translationChain) / sizeof(translationChain[0]);
|
||||
for (size_t ti = 1; ti < numTranslations; ti++) {
|
||||
IGC::CodeType::CodeType_t inType = translationChain[ti - 1];
|
||||
@@ -295,7 +297,8 @@ cl_int CompilerInterface::createLibrary(
|
||||
auto igcOptions = CIF::Builtins::CreateConstBuffer(igcMain.get(), inputArgs.pOptions, inputArgs.OptionsSize);
|
||||
auto igcInternalOptions = CIF::Builtins::CreateConstBuffer(igcMain.get(), inputArgs.pInternalOptions, inputArgs.InternalOptionsSize);
|
||||
|
||||
auto igcTranslationCtx = createIgcTranslationCtx(device, IGC::CodeType::elf, IGC::CodeType::llvmBc);
|
||||
auto intermediateRepresentation = getPreferredIntermediateRepresentation(device);
|
||||
auto igcTranslationCtx = createIgcTranslationCtx(device, IGC::CodeType::elf, intermediateRepresentation);
|
||||
|
||||
auto igcOutput = translate(igcTranslationCtx.get(), igcSrc.get(),
|
||||
igcOptions.get(), igcInternalOptions.get());
|
||||
@@ -309,7 +312,7 @@ cl_int CompilerInterface::createLibrary(
|
||||
return CL_BUILD_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
program.storeLlvmBinary(igcOutput->GetOutput()->GetMemory<char>(), igcOutput->GetOutput()->GetSizeRaw());
|
||||
program.storeIrBinary(igcOutput->GetOutput()->GetMemory<char>(), igcOutput->GetOutput()->GetSizeRaw(), intermediateRepresentation == IGC::CodeType::spirV);
|
||||
program.updateBuildLog(&device, igcOutput->GetBuildLog()->GetMemory<char>(), igcOutput->GetBuildLog()->GetSizeRaw());
|
||||
}
|
||||
|
||||
@@ -362,17 +365,17 @@ BinaryCache *CompilerInterface::replaceBinaryCache(BinaryCache *newCache) {
|
||||
return res;
|
||||
}
|
||||
|
||||
CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> CompilerInterface::createFclTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType) {
|
||||
IGC::FclOclDeviceCtxTagOCL *CompilerInterface::getFclDeviceCtx(const Device &device) {
|
||||
auto it = fclDeviceContexts.find(&device);
|
||||
if (it != fclDeviceContexts.end()) {
|
||||
return it->second->CreateTranslationCtx(inType, outType);
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
{
|
||||
auto ulock = this->lock();
|
||||
it = fclDeviceContexts.find(&device);
|
||||
if (it != fclDeviceContexts.end()) {
|
||||
return it->second->CreateTranslationCtx(inType, outType);
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
if (fclMain == nullptr) {
|
||||
@@ -388,12 +391,27 @@ CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> CompilerInterface::createFclT
|
||||
newDeviceCtx->SetOclApiVersion(device.getHardwareInfo().capabilityTable.clVersionSupport * 10);
|
||||
fclDeviceContexts[&device] = std::move(newDeviceCtx);
|
||||
|
||||
return fclDeviceContexts[&device].get();
|
||||
}
|
||||
}
|
||||
|
||||
IGC::CodeType::CodeType_t CompilerInterface::getPreferredIntermediateRepresentation(const Device &device) {
|
||||
return IGC::CodeType::llvmBc;
|
||||
}
|
||||
|
||||
CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> CompilerInterface::createFclTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType) {
|
||||
|
||||
auto deviceCtx = getFclDeviceCtx(device);
|
||||
if (deviceCtx == nullptr) {
|
||||
DEBUG_BREAK_IF(true); // could not create device context
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (fclBaseTranslationCtx == nullptr) {
|
||||
fclBaseTranslationCtx = fclDeviceContexts[&device]->CreateTranslationCtx(inType, outType);
|
||||
}
|
||||
|
||||
return fclDeviceContexts[&device]->CreateTranslationCtx(inType, outType);
|
||||
}
|
||||
return deviceCtx->CreateTranslationCtx(inType, outType);
|
||||
}
|
||||
|
||||
CIF::RAII::UPtr_t<IGC::IgcOclTranslationCtxTagOCL> CompilerInterface::createIgcTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType) {
|
||||
|
||||
@@ -117,6 +117,9 @@ class CompilerInterface {
|
||||
std::map<const Device *, fclDevCtxUptr> fclDeviceContexts;
|
||||
CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> fclBaseTranslationCtx = nullptr;
|
||||
|
||||
MOCKABLE_VIRTUAL IGC::FclOclDeviceCtxTagOCL *getFclDeviceCtx(const Device &device);
|
||||
MOCKABLE_VIRTUAL IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation(const Device &device);
|
||||
|
||||
MOCKABLE_VIRTUAL CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> createFclTranslationCtx(const Device &device,
|
||||
IGC::CodeType::CodeType_t inType,
|
||||
IGC::CodeType::CodeType_t outType);
|
||||
|
||||
@@ -96,7 +96,7 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
inputProgramsInternal.push_back(pInputProgObj);
|
||||
if ((pInputProgObj->llvmBinary == nullptr) || (pInputProgObj->llvmBinarySize == 0)) {
|
||||
if ((pInputProgObj->irBinary == nullptr) || (pInputProgObj->irBinarySize == 0)) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
@@ -107,8 +107,8 @@ cl_int Program::link(
|
||||
sectionNode.Type = CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY;
|
||||
}
|
||||
sectionNode.Flags = 0;
|
||||
sectionNode.pData = pInputProgObj->llvmBinary;
|
||||
sectionNode.DataSize = static_cast<unsigned int>(pInputProgObj->llvmBinarySize);
|
||||
sectionNode.pData = pInputProgObj->irBinary;
|
||||
sectionNode.DataSize = static_cast<unsigned int>(pInputProgObj->irBinarySize);
|
||||
|
||||
pElfWriter->addSection(§ionNode);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ cl_int Program::processElfBinary(
|
||||
case CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY:
|
||||
pElfReader->getSectionData(i, pSectionData, sectionDataSize);
|
||||
if (pSectionData && sectionDataSize) {
|
||||
storeLlvmBinary(pSectionData, sectionDataSize);
|
||||
storeIrBinary(pSectionData, sectionDataSize, isSpirV);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -169,7 +169,7 @@ cl_int Program::resolveProgramBinary() {
|
||||
case CL_PROGRAM_BINARY_TYPE_LIBRARY:
|
||||
headerType = CLElfLib::EH_TYPE_OPENCL_LIBRARY;
|
||||
|
||||
if (!llvmBinary || !llvmBinarySize) {
|
||||
if (!irBinary || !irBinarySize) {
|
||||
retVal = CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
@@ -177,7 +177,7 @@ cl_int Program::resolveProgramBinary() {
|
||||
case CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT:
|
||||
headerType = CLElfLib::EH_TYPE_OPENCL_OBJECTS;
|
||||
|
||||
if (!llvmBinary || !llvmBinarySize) {
|
||||
if (!irBinary || !irBinarySize) {
|
||||
retVal = CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
@@ -209,13 +209,13 @@ cl_int Program::resolveProgramBinary() {
|
||||
}
|
||||
if (headerType == CLElfLib::EH_TYPE_OPENCL_LIBRARY) {
|
||||
sectionNode.Name = "Intel(R) OpenCL LLVM Archive";
|
||||
sectionNode.pData = (char *)llvmBinary;
|
||||
sectionNode.DataSize = (uint32_t)llvmBinarySize;
|
||||
sectionNode.pData = (char *)irBinary;
|
||||
sectionNode.DataSize = (uint32_t)irBinarySize;
|
||||
elfRetVal = pElfWriter->addSection(§ionNode);
|
||||
} else {
|
||||
sectionNode.Name = "Intel(R) OpenCL LLVM Object";
|
||||
sectionNode.pData = (char *)llvmBinary;
|
||||
sectionNode.DataSize = (uint32_t)llvmBinarySize;
|
||||
sectionNode.pData = (char *)irBinary;
|
||||
sectionNode.DataSize = (uint32_t)irBinarySize;
|
||||
elfRetVal = pElfWriter->addSection(§ionNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ Program::Program(Context *context, bool isBuiltIn) : context(context), isBuiltIn
|
||||
elfBinarySize = 0;
|
||||
genBinary = nullptr;
|
||||
genBinarySize = 0;
|
||||
llvmBinary = nullptr;
|
||||
llvmBinarySize = 0;
|
||||
irBinary = nullptr;
|
||||
irBinarySize = 0;
|
||||
debugData = nullptr;
|
||||
debugDataSize = 0;
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
@@ -109,8 +109,8 @@ Program::~Program() {
|
||||
delete[] genBinary;
|
||||
genBinary = nullptr;
|
||||
|
||||
delete[] llvmBinary;
|
||||
llvmBinary = nullptr;
|
||||
delete[] irBinary;
|
||||
irBinary = nullptr;
|
||||
|
||||
delete[] debugData;
|
||||
debugData = nullptr;
|
||||
@@ -156,9 +156,9 @@ cl_int Program::createProgramFromBinary(
|
||||
isCreatedFromBinary = true;
|
||||
} else if (binaryVersion != iOpenCL::CURRENT_ICBE_VERSION) {
|
||||
// Version of compiler used to create program binary is invalid,
|
||||
// needs to recompile program binary from its LLVM (if available).
|
||||
// needs to recompile program binary from its IR (if available).
|
||||
// if recompile fails propagate error retVal from previous function
|
||||
if (!rebuildProgramFromLLVM()) {
|
||||
if (!rebuildProgramFromIr()) {
|
||||
retVal = CL_SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -167,26 +167,30 @@ cl_int Program::createProgramFromBinary(
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::rebuildProgramFromLLVM() {
|
||||
cl_int Program::rebuildProgramFromIr() {
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
size_t dataSize;
|
||||
char *pData = nullptr;
|
||||
CLElfLib::CElfWriter *pElfWriter = nullptr;
|
||||
|
||||
do {
|
||||
if (!Program::isValidLlvmBinary(llvmBinary, llvmBinarySize)) {
|
||||
if (!Program::isValidLlvmBinary(irBinary, irBinarySize)) {
|
||||
if ((!Program::isValidSpirvBinary(irBinary, irBinarySize))) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
isSpirV = true;
|
||||
}
|
||||
|
||||
pElfWriter = CLElfLib::CElfWriter::create(CLElfLib::EH_TYPE_OPENCL_OBJECTS, CLElfLib::EH_MACHINE_NONE, 0);
|
||||
UNRECOVERABLE_IF(pElfWriter == nullptr);
|
||||
|
||||
CLElfLib::SSectionNode sectionNode;
|
||||
sectionNode.Name = "";
|
||||
sectionNode.Type = CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY;
|
||||
sectionNode.Type = isSpirV ? CLElfLib::SH_TYPE_SPIRV : CLElfLib::SH_TYPE_OPENCL_LLVM_BINARY;
|
||||
sectionNode.Flags = 0;
|
||||
sectionNode.pData = llvmBinary;
|
||||
sectionNode.DataSize = static_cast<unsigned int>(llvmBinarySize);
|
||||
sectionNode.pData = irBinary;
|
||||
sectionNode.DataSize = static_cast<unsigned int>(irBinarySize);
|
||||
pElfWriter->addSection(§ionNode);
|
||||
|
||||
pElfWriter->resolveBinary(nullptr, dataSize);
|
||||
@@ -276,10 +280,12 @@ void Program::storeGenBinary(
|
||||
storeBinary(genBinary, genBinarySize, pSrc, srcSize);
|
||||
}
|
||||
|
||||
void Program::storeLlvmBinary(
|
||||
void Program::storeIrBinary(
|
||||
const void *pSrc,
|
||||
const size_t srcSize) {
|
||||
storeBinary(llvmBinary, llvmBinarySize, pSrc, srcSize);
|
||||
const size_t srcSize,
|
||||
bool isSpirV) {
|
||||
storeBinary(irBinary, irBinarySize, pSrc, srcSize);
|
||||
this->isSpirV = isSpirV;
|
||||
}
|
||||
|
||||
void Program::storeDebugData(
|
||||
|
||||
@@ -185,7 +185,7 @@ class Program : public BaseObject<_cl_program> {
|
||||
return this->genBinary;
|
||||
}
|
||||
|
||||
void storeLlvmBinary(const void *pSrc, const size_t srcSize);
|
||||
void storeIrBinary(const void *pSrc, const size_t srcSize, bool isSpirV);
|
||||
|
||||
void storeDebugData(const void *pSrc, const size_t srcSize);
|
||||
void processDebugData();
|
||||
@@ -264,7 +264,7 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
cl_int parseProgramScopePatchList();
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int rebuildProgramFromLLVM();
|
||||
MOCKABLE_VIRTUAL cl_int rebuildProgramFromIr();
|
||||
|
||||
cl_int parsePatchList(KernelInfo &pKernelInfo);
|
||||
|
||||
@@ -295,8 +295,8 @@ class Program : public BaseObject<_cl_program> {
|
||||
char* genBinary;
|
||||
size_t genBinarySize;
|
||||
|
||||
char* llvmBinary;
|
||||
size_t llvmBinarySize;
|
||||
char* irBinary;
|
||||
size_t irBinarySize;
|
||||
|
||||
char* debugData;
|
||||
size_t debugDataSize;
|
||||
|
||||
@@ -277,8 +277,8 @@ TEST_F(CompilerInterfaceTest, CompileClToIsaWithOptions) {
|
||||
gEnvironment->igcPopDebugVars();
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, CompileClToLLVM) {
|
||||
// compile only from .cl to LLVM
|
||||
TEST_F(CompilerInterfaceTest, CompileClToIr) {
|
||||
// compile only from .cl to IR
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = clFiles + "copybuffer.elf";
|
||||
gEnvironment->fclPushDebugVars(fclDebugVars);
|
||||
@@ -325,8 +325,8 @@ TEST_F(CompilerInterfaceTest, whenFclTranslatorReturnsNullptrThenCompileFailsGra
|
||||
gEnvironment->fclPopDebugVars();
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, CompileClToLLVMCompileFailure) {
|
||||
// compile only from .cl to LLVM
|
||||
TEST_F(CompilerInterfaceTest, CompileClToIrCompileFailure) {
|
||||
// compile only from .cl to IR
|
||||
MockCompilerDebugVars fclDebugVars;
|
||||
fclDebugVars.fileName = "../copybuffer.elf";
|
||||
fclDebugVars.forceBuildFailure = true;
|
||||
@@ -338,7 +338,7 @@ TEST_F(CompilerInterfaceTest, CompileClToLLVMCompileFailure) {
|
||||
gEnvironment->fclPopDebugVars();
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, LinkLLVMLinkFailure) {
|
||||
TEST_F(CompilerInterfaceTest, LinkIrLinkFailure) {
|
||||
// link only .ll to gen ISA
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = "../copybuffer.ll";
|
||||
@@ -351,7 +351,7 @@ TEST_F(CompilerInterfaceTest, LinkLLVMLinkFailure) {
|
||||
gEnvironment->igcPopDebugVars();
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, LinkLLVM) {
|
||||
TEST_F(CompilerInterfaceTest, LinkIr) {
|
||||
// link only from .ll to gen ISA
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = clFiles + "copybuffer.ll";
|
||||
@@ -399,7 +399,7 @@ TEST_F(CompilerInterfaceTest, whenTranslateReturnsNullptrThenLinkFailsGracefully
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, CreateLibFailure) {
|
||||
// create library from .ll to LLVM
|
||||
// create library from .ll to IR
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = "../copybuffer.ll";
|
||||
igcDebugVars.forceBuildFailure = true;
|
||||
@@ -412,7 +412,7 @@ TEST_F(CompilerInterfaceTest, CreateLibFailure) {
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, CreateLib) {
|
||||
// create library from .ll to LLVM
|
||||
// create library from .ll to IR
|
||||
MockCompilerDebugVars igcDebugVars;
|
||||
igcDebugVars.fileName = clFiles + "copybuffer.ll";
|
||||
gEnvironment->igcPushDebugVars(igcDebugVars);
|
||||
@@ -683,13 +683,13 @@ struct LockListener {
|
||||
|
||||
TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenDeviceCtxIsNotAvailableThenCreateNewDeviceCtxAndUseItToReturnValidTranslationCtx) {
|
||||
auto device = this->pContext->getDevice(0);
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_NE(nullptr, ret.get());
|
||||
auto firstBaseCtx = this->pCompilerInterface->getFclBaseTranslationCtx();
|
||||
EXPECT_NE(nullptr, firstBaseCtx);
|
||||
|
||||
MockDevice md{device->getHardwareInfo()};
|
||||
auto ret2 = this->pCompilerInterface->createFclTranslationCtx(md, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret2 = this->pCompilerInterface->createFclTranslationCtx(md, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_NE(nullptr, ret2.get());
|
||||
EXPECT_EQ(firstBaseCtx, this->pCompilerInterface->getFclBaseTranslationCtx());
|
||||
}
|
||||
@@ -698,7 +698,7 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewFclTranslationCtxWhenDeviceCtxIs
|
||||
auto device = this->pContext->getDevice(0);
|
||||
auto deviceCtx = CIF::RAII::UPtr(new MockCompilerDeviceCtx<MockFclOclDeviceCtx, MockFclOclTranslationCtx>);
|
||||
this->pCompilerInterface->setFclDeviceCtx(*device, deviceCtx.get());
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_NE(nullptr, ret.get());
|
||||
EXPECT_EQ(deviceCtx->returned, ret.get());
|
||||
}
|
||||
@@ -711,7 +711,7 @@ TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewFclTranslationContex
|
||||
this->pCompilerInterface->lockListenerData = &listenerData;
|
||||
this->pCompilerInterface->lockListener = ListenerT::Listener;
|
||||
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_NE(nullptr, ret.get());
|
||||
ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size());
|
||||
ASSERT_NE(this->pCompilerInterface->getFclDeviceContexts().end(),
|
||||
@@ -725,9 +725,9 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewTranslationCtxWhenFclMainIsNotAv
|
||||
|
||||
auto device = this->pContext->getDevice(0);
|
||||
MockCompilerInterface tempCompilerInterface;
|
||||
auto retFcl = tempCompilerInterface.createFclTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retFcl = tempCompilerInterface.createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_EQ(nullptr, retFcl);
|
||||
auto retIgc = tempCompilerInterface.createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retIgc = tempCompilerInterface.createIgcTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_EQ(nullptr, retIgc);
|
||||
|
||||
OCLRT::failCreateCifMain = false;
|
||||
@@ -741,10 +741,10 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewTranslationCtxWhenCouldNotCreate
|
||||
OCLRT::MockCIFMain::setGlobalCreatorFunc<OCLRT::MockFclOclDeviceCtx>(nullptr);
|
||||
OCLRT::MockCIFMain::setGlobalCreatorFunc<OCLRT::MockIgcOclDeviceCtx>(nullptr);
|
||||
|
||||
auto retFcl = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retFcl = pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_EQ(nullptr, retFcl);
|
||||
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||
EXPECT_EQ(nullptr, retIgc);
|
||||
|
||||
OCLRT::MockCIFMain::setGlobalCreatorFunc<OCLRT::MockFclOclDeviceCtx>(befFclMock);
|
||||
@@ -755,7 +755,7 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewIgcTranslationCtxWhenDeviceCtxIs
|
||||
auto device = this->pContext->getDevice(0);
|
||||
auto deviceCtx = CIF::RAII::UPtr(new MockCompilerDeviceCtx<MockIgcOclDeviceCtx, MockIgcOclTranslationCtx>);
|
||||
this->pCompilerInterface->setIgcDeviceCtx(*device, deviceCtx.get());
|
||||
auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin);
|
||||
EXPECT_NE(nullptr, ret.get());
|
||||
EXPECT_EQ(deviceCtx->returned, ret.get());
|
||||
}
|
||||
@@ -768,7 +768,7 @@ TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewIgcTranslationContex
|
||||
this->pCompilerInterface->lockListenerData = &listenerData;
|
||||
this->pCompilerInterface->lockListener = ListenerT::Listener;
|
||||
|
||||
auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = this->pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin);
|
||||
EXPECT_NE(nullptr, ret.get());
|
||||
ASSERT_EQ(1U, this->pCompilerInterface->getIgcDeviceContexts().size());
|
||||
ASSERT_NE(this->pCompilerInterface->getIgcDeviceContexts().end(),
|
||||
@@ -791,7 +791,7 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewIgcTranslationCtxWhenCouldNotPop
|
||||
debugVars.failCreateGtSystemInfoInterface = (i & (1 << 1)) != 0;
|
||||
setIgcDebugVars(debugVars);
|
||||
|
||||
auto ret = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto ret = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin);
|
||||
EXPECT_EQ(nullptr, ret);
|
||||
}
|
||||
|
||||
@@ -800,7 +800,7 @@ TEST_F(CompilerInterfaceTest, GivenRequestForNewIgcTranslationCtxWhenCouldNotPop
|
||||
|
||||
TEST_F(CompilerInterfaceTest, givenNoDbgKeyForceUseDifferentPlatformWhenRequestForNewTranslationCtxThenUseDefaultPlatform) {
|
||||
auto device = this->pContext->getDevice(0);
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin);
|
||||
EXPECT_NE(nullptr, retIgc);
|
||||
IGC::IgcOclDeviceCtxTagOCL *devCtx = pCompilerInterface->peekIgcDeviceCtx(device);
|
||||
auto igcPlatform = devCtx->GetPlatformHandle();
|
||||
@@ -822,7 +822,7 @@ TEST_F(CompilerInterfaceTest, givenDbgKeyForceUseDifferentPlatformWhenRequestFor
|
||||
DebugManager.flags.ForceCompilerUsePlatform.set(dbgPlatformString);
|
||||
|
||||
auto device = this->pContext->getDevice(0);
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::llvmBc, IGC::CodeType::oclGenBin);
|
||||
auto retIgc = pCompilerInterface->createIgcTranslationCtx(*device, IGC::CodeType::spirV, IGC::CodeType::oclGenBin);
|
||||
EXPECT_NE(nullptr, retIgc);
|
||||
IGC::IgcOclDeviceCtxTagOCL *devCtx = pCompilerInterface->peekIgcDeviceCtx(device);
|
||||
auto igcPlatform = devCtx->GetPlatformHandle();
|
||||
|
||||
@@ -76,6 +76,11 @@ struct MockCIFMain : MockCIF<CIF::CIFMain> {
|
||||
globalCreators[InterfaceT::GetInterfaceId()] = func;
|
||||
}
|
||||
|
||||
template <typename InterfaceT>
|
||||
void setDefaultCreatorFunc(CreatorFuncT func) {
|
||||
defaultCreators[InterfaceT::GetInterfaceId()] = func;
|
||||
}
|
||||
|
||||
template <typename InterfaceT>
|
||||
static CreatorFuncT getGlobalCreatorFunc() {
|
||||
auto it = globalCreators.find(InterfaceT::GetInterfaceId());
|
||||
|
||||
@@ -354,6 +354,7 @@ class MockCompilerInterface : public CompilerInterface {
|
||||
SipKernelType requestedSipKernel = SipKernelType::COUNT;
|
||||
|
||||
IGC::IgcOclDeviceCtxTagOCL *peekIgcDeviceCtx(Device *device) { return igcDeviceContexts[device].get(); }
|
||||
using CompilerInterface::useLlvmText;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
||||
@@ -98,10 +98,16 @@ class MockProgram : public Program {
|
||||
void SetGlobalVariableTotalSize(size_t globalVarSize) { globalVarTotalSize = globalVarSize; }
|
||||
void SetDevice(Device *pDev) { pDevice = pDev; }
|
||||
|
||||
char *GetLLVMBinary() { return llvmBinary; }
|
||||
size_t GetLLVMBinarySize() { return llvmBinarySize; }
|
||||
void SetLLVMBinary(char *ptr) { llvmBinary = ptr; }
|
||||
void SetLLVMBinarySize(size_t bsz) { llvmBinarySize = bsz; }
|
||||
char *GetIrBinary() { return irBinary; }
|
||||
size_t GetIrBinarySize() { return irBinarySize; }
|
||||
void SetIrBinary(char *ptr, bool isSpirv) {
|
||||
irBinary = ptr;
|
||||
this->isSpirV = isSpirV;
|
||||
}
|
||||
void SetIrBinarySize(size_t bsz, bool isSpirv) {
|
||||
irBinarySize = bsz;
|
||||
this->isSpirV = isSpirV;
|
||||
}
|
||||
|
||||
uint64_t getHash();
|
||||
void setAllowNonUniform(bool allow) {
|
||||
|
||||
@@ -28,8 +28,15 @@ namespace OCLRT {
|
||||
|
||||
class MockOfflineCompiler : public OfflineCompiler {
|
||||
public:
|
||||
using OfflineCompiler::generateFilePathForIr;
|
||||
using OfflineCompiler::generateOptsSuffix;
|
||||
using OfflineCompiler::inputFileLlvm;
|
||||
using OfflineCompiler::isSpirV;
|
||||
using OfflineCompiler::options;
|
||||
using OfflineCompiler::outputDirectory;
|
||||
using OfflineCompiler::outputFile;
|
||||
using OfflineCompiler::useLlvmText;
|
||||
using OfflineCompiler::useOptionsSuffix;
|
||||
|
||||
MockOfflineCompiler() : OfflineCompiler() {
|
||||
}
|
||||
|
||||
@@ -731,4 +731,64 @@ TEST(OfflineCompilerTest, givenNonExistingFilenameWhenUsedToReadOptionsThenReadO
|
||||
EXPECT_FALSE(result);
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenEmptyDirectoryWhenGenerateFilePathIsCalledThenTrailingSlashIsNotAppended) {
|
||||
std::string path = generateFilePath("", "a", "b");
|
||||
EXPECT_STREQ("ab", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenNonEmptyDirectoryWithTrailingSlashWhenGenerateFilePathIsCalledThenAdditionalTrailingSlashIsNotAppended) {
|
||||
std::string path = generateFilePath("d/", "a", "b");
|
||||
EXPECT_STREQ("d/ab", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenNonEmptyDirectoryWithoutTrailingSlashWhenGenerateFilePathIsCalledThenTrailingSlashIsAppended) {
|
||||
std::string path = generateFilePath("d", "a", "b");
|
||||
EXPECT_STREQ("d/ab", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenSpirvPathWhenGenerateFilePathForIrIsCalledThenProperExtensionIsReturned) {
|
||||
MockOfflineCompiler compiler;
|
||||
compiler.isSpirV = true;
|
||||
compiler.outputDirectory = "d";
|
||||
std::string path = compiler.generateFilePathForIr("a");
|
||||
EXPECT_STREQ("d/a.spv", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenLlvmBcPathWhenGenerateFilePathForIrIsCalledThenProperExtensionIsReturned) {
|
||||
MockOfflineCompiler compiler;
|
||||
compiler.isSpirV = false;
|
||||
compiler.outputDirectory = "d";
|
||||
std::string path = compiler.generateFilePathForIr("a");
|
||||
EXPECT_STREQ("d/a.bc", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenLlvmTextPathWhenGenerateFilePathForIrIsCalledThenProperExtensionIsReturned) {
|
||||
MockOfflineCompiler compiler;
|
||||
compiler.isSpirV = false;
|
||||
compiler.useLlvmText = true;
|
||||
compiler.outputDirectory = "d";
|
||||
std::string path = compiler.generateFilePathForIr("a");
|
||||
EXPECT_STREQ("d/a.ll", path.c_str());
|
||||
|
||||
compiler.isSpirV = true;
|
||||
path = compiler.generateFilePathForIr("a");
|
||||
EXPECT_STREQ("d/a.ll", path.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenDisabledOptsSuffixWhenGenerateOptsSuffixIsCalledThenEmptyStringIsReturned) {
|
||||
MockOfflineCompiler compiler;
|
||||
compiler.options = "A B C";
|
||||
compiler.useOptionsSuffix = false;
|
||||
std::string suffix = compiler.generateOptsSuffix();
|
||||
EXPECT_STREQ("", suffix.c_str());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenEnabledOptsSuffixWhenGenerateOptsSuffixIsCalledThenEscapedStringIsReturned) {
|
||||
MockOfflineCompiler compiler;
|
||||
compiler.options = "A B C";
|
||||
compiler.useOptionsSuffix = true;
|
||||
std::string suffix = compiler.generateOptsSuffix();
|
||||
EXPECT_STREQ("A_B_C", suffix.c_str());
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
||||
|
||||
@@ -77,11 +77,12 @@ TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
|
||||
isSpirV = Program::isValidSpirvBinary(spirvBinary, spirvBinarySize);
|
||||
EXPECT_TRUE(isSpirV);
|
||||
|
||||
//clCompileProgram => SPIR-V stored as LLVM binary
|
||||
storeLlvmBinary(spirvBinary, spirvBinarySize);
|
||||
//clCompileProgram => SPIR-V stored as IR binary
|
||||
storeIrBinary(spirvBinary, spirvBinarySize, true);
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
EXPECT_NE(nullptr, llvmBinary);
|
||||
EXPECT_NE(0u, llvmBinarySize);
|
||||
EXPECT_NE(nullptr, irBinary);
|
||||
EXPECT_NE(0u, irBinarySize);
|
||||
EXPECT_TRUE(isSpirV);
|
||||
|
||||
//clGetProgramInfo => SPIR-V stored as ELF binary
|
||||
cl_int retVal = resolveProgramBinary();
|
||||
@@ -142,11 +143,11 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe
|
||||
|
||||
size_t optionsSize = strlen(options.c_str()) + 1;
|
||||
auto pTmpGenBinary = new char[genBinarySize];
|
||||
auto pTmpLlvmBinary = new char[llvmBinarySize];
|
||||
auto pTmpIrBinary = new char[irBinarySize];
|
||||
auto pTmpOptions = new char[optionsSize];
|
||||
|
||||
memcpy_s(pTmpGenBinary, genBinarySize, genBinary, genBinarySize);
|
||||
memcpy_s(pTmpLlvmBinary, llvmBinarySize, llvmBinary, llvmBinarySize);
|
||||
memcpy_s(pTmpIrBinary, irBinarySize, irBinary, irBinarySize);
|
||||
memcpy_s(pTmpOptions, optionsSize, options.c_str(), optionsSize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
@@ -159,11 +160,11 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe
|
||||
retVal = resolveProgramBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pTmpGenBinary, genBinary, genBinarySize));
|
||||
EXPECT_EQ(0, memcmp(pTmpLlvmBinary, llvmBinary, llvmBinarySize));
|
||||
EXPECT_EQ(0, memcmp(pTmpIrBinary, irBinary, irBinarySize));
|
||||
EXPECT_EQ(0, memcmp(pTmpOptions, options.c_str(), optionsSize));
|
||||
|
||||
delete[] pTmpGenBinary;
|
||||
delete[] pTmpLlvmBinary;
|
||||
delete[] pTmpIrBinary;
|
||||
delete[] pTmpOptions;
|
||||
|
||||
deleteDataReadFromFile(pBinary);
|
||||
|
||||
@@ -1249,18 +1249,19 @@ TEST_P(ProgramFromSourceTest, CreateWithSource_Link) {
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// fail linking - code to be linked does not exist
|
||||
char *pLLVMBin = p->GetLLVMBinary();
|
||||
size_t LLVMBinSize = p->GetLLVMBinarySize();
|
||||
p->SetLLVMBinary(nullptr);
|
||||
bool isSpirvTmp = p->getIsSpirV();
|
||||
char *pIrBin = p->GetIrBinary();
|
||||
size_t irBinSize = p->GetIrBinarySize();
|
||||
p->SetIrBinary(nullptr, false);
|
||||
retVal = pProgram->link(0, nullptr, nullptr, 1, &program, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
|
||||
p->SetLLVMBinary(pLLVMBin);
|
||||
p->SetIrBinary(pIrBin, isSpirvTmp);
|
||||
|
||||
// fail linking - size of code to be linked is == 0
|
||||
p->SetLLVMBinarySize(0);
|
||||
p->SetIrBinarySize(0, isSpirvTmp);
|
||||
retVal = pProgram->link(0, nullptr, nullptr, 1, &program, nullptr, nullptr);
|
||||
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
|
||||
p->SetLLVMBinarySize(LLVMBinSize);
|
||||
p->SetIrBinarySize(irBinSize, isSpirvTmp);
|
||||
|
||||
// fail linking - any link error (here caused by specifying unrecognized option)
|
||||
retVal = pProgram->link(0, nullptr, "-invalid-option", 1, &program, nullptr, nullptr);
|
||||
@@ -1629,7 +1630,7 @@ TEST(ProgramFromBinaryTests, givenBinaryWithInvalidICBEThenErrorIsReturned) {
|
||||
class FailProgram : public Program {
|
||||
public:
|
||||
FailProgram(Context *context, bool isBuiltIn = false) : Program(context, isBuiltIn) {}
|
||||
cl_int rebuildProgramFromLLVM() override {
|
||||
cl_int rebuildProgramFromIr() override {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
// make method visible
|
||||
@@ -2183,8 +2184,8 @@ TEST_F(ProgramTests, ValidBinaryWithIGCVersionEqual0) {
|
||||
MyProgram3(){};
|
||||
cl_int createProgramFromBinaryPub(const void *pBinary, size_t binarySize) { return createProgramFromBinary(pBinary, binarySize); }
|
||||
void setDevice(Device *device) { pDevice = device; }
|
||||
cl_int rebuildProgramFromLLVMPub() { return rebuildProgramFromLLVM(); }
|
||||
char *getLlvmBinary() { return llvmBinary; };
|
||||
using Program::rebuildProgramFromIr;
|
||||
char *getIrBinary() { return irBinary; };
|
||||
};
|
||||
|
||||
cl_int retVal;
|
||||
@@ -2204,7 +2205,7 @@ TEST_F(ProgramTests, ValidBinaryWithIGCVersionEqual0) {
|
||||
EXPECT_NE(0u, binarySize);
|
||||
|
||||
// Find its OpenCL program data and mark that the data were created with unknown compiler version,
|
||||
// which means that the program has to be rebuild from its LLVM binary
|
||||
// which means that the program has to be rebuild from its IR binary
|
||||
CLElfLib::CElfReader *pElfReader = nullptr;
|
||||
pElfReader = CLElfLib::CElfReader::create((const char *)pBinary, binarySize);
|
||||
EXPECT_NE(nullptr, pElfReader);
|
||||
@@ -2234,12 +2235,11 @@ TEST_F(ProgramTests, ValidBinaryWithIGCVersionEqual0) {
|
||||
retVal = pProgram->createProgramFromBinaryPub(pBinary, binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Find its LLVM binary section and modify its header magic,
|
||||
// then ask to rebuild program from its LLVM binary - it should fail
|
||||
char *pLlvmBinary = pProgram->getLlvmBinary();
|
||||
EXPECT_EQ(*pLlvmBinary, 'B');
|
||||
(*pLlvmBinary)--;
|
||||
retVal = pProgram->rebuildProgramFromLLVMPub();
|
||||
// Get IR binary and modify its header magic,
|
||||
// then ask to rebuild program from its IR binary - it should fail
|
||||
char *pIrBinary = pProgram->getIrBinary();
|
||||
(*pIrBinary)--;
|
||||
retVal = pProgram->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
|
||||
|
||||
// Cleanup
|
||||
@@ -2256,7 +2256,7 @@ TEST_F(ProgramTests, RebuildBinaryButNoCompilerInterface) {
|
||||
|
||||
cl_int createProgramFromBinaryPub(const void *pBinary, size_t binarySize) { return createProgramFromBinary(pBinary, binarySize); }
|
||||
void setDevice(Device *device) { pDevice = device; }
|
||||
cl_int rebuildProgramFromLLVMPub() { return rebuildProgramFromLLVM(); }
|
||||
using Program::rebuildProgramFromIr;
|
||||
|
||||
protected:
|
||||
CompilerInterface *getCompilerInterface() const override { return nullptr; }
|
||||
@@ -2279,8 +2279,8 @@ TEST_F(ProgramTests, RebuildBinaryButNoCompilerInterface) {
|
||||
cl_int retVal = pProgram->createProgramFromBinaryPub(pBinary, binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Ask to rebuild program from its LLVM binary - it should fail (no Compiler Interface)
|
||||
retVal = pProgram->rebuildProgramFromLLVMPub();
|
||||
// Ask to rebuild program from its IR binary - it should fail (no Compiler Interface)
|
||||
retVal = pProgram->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal);
|
||||
|
||||
// Cleanup
|
||||
@@ -2303,7 +2303,7 @@ TEST_F(ProgramTests, RebuildBinaryWithRebuildError) {
|
||||
|
||||
cl_int createProgramFromBinaryPub(const void *pBinary, size_t binarySize) { return createProgramFromBinary(pBinary, binarySize); }
|
||||
void setDevice(Device *device) { pDevice = device; }
|
||||
cl_int rebuildProgramFromLLVMPub() { return rebuildProgramFromLLVM(); }
|
||||
using Program::rebuildProgramFromIr;
|
||||
void releaseCompilerInterface() {
|
||||
delete cip;
|
||||
cip = nullptr;
|
||||
@@ -2334,8 +2334,8 @@ TEST_F(ProgramTests, RebuildBinaryWithRebuildError) {
|
||||
cl_int retVal = pProgram->createProgramFromBinaryPub(pBinary, binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Ask to rebuild program from its LLVM binary - it should fail (linking error)
|
||||
retVal = pProgram->rebuildProgramFromLLVMPub();
|
||||
// Ask to rebuild program from its IR binary - it should fail (linking error)
|
||||
retVal = pProgram->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_LINK_PROGRAM_FAILURE, retVal);
|
||||
|
||||
// Cleanup
|
||||
@@ -2448,7 +2448,7 @@ TEST_F(ProgramTests, RebuildBinaryWithProcessGenBinaryError) {
|
||||
MyProgram3(){};
|
||||
cl_int createProgramFromBinaryPub(const void *pBinary, size_t binarySize) { return createProgramFromBinary(pBinary, binarySize); }
|
||||
void setDevice(Device *device) { pDevice = device; }
|
||||
cl_int rebuildProgramFromLLVMPub() { return rebuildProgramFromLLVM(); }
|
||||
using Program::rebuildProgramFromIr;
|
||||
cl_int processGenBinary() override { return CL_INVALID_BINARY; }
|
||||
};
|
||||
|
||||
@@ -2472,8 +2472,8 @@ TEST_F(ProgramTests, RebuildBinaryWithProcessGenBinaryError) {
|
||||
retVal = pProgram->createProgramFromBinaryPub(pBinary, binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Ask to rebuild program from its LLVM binary - it should fail (simulated invalid binary)
|
||||
retVal = pProgram->rebuildProgramFromLLVMPub();
|
||||
// Ask to rebuild program from its IR binary - it should fail (simulated invalid binary)
|
||||
retVal = pProgram->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
|
||||
// Cleanup
|
||||
@@ -2694,10 +2694,10 @@ struct CreateProgramFromBinaryMock : MockProgram {
|
||||
|
||||
cl_int createProgramFromBinary(const void *pBinary,
|
||||
size_t binarySize) override {
|
||||
this->llvmBinary = new char[binarySize];
|
||||
this->llvmBinarySize = binarySize;
|
||||
this->irBinary = new char[binarySize];
|
||||
this->irBinarySize = binarySize;
|
||||
this->isSpirV = spirv;
|
||||
memcpy_s(this->llvmBinary, binarySize, pBinary, binarySize);
|
||||
memcpy_s(this->irBinary, binarySize, pBinary, binarySize);
|
||||
return ErrCodeToReturn;
|
||||
}
|
||||
};
|
||||
@@ -2976,3 +2976,103 @@ TEST(ProgramDestructionTests, givenProgramUsingDeviceWhenItIsDestroyedAfterPlatf
|
||||
context->decRefInternal();
|
||||
pProgram->decRefInternal();
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, givenCompilerInterfaceWhenCompileIsCalledThenProperIntermediateRepresentationTypeIsUsed) {
|
||||
struct SmallMockCompilerInterface : MockCompilerInterface {
|
||||
using CompilerInterface::initialize;
|
||||
using CompilerInterface::useLlvmText;
|
||||
IGC::CodeType::CodeType_t intermediateRepresentation;
|
||||
IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation(const Device &device) override {
|
||||
return intermediateRepresentation;
|
||||
}
|
||||
};
|
||||
|
||||
struct SmallMockProgram : public Program {};
|
||||
using ProgramAutoPtr = std::unique_ptr<SmallMockProgram, void (*)(SmallMockProgram *)>;
|
||||
|
||||
auto device = castToObject<Device>(pContext->getDevice(0));
|
||||
|
||||
TranslationArgs input = {};
|
||||
char inputData = 0;
|
||||
input.pInput = &inputData;
|
||||
input.InputSize = 1;
|
||||
|
||||
SmallMockCompilerInterface compilerInterface;
|
||||
auto compilerMain = new MockCIFMain();
|
||||
compilerInterface.overrideGlobalCompilerInterface();
|
||||
compilerInterface.SetFclMain(compilerMain);
|
||||
compilerMain->Retain();
|
||||
compilerInterface.SetIgcMain(compilerMain);
|
||||
compilerMain->setDefaultCreatorFunc<OCLRT::MockIgcOclDeviceCtx>(OCLRT::MockIgcOclDeviceCtx::Create);
|
||||
compilerMain->setDefaultCreatorFunc<OCLRT::MockFclOclDeviceCtx>(OCLRT::MockFclOclDeviceCtx::Create);
|
||||
|
||||
compilerInterface.useLlvmText = true;
|
||||
ProgramAutoPtr programLlvmText{new SmallMockProgram(), [](SmallMockProgram *p) { p->release(); }};
|
||||
programLlvmText->setDevice(device);
|
||||
compilerInterface.intermediateRepresentation = IGC::CodeType::spirV;
|
||||
compilerInterface.compile(*programLlvmText, input);
|
||||
EXPECT_FALSE(programLlvmText->getIsSpirV());
|
||||
|
||||
compilerInterface.useLlvmText = false;
|
||||
ProgramAutoPtr programSpirV{new SmallMockProgram(), [](SmallMockProgram *p) { p->release(); }};
|
||||
programSpirV->setDevice(device);
|
||||
compilerInterface.intermediateRepresentation = IGC::CodeType::spirV;
|
||||
compilerInterface.compile(*programSpirV, input);
|
||||
EXPECT_TRUE(programSpirV->getIsSpirV());
|
||||
|
||||
ProgramAutoPtr programLlvmBc{new SmallMockProgram(), [](SmallMockProgram *p) { p->release(); }};
|
||||
programLlvmBc->setDevice(device);
|
||||
compilerInterface.intermediateRepresentation = IGC::CodeType::llvmBc;
|
||||
compilerInterface.compile(*programLlvmBc, input);
|
||||
EXPECT_FALSE(programLlvmBc->getIsSpirV());
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, givenProgramWithSpirvWhenRebuildProgramIsCalledThenSpirvPathIsTaken) {
|
||||
struct SmallMockProgram : public Program {
|
||||
using Program::rebuildProgramFromIr;
|
||||
};
|
||||
using ProgramAutoPtr = std::unique_ptr<SmallMockProgram, void (*)(SmallMockProgram *)>;
|
||||
|
||||
auto device = castToObject<Device>(pContext->getDevice(0));
|
||||
|
||||
MockCompilerInterface compilerInterface;
|
||||
auto compilerMain = new MockCIFMain();
|
||||
compilerInterface.overrideGlobalCompilerInterface();
|
||||
compilerInterface.SetFclMain(compilerMain);
|
||||
compilerMain->Retain();
|
||||
compilerInterface.SetIgcMain(compilerMain);
|
||||
compilerMain->setDefaultCreatorFunc<OCLRT::MockIgcOclDeviceCtx>(OCLRT::MockIgcOclDeviceCtx::Create);
|
||||
compilerMain->setDefaultCreatorFunc<OCLRT::MockFclOclDeviceCtx>(OCLRT::MockFclOclDeviceCtx::Create);
|
||||
|
||||
std::string receivedInput;
|
||||
MockCompilerDebugVars debugVars = {};
|
||||
debugVars.receivedInput = &receivedInput;
|
||||
debugVars.forceBuildFailure = true;
|
||||
gEnvironment->igcPushDebugVars(debugVars);
|
||||
std::unique_ptr<void, void (*)(void *)> igcDebugVarsAutoPop{&gEnvironment, [](void *) { gEnvironment->igcPopDebugVars(); }};
|
||||
|
||||
ProgramAutoPtr program{new SmallMockProgram(), [](SmallMockProgram *p) { p->release(); }};
|
||||
program->setDevice(device);
|
||||
uint32_t spirv[16] = {0x03022307, 0x23471113, 0x17192329};
|
||||
program->storeIrBinary(spirv, sizeof(spirv), true);
|
||||
auto buildRet = program->rebuildProgramFromIr();
|
||||
EXPECT_NE(CL_SUCCESS, buildRet);
|
||||
|
||||
using namespace CLElfLib;
|
||||
using AutoElfReader = std::unique_ptr<CElfReader, void (*)(CElfReader *)>;
|
||||
AutoElfReader elfReader{CElfReader::create(receivedInput.data(), receivedInput.size()), [](CElfReader *r) { CElfReader::destroy(r); }};
|
||||
const SElf64SectionHeader *spvSection = nullptr;
|
||||
char *spvSectionData = nullptr;
|
||||
size_t spvSectionDataSize = 0;
|
||||
for (uint32_t i = 0; i < elfReader->getElfHeader()->NumSectionHeaderEntries; i++) {
|
||||
const SElf64SectionHeader *section = elfReader->getSectionHeader(i);
|
||||
if (section->Type == CLElfLib::SH_TYPE_SPIRV) {
|
||||
EXPECT_EQ(nullptr, spvSection);
|
||||
elfReader->getSectionData(i, spvSectionData, spvSectionDataSize);
|
||||
spvSection = section;
|
||||
}
|
||||
}
|
||||
ASSERT_NE(nullptr, spvSection);
|
||||
EXPECT_EQ(sizeof(spirv), spvSectionDataSize);
|
||||
EXPECT_EQ(0, memcmp(spirv, spvSectionData, spvSectionDataSize));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user