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:
Chodor, Jaroslaw
2018-06-18 14:36:23 +02:00
committed by sys_ocldev
parent 30777275d4
commit b490a1331b
17 changed files with 372 additions and 159 deletions

2
Jenkinsfile vendored
View File

@@ -1,4 +1,4 @@
#!groovy
neoDependenciesRev='782940-1037'
strategy='EQUAL'
allowedCD=298
allowedCD=297

View File

@@ -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(&sectionNode);
}
@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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(&sectionNode);
}

View File

@@ -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(&sectionNode);
} 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(&sectionNode);
}
}

View File

@@ -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(&sectionNode);
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(

View File

@@ -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;

View File

@@ -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();

View File

@@ -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());

View File

@@ -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 <>

View File

@@ -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) {

View File

@@ -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() {
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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));
}