From b11d7cd7b02d62f6e3c410affee90ac674acd320 Mon Sep 17 00:00:00 2001 From: Mateusz Hoppe Date: Mon, 22 Nov 2021 13:05:54 +0000 Subject: [PATCH] Add debug key for compiler internal options injection Signed-off-by: Mateusz Hoppe --- level_zero/core/source/module/module_imp.cpp | 4 + .../core/test/unit_tests/mocks/mock_module.h | 13 ++++ .../unit_tests/sources/module/test_module.cpp | 75 ++++++++++++------- opencl/source/program/build.cpp | 4 + opencl/source/program/compile.cpp | 4 + opencl/test/unit_test/mocks/mock_program.h | 1 + .../test/unit_test/program/program_tests.cpp | 70 +++++++++++++++++ .../test/unit_test/test_files/igdrcl.config | 1 + .../debug_settings/debug_variables_base.inl | 1 + 9 files changed, 147 insertions(+), 26 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 0a44b87c82..d3899fc1ad 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -508,6 +508,10 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) } else { this->createBuildOptions(desc->pBuildFlags, buildOptions, internalBuildOptions); + if (type == ModuleType::User && NEO::DebugManager.flags.InjectInternalBuildOptions.get() != "unk") { + NEO::CompilerOptions::concatenateAppend(internalBuildOptions, NEO::DebugManager.flags.InjectInternalBuildOptions.get()); + } + if (desc->format == ZE_MODULE_FORMAT_NATIVE) { success = this->translationUnit->createFromNativeBinary( reinterpret_cast(desc->pInputModule), desc->inputSize); diff --git a/level_zero/core/test/unit_tests/mocks/mock_module.h b/level_zero/core/test/unit_tests/mocks/mock_module.h index 57d0ad879f..bb8c9bb409 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_module.h +++ b/level_zero/core/test/unit_tests/mocks/mock_module.h @@ -89,14 +89,27 @@ struct MockCompilerInterface : public NEO::CompilerInterface { const NEO::TranslationInput &input, NEO::TranslationOutput &output) override { + receivedApiOptions = input.apiOptions.begin(); + inputInternalOptions = input.internalOptions.begin(); + + if (failBuild) { + return NEO::TranslationOutput::ErrorCode::BuildFailure; + } return NEO::TranslationOutput::ErrorCode::Success; } NEO::TranslationOutput::ErrorCode link(const NEO::Device &device, const NEO::TranslationInput &input, NEO::TranslationOutput &output) override { + receivedApiOptions = input.apiOptions.begin(); + inputInternalOptions = input.internalOptions.begin(); + return NEO::TranslationOutput::ErrorCode::Success; } + + std::string receivedApiOptions; + std::string inputInternalOptions; + bool failBuild = false; }; template struct MockCompilerInterfaceWithSpecConstants : public NEO::CompilerInterface { 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 3c111ef726..8b2c4e186c 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 @@ -1594,21 +1594,15 @@ kernels: } HWTEST_F(ModuleTranslationUnitTest, WhenBuildOptionsAreNullThenReuseExistingOptions) { - struct MockCompilerInterface : CompilerInterface { - TranslationOutput::ErrorCode build(const NEO::Device &device, - const TranslationInput &input, - TranslationOutput &output) override { - receivedApiOptions = input.apiOptions.begin(); - return TranslationOutput::ErrorCode::BuildFailure; - } - std::string receivedApiOptions; - }; + auto *pMockCompilerInterface = new MockCompilerInterface; auto &rootDeviceEnvironment = this->neoDevice->executionEnvironment->rootDeviceEnvironments[this->neoDevice->getRootDeviceIndex()]; rootDeviceEnvironment->compilerInterface.reset(pMockCompilerInterface); L0::ModuleTranslationUnit moduleTu(this->device); moduleTu.options = "abcd"; + pMockCompilerInterface->failBuild = true; + auto ret = moduleTu.buildFromSpirV("", 0U, nullptr, "", nullptr); EXPECT_FALSE(ret); EXPECT_STREQ("abcd", moduleTu.options.c_str()); @@ -1616,15 +1610,6 @@ HWTEST_F(ModuleTranslationUnitTest, WhenBuildOptionsAreNullThenReuseExistingOpti } HWTEST_F(ModuleTranslationUnitTest, WhenBuildOptionsAreNullThenReuseExistingOptions2) { - struct MockCompilerInterface : CompilerInterface { - TranslationOutput::ErrorCode build(const NEO::Device &device, - const TranslationInput &input, - TranslationOutput &output) override { - inputInternalOptions = input.internalOptions.begin(); - return TranslationOutput::ErrorCode::Success; - } - std::string inputInternalOptions; - }; auto pMockCompilerInterface = new MockCompilerInterface; auto &rootDeviceEnvironment = this->neoDevice->executionEnvironment->rootDeviceEnvironments[this->neoDevice->getRootDeviceIndex()]; rootDeviceEnvironment->compilerInterface.reset(pMockCompilerInterface); @@ -1639,14 +1624,6 @@ HWTEST_F(ModuleTranslationUnitTest, WhenBuildOptionsAreNullThenReuseExistingOpti } HWTEST_F(ModuleTranslationUnitTest, givenSystemSharedAllocationAllowedWhenBuildingModuleThen4GbBuffersAreRequired) { - struct MockCompilerInterface : CompilerInterface { - TranslationOutput::ErrorCode build(const NEO::Device &device, const TranslationInput &input, TranslationOutput &output) override { - inputInternalOptions = input.internalOptions.begin(); - return TranslationOutput::ErrorCode::Success; - } - std::string inputInternalOptions; - }; - auto mockCompilerInterface = new MockCompilerInterface; auto &rootDeviceEnvironment = neoDevice->executionEnvironment->rootDeviceEnvironments[neoDevice->getRootDeviceIndex()]; rootDeviceEnvironment->compilerInterface.reset(mockCompilerInterface); @@ -1788,6 +1765,52 @@ TEST_F(ModuleTest, givenInternalOptionsWhenBindlessDisabledThenBindlesOptionsNot EXPECT_FALSE(NEO::CompilerOptions::contains(internalBuildOptions, NEO::CompilerOptions::bindlessMode)); } +TEST_F(ModuleTest, GivenInjectInternalBuildOptionsWhenBuildingUserModuleThenInternalOptionsAreAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set(" -abc"); + + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + device->getNEODevice()->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + + ModuleBuildLog *moduleBuildLog = nullptr; + + auto module = std::unique_ptr(new L0::ModuleImp(device, moduleBuildLog, ModuleType::User)); + ASSERT_NE(nullptr, module.get()); + module->initialize(&moduleDesc, device->getNEODevice()); + + EXPECT_TRUE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")); +}; + +TEST_F(ModuleTest, GivenInjectInternalBuildOptionsWhenBuildingBuiltinModuleThenInternalOptionsAreNotAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set(" -abc"); + + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + device->getNEODevice()->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + + ModuleBuildLog *moduleBuildLog = nullptr; + + auto module = std::unique_ptr(new L0::ModuleImp(device, moduleBuildLog, ModuleType::Builtin)); + ASSERT_NE(nullptr, module.get()); + module->initialize(&moduleDesc, device->getNEODevice()); + + EXPECT_FALSE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")); +}; + using ModuleDebugDataTest = Test; TEST_F(ModuleDebugDataTest, GivenDebugDataWithRelocationsWhenCreatingRelocatedDebugDataThenRelocationsAreApplied) { auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); diff --git a/opencl/source/program/build.cpp b/opencl/source/program/build.cpp index ec492a794f..3627595d77 100644 --- a/opencl/source/program/build.cpp +++ b/opencl/source/program/build.cpp @@ -113,6 +113,10 @@ cl_int Program::build( } CompilerOptions::concatenateAppend(internalOptions, extensions); + if (!this->getIsBuiltIn() && DebugManager.flags.InjectInternalBuildOptions.get() != "unk") { + NEO::CompilerOptions::concatenateAppend(internalOptions, NEO::DebugManager.flags.InjectInternalBuildOptions.get()); + } + inputArgs.apiOptions = ArrayRef(options.c_str(), options.length()); inputArgs.internalOptions = ArrayRef(internalOptions.c_str(), internalOptions.length()); inputArgs.GTPinInput = gtpinGetIgcInit(); diff --git a/opencl/source/program/compile.cpp b/opencl/source/program/compile.cpp index 31c919da8c..4336b414c0 100644 --- a/opencl/source/program/compile.cpp +++ b/opencl/source/program/compile.cpp @@ -138,6 +138,10 @@ cl_int Program::compile( } } + if (!this->getIsBuiltIn() && DebugManager.flags.InjectInternalBuildOptions.get() != "unk") { + NEO::CompilerOptions::concatenateAppend(internalOptions, NEO::DebugManager.flags.InjectInternalBuildOptions.get()); + } + inputArgs.src = ArrayRef(reinterpret_cast(compileData.data()), compileData.size()); inputArgs.apiOptions = ArrayRef(options.c_str(), options.length()); inputArgs.internalOptions = ArrayRef(internalOptions.c_str(), internalOptions.length()); diff --git a/opencl/test/unit_test/mocks/mock_program.h b/opencl/test/unit_test/mocks/mock_program.h index fe27202468..70ade0a943 100644 --- a/opencl/test/unit_test/mocks/mock_program.h +++ b/opencl/test/unit_test/mocks/mock_program.h @@ -44,6 +44,7 @@ class MockProgram : public Program { using Program::internalOptionsToExtract; using Program::irBinary; using Program::irBinarySize; + using Program::isBuiltIn; using Program::isSpirV; using Program::kernelDebugEnabled; using Program::linkBinary; diff --git a/opencl/test/unit_test/program/program_tests.cpp b/opencl/test/unit_test/program/program_tests.cpp index e2054c958f..140e5d81fc 100644 --- a/opencl/test/unit_test/program/program_tests.cpp +++ b/opencl/test/unit_test/program/program_tests.cpp @@ -2659,6 +2659,76 @@ TEST_F(ProgramTests, givenProgramWhenInternalOptionsArePassedWithInvalidValuesTh EXPECT_EQ(expectedOutput, internalOptions); } +TEST_F(ProgramTests, GivenInjectInternalBuildOptionsWhenBuildingProgramThenInternalOptionsWereAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set("-abc"); + + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pDevice = pContext->getDevice(0); + pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto program = std::make_unique(toClDeviceVector(*pDevice)); + program->sourceCode = "__kernel mock() {}"; + program->createdFrom = Program::CreatedFrom::SOURCE; + + cl_int retVal = program->build(program->getDevices(), "", false); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_TRUE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")) << cip->buildInternalOptions; +} + +TEST_F(ProgramTests, GivenInjectInternalBuildOptionsWhenBuildingBuiltInProgramThenInternalOptionsAreNotAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set("-abc"); + + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pDevice = pContext->getDevice(0); + pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto program = std::make_unique(toClDeviceVector(*pDevice)); + program->sourceCode = "__kernel mock() {}"; + program->createdFrom = Program::CreatedFrom::SOURCE; + program->isBuiltIn = true; + + cl_int retVal = program->build(program->getDevices(), "", false); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_FALSE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")) << cip->buildInternalOptions; +} + +TEST_F(ProgramTests, GivenInjectInternalBuildOptionsWhenCompilingProgramThenInternalOptionsWereAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set("-abc"); + + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pDevice = pContext->getDevice(0); + pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto program = std::make_unique(toClDeviceVector(*pDevice)); + program->sourceCode = "__kernel mock() {}"; + program->createdFrom = Program::CreatedFrom::SOURCE; + + cl_int retVal = program->compile(program->getDevices(), nullptr, 0, nullptr, nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_TRUE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")) << cip->buildInternalOptions; +} + +TEST_F(ProgramTests, GivenInjectInternalBuildOptionsWhenCompilingBuiltInProgramThenInternalOptionsAreNotAppended) { + DebugManagerStateRestore dbgRestorer; + DebugManager.flags.InjectInternalBuildOptions.set("-abc"); + + auto cip = new MockCompilerInterfaceCaptureBuildOptions(); + auto pDevice = pContext->getDevice(0); + pDevice->getExecutionEnvironment()->rootDeviceEnvironments[pDevice->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto program = std::make_unique(toClDeviceVector(*pDevice)); + program->sourceCode = "__kernel mock() {}"; + program->createdFrom = Program::CreatedFrom::SOURCE; + program->isBuiltIn = true; + + cl_int retVal = program->compile(program->getDevices(), nullptr, 0, nullptr, nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_FALSE(CompilerOptions::contains(cip->buildInternalOptions, "-abc")) << cip->buildInternalOptions; +} + class AdditionalOptionsMockProgram : public MockProgram { public: using MockProgram::MockProgram; diff --git a/opencl/test/unit_test/test_files/igdrcl.config b/opencl/test/unit_test/test_files/igdrcl.config index 16ec9a5150..7d6bb753ac 100644 --- a/opencl/test/unit_test/test_files/igdrcl.config +++ b/opencl/test/unit_test/test_files/igdrcl.config @@ -33,6 +33,7 @@ EnableSWTags = 0 DumpSWTagsBXML = 0 ForceDeviceId = unk LoadBinarySipFromFile = unk +InjectInternalBuildOptions = unk OverrideCsrAllocationSize = -1 ForceL1Caching = -1 UseKmdMigration = -1 diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index f1521e96a0..2b4e0d8471 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -76,6 +76,7 @@ DECLARE_DEBUG_VARIABLE(bool, AllowPatchingVfeStateInCommandLists, false, "true: DECLARE_DEBUG_VARIABLE(bool, PrintMemoryRegionSizes, false, "print memory bank type, instance and it's size") DECLARE_DEBUG_VARIABLE(std::string, ForceDeviceId, std::string("unk"), "DeviceId selected for testing") DECLARE_DEBUG_VARIABLE(std::string, LoadBinarySipFromFile, std::string("unk"), "Select binary file to load SIP kernel raw binary. When file named *_header.* exists, it is used as header") +DECLARE_DEBUG_VARIABLE(std::string, InjectInternalBuildOptions, std::string("unk"), "Appends internal build options string to user modules") DECLARE_DEBUG_VARIABLE(int64_t, OverrideMultiStoragePlacement, -1, "-1: disable, 0+: tile mask, each bit corresponds to tile") DECLARE_DEBUG_VARIABLE(int64_t, ForceCompressionDisabledForCompressedBlitCopies, -1, "-1: default, 0: disabled, 1: enabled. If compression is required, set AUX_CCS_E, but force CompressionEnable filed. 0 should result in uncompressed read/write") DECLARE_DEBUG_VARIABLE(int32_t, ForceL1Caching, -1, "-1: default, 0: disable, 1: enable, When set to true driver will program L1 cache policy for surface state and stateless accessess")