From 46b78812ccf8d3cc8d0d76647e07831d2994a7a6 Mon Sep 17 00:00:00 2001 From: Mateusz Hoppe Date: Mon, 30 Sep 2024 15:13:31 +0000 Subject: [PATCH] fix: use internal options when native binary is rebuilt from spirv Resolves: NEO-12838 Signed-off-by: Mateusz Hoppe --- level_zero/core/source/module/module_imp.cpp | 6 +- level_zero/core/source/module/module_imp.h | 2 +- .../unit_tests/sources/module/test_module.cpp | 74 ++++++++++++++++--- 3 files changed, 69 insertions(+), 13 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 08f257509f..ef1887a37a 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -291,7 +291,7 @@ ze_result_t ModuleTranslationUnit::buildFromSpirV(const char *input, uint32_t in return this->compileGenBinary(inputArgs, false); } -ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, size_t inputSize) { +ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) { UNRECOVERABLE_IF((nullptr == device) || (nullptr == device->getNEODevice())); auto productAbbreviation = NEO::hardwarePrefix[device->getNEODevice()->getHardwareInfo().platform.eProductFamily]; @@ -348,7 +348,7 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz updateBuildLog(NEO::CompilerWarnings::recompiledFromIr.str()); } - return buildFromSpirV(this->irBinary.get(), static_cast(this->irBinarySize), this->options.c_str(), "", nullptr); + return buildFromSpirV(this->irBinary.get(), static_cast(this->irBinarySize), this->options.c_str(), internalBuildOptions, nullptr); } else { if (processUnpackedBinary() != ZE_RESULT_SUCCESS) { driverHandle->clearErrorDescription(); @@ -741,7 +741,7 @@ inline ze_result_t ModuleImp::initializeTranslationUnit(const ze_module_desc_t * this->isFunctionSymbolExportEnabled = true; this->isGlobalSymbolExportEnabled = true; this->precompiled = true; - return this->translationUnit->createFromNativeBinary(reinterpret_cast(desc->pInputModule), desc->inputSize); + return this->translationUnit->createFromNativeBinary(reinterpret_cast(desc->pInputModule), desc->inputSize, internalBuildOptions.c_str()); } else if (desc->format == ZE_MODULE_FORMAT_IL_SPIRV) { this->builtFromSpirv = true; this->precompiled = false; diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index 373384edb0..16c9ae314d 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -53,7 +53,7 @@ struct ModuleTranslationUnit { const ze_module_constants_t *pConstants); MOCKABLE_VIRTUAL ze_result_t staticLinkSpirV(std::vector inputSpirVs, std::vector inputModuleSizes, const char *buildOptions, const char *internalBuildOptions, std::vector specConstants); - MOCKABLE_VIRTUAL ze_result_t createFromNativeBinary(const char *input, size_t inputSize); + MOCKABLE_VIRTUAL ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions); MOCKABLE_VIRTUAL ze_result_t processUnpackedBinary(); std::vector generateElfFromSpirV(std::vector inputSpirVs, std::vector inputModuleSizes); bool processSpecConstantInfo(NEO::CompilerInterface *compilerInterface, const ze_module_constants_t *pConstants, const char *input, uint32_t inputSize); diff --git a/level_zero/core/test/unit_tests/sources/module/test_module.cpp b/level_zero/core/test/unit_tests/sources/module/test_module.cpp index 724a5d9f2d..308eb95003 100644 --- a/level_zero/core/test/unit_tests/sources/module/test_module.cpp +++ b/level_zero/core/test/unit_tests/sources/module/test_module.cpp @@ -3012,10 +3012,10 @@ struct MockModuleTU : public L0::ModuleTranslationUnit { } } - ze_result_t createFromNativeBinary(const char *input, size_t inputSize) override { + ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) override { debugManager.flags.FailBuildProgramWithStatefulAccess.set(0); wasCreateFromNativeBinaryCalled = true; - return L0::ModuleTranslationUnit::createFromNativeBinary(input, inputSize); + return L0::ModuleTranslationUnit::createFromNativeBinary(input, inputSize, internalBuildOptions); } bool callRealBuildFromSpirv = false; @@ -3145,6 +3145,62 @@ HWTEST_F(ModuleTranslationUnitTest, GivenRebuildFlagWhenCreatingModuleFromNative EXPECT_TRUE(containsWarning); } +HWTEST_F(ModuleTranslationUnitTest, GivenNativeBinaryWhenRebuildingFromIntermediateThenCorrectInternalOptionsAreUsed) { + DebugManagerStateRestore dgbRestorer; + NEO::debugManager.flags.RebuildPrecompiledKernels.set(true); + + auto *pMockCompilerInterface = new MockCompilerInterface; + auto &rootDeviceEnvironment = this->neoDevice->executionEnvironment->rootDeviceEnvironments[this->neoDevice->getRootDeviceIndex()]; + rootDeviceEnvironment->compilerInterface.reset(pMockCompilerInterface); + + auto additionalSections = {ZebinTestData::AppendElfAdditionalSection::spirv}; + bool forceRecompilation = true; + auto zebinData = std::make_unique(device->getHwInfo(), additionalSections, forceRecompilation); + const auto &src = zebinData->storage; + + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_NATIVE; + moduleDesc.pInputModule = reinterpret_cast(src.data()); + moduleDesc.inputSize = src.size(); + + std::unique_ptr moduleBuildLog{ModuleBuildLog::create()}; + Module module(device, moduleBuildLog.get(), ModuleType::user); + + auto mockTranslationUnit = new MockModuleTranslationUnit(device); + mockTranslationUnit->processUnpackedBinaryCallBase = false; + module.translationUnit.reset(mockTranslationUnit); + + ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; + result = module.initialize(&moduleDesc, neoDevice); + ASSERT_EQ(result, ZE_RESULT_SUCCESS); + + char *buildFlags = nullptr; + std::string options; + std::string internalOptions; + module.createBuildOptions(buildFlags, options, internalOptions); + internalOptions = module.translationUnit->generateCompilerOptions(options.c_str(), internalOptions.c_str()); + + EXPECT_EQ(internalOptions, pMockCompilerInterface->inputInternalOptions); + + pMockCompilerInterface->inputInternalOptions = ""; + + uint8_t binary[10]; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + Module module2(device, nullptr, ModuleType::user); + + auto mockTranslationUnit2 = new MockModuleTranslationUnit(device); + mockTranslationUnit2->processUnpackedBinaryCallBase = false; + module2.translationUnit.reset(mockTranslationUnit2); + + result = module2.initialize(&moduleDesc, neoDevice); + ASSERT_EQ(result, ZE_RESULT_SUCCESS); + + // make sure internal options are matching those from buildFromSpirv + EXPECT_EQ(internalOptions, pMockCompilerInterface->inputInternalOptions); +} + HWTEST_F(ModuleTranslationUnitTest, GivenRebuildFlagWhenCreatingModuleFromNativeBinaryAndWarningSuppressionIsPresentThenModuleRecompilationWarningIsNotIssued) { DebugManagerStateRestore dgbRestorer; NEO::debugManager.flags.RebuildPrecompiledKernels.set(true); @@ -3189,7 +3245,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpRequir emptyProgram.elfHeader->machine = hwInfo.platform.eProductFamily; L0::ModuleTranslationUnit moduleTuValid(this->device); ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; - result = moduleTuValid.createFromNativeBinary(reinterpret_cast(emptyProgram.storage.data()), emptyProgram.storage.size()); + result = moduleTuValid.createFromNativeBinary(reinterpret_cast(emptyProgram.storage.data()), emptyProgram.storage.size(), ""); const char *pStr = nullptr; std::string emptyString = ""; zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr); @@ -3198,7 +3254,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpRequir ++emptyProgram.elfHeader->machine; L0::ModuleTranslationUnit moduleTuInvalid(this->device); - result = moduleTuInvalid.createFromNativeBinary(reinterpret_cast(emptyProgram.storage.data()), emptyProgram.storage.size()); + result = moduleTuInvalid.createFromNativeBinary(reinterpret_cast(emptyProgram.storage.data()), emptyProgram.storage.size(), ""); zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr); EXPECT_NE(0, strcmp(pStr, emptyString.c_str())); EXPECT_EQ(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, result); @@ -3234,7 +3290,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpPacked moduleTuValid.setDummyKernelInfo(); ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; - result = moduleTuValid.createFromNativeBinary(reinterpret_cast(arData.data()), arData.size()); + result = moduleTuValid.createFromNativeBinary(reinterpret_cast(arData.data()), arData.size(), ""); EXPECT_EQ(result, ZE_RESULT_SUCCESS); EXPECT_EQ(moduleTuValid.processUnpackedBinaryCalled, 1u); EXPECT_NE(moduleTuValid.packedDeviceBinarySize, arData.size()); @@ -3248,7 +3304,7 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromZebinThenDontAppendAllowZebi zebin.elfHeader->machine = hwInfo.platform.eProductFamily; L0::ModuleTranslationUnit moduleTu(this->device); ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE; - result = moduleTu.createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size()); + result = moduleTu.createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size(), ""); EXPECT_EQ(result, ZE_RESULT_SUCCESS); auto expectedOptions = ""; @@ -3280,7 +3336,7 @@ kernels: MockModule mockModule{this->device, nullptr, ModuleType::user}; auto maxWorkGroupSize = static_cast(this->neoDevice->deviceInfo.maxWorkGroupSize); auto mockTU = mockModule.translationUnit.get(); - auto result = mockTU->createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size()); + auto result = mockTU->createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size(), ""); EXPECT_EQ(result, ZE_RESULT_SUCCESS); auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor; @@ -3327,7 +3383,7 @@ kernels: MockModule mockModule{this->device, nullptr, ModuleType::user}; auto maxWorkGroupSize = static_cast(this->neoDevice->deviceInfo.maxWorkGroupSize); auto mockTU = mockModule.translationUnit.get(); - auto result = mockTU->createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size()); + auto result = mockTU->createFromNativeBinary(reinterpret_cast(zebin.storage.data()), zebin.storage.size(), ""); EXPECT_EQ(result, ZE_RESULT_SUCCESS); auto &defaultKernelDescriptor = mockTU->programInfo.kernelInfos[0]->kernelDescriptor; @@ -4220,7 +4276,7 @@ TEST_F(ModuleInitializeTest, whenModuleInitializeIsCalledThenCorrectResultIsRetu class MyMockModuleTU : public MockModuleTU { public: using MockModuleTU::MockModuleTU; - ze_result_t createFromNativeBinary(const char *input, size_t inputSize) override { + ze_result_t createFromNativeBinary(const char *input, size_t inputSize, const char *internalBuildOptions) override { programInfo.kernelInfos[0]->heapInfo.pKernelHeap = &mockKernelHeap; programInfo.kernelInfos[0]->heapInfo.kernelHeapSize = 4; return ZE_RESULT_SUCCESS;