From 7bded13638dce1c5d31d12aad9c64a3b03ea35e7 Mon Sep 17 00:00:00 2001 From: "Chodor, Jaroslaw" Date: Tue, 8 Apr 2025 14:43:25 +0000 Subject: [PATCH] feature: Enabling support for redirecting FCL to IGC for OCL This allows for invoking IGC as OCL C translator in OpenCL paths Accepted debug env : UseIgcAsFcl=1 ; forces IGC UseIgcAsFcl=2 ; forces FCL UseIgcAsFcl=0 ; uses defaults Related-To: NEO-14473 Signed-off-by: Chodor, Jaroslaw --- .../compiler_interface/compiler_interface.cpp | 60 ++++++++-- .../compiler_interface/compiler_interface.h | 8 +- .../debug_settings/debug_variables_base.inl | 1 + .../source/helpers/compiler_product_helper.h | 5 + .../helpers/compiler_product_helper_base.inl | 10 ++ .../common/mocks/mock_compiler_interface.h | 3 +- .../mocks/mock_compiler_product_helper.h | 3 +- shared/test/common/test_files/igdrcl.config | 1 + .../compiler_interface_tests.cpp | 110 +++++++++++++++++- 9 files changed, 181 insertions(+), 20 deletions(-) diff --git a/shared/source/compiler_interface/compiler_interface.cpp b/shared/source/compiler_interface/compiler_interface.cpp index 700bf43b1f..13d43bd644 100644 --- a/shared/source/compiler_interface/compiler_interface.cpp +++ b/shared/source/compiler_interface/compiler_interface.cpp @@ -102,9 +102,16 @@ TranslationOutput::ErrorCode CompilerInterface::build( intermediateCodeType = getPreferredIntermediateRepresentation(device); } - auto fclTranslationCtx = createFclTranslationCtx(device, srcCodeType, intermediateCodeType); - auto fclOutput = translate(fclTranslationCtx.get(), inSrc.get(), - fclOptions.get(), fclInternalOptions.get()); + CIF::RAII::UPtr_t fclOutput; + if (this->useIgcAsFcl(&device)) { + auto igcTranslationCtx = createIgcTranslationCtx(device, srcCodeType, intermediateCodeType); + fclOutput = translate(igcTranslationCtx.get(), inSrc.get(), + fclOptions.get(), fclInternalOptions.get()); + } else { + auto fclTranslationCtx = createFclTranslationCtx(device, srcCodeType, intermediateCodeType); + fclOutput = translate(fclTranslationCtx.get(), inSrc.get(), + fclOptions.get(), fclInternalOptions.get()); + } if (fclOutput == nullptr) { return TranslationOutput::ErrorCode::unknownError; @@ -206,15 +213,26 @@ TranslationOutput::ErrorCode CompilerInterface::compile( outType = getPreferredIntermediateRepresentation(device); } - auto *fclMain = fcl.entryPoint.get(); + CIF::CIFMain *fclMain = nullptr; + if (this->useIgcAsFcl(&device)) { + fclMain = getIgc(&device)->entryPoint.get(); + } else { + fclMain = fcl.entryPoint.get(); + } auto fclSrc = CIF::Builtins::CreateConstBuffer(fclMain, input.src.begin(), input.src.size()); auto fclOptions = CIF::Builtins::CreateConstBuffer(fclMain, input.apiOptions.begin(), input.apiOptions.size()); auto fclInternalOptions = CIF::Builtins::CreateConstBuffer(fclMain, input.internalOptions.begin(), input.internalOptions.size()); - auto fclTranslationCtx = createFclTranslationCtx(device, input.srcType, outType); - - auto fclOutput = translate(fclTranslationCtx.get(), fclSrc.get(), - fclOptions.get(), fclInternalOptions.get()); + CIF::RAII::UPtr_t fclOutput; + if (this->useIgcAsFcl(&device)) { + auto igcTranslationCtx = createIgcTranslationCtx(device, input.srcType, outType); + fclOutput = translate(igcTranslationCtx.get(), fclSrc.get(), + fclOptions.get(), fclInternalOptions.get()); + } else { + auto fclTranslationCtx = createFclTranslationCtx(device, input.srcType, outType); + fclOutput = translate(fclTranslationCtx.get(), fclSrc.get(), + fclOptions.get(), fclInternalOptions.get()); + } if (fclOutput == nullptr) { return TranslationOutput::ErrorCode::unknownError; @@ -550,7 +568,11 @@ IGC::IgcOclDeviceCtxTagOCL *CompilerInterface::getFinalizerDeviceCtx(const Devic } IGC::CodeType::CodeType_t CompilerInterface::getPreferredIntermediateRepresentation(const Device &device) { - return getFclDeviceCtx(device)->GetPreferredIntermediateRepresentation(); + if (useIgcAsFcl(&device)) { + return device.getCompilerProductHelper().getPreferredIntermediateRepresentation(); + } else { + return getFclDeviceCtx(device)->GetPreferredIntermediateRepresentation(); + } } CIF::RAII::UPtr_t CompilerInterface::createFclTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType) { @@ -599,6 +621,10 @@ bool CompilerInterface::disableZebin(std::string &options, std::string &internal return addOptionDisableZebin(options, internalOptions); } +bool CompilerInterface::isFclAvailable(const Device *device) { + return useIgcAsFcl(device) ? isIgcAvailable(device) : static_cast(fcl.entryPoint); +} + bool CompilerInterface::isIgcAvailable(const Device *device) { return nullptr != getIgc(device); } @@ -607,6 +633,22 @@ bool CompilerInterface::isFinalizerAvailable(const Device *device) { return nullptr != getFinalizer(device); } +bool CompilerInterface::useIgcAsFcl(const Device *device) { + if (0 != debugManager.flags.UseIgcAsFcl.get()) { + if (1 == debugManager.flags.UseIgcAsFcl.get()) { + return true; + } else if (2 == debugManager.flags.UseIgcAsFcl.get()) { + return false; + } + } + + if (nullptr == device) { + return false; + } + + return device->getCompilerProductHelper().useIgcAsFcl(); +} + const CompilerInterface::CompilerLibraryEntry *CompilerInterface::getIgc(const Device *device) { if (nullptr == device) { if (defaultIgc.entryPoint == nullptr) { diff --git a/shared/source/compiler_interface/compiler_interface.h b/shared/source/compiler_interface/compiler_interface.h index 469e5a7547..d4565b1780 100644 --- a/shared/source/compiler_interface/compiler_interface.h +++ b/shared/source/compiler_interface/compiler_interface.h @@ -205,12 +205,10 @@ class CompilerInterface : NEO::NonCopyableAndNonMovableClass { MOCKABLE_VIRTUAL CIF::RAII::UPtr_t createFinalizerTranslationCtx(const Device &device, IGC::CodeType::CodeType_t inType, IGC::CodeType::CodeType_t outType); - bool isFclAvailable() const { - return (fcl.entryPoint.get() != nullptr); - } - + bool isFclAvailable(const Device *device); bool isIgcAvailable(const Device *device); bool isFinalizerAvailable(const Device *device); + bool useIgcAsFcl(const Device *device); const CompilerLibraryEntry *getCustomCompilerLibrary(const char *libName); @@ -241,7 +239,7 @@ class CompilerInterface : NEO::NonCopyableAndNonMovableClass { bool requiresFcl = (IGC::CodeType::oclC == translationSrc); bool requiresIgc = (IGC::CodeType::oclC != translationSrc) || ((IGC::CodeType::spirV != translationDst) && (IGC::CodeType::llvmBc != translationDst) && (IGC::CodeType::llvmLl != translationDst)); bool requiresFinalizer = (finalizerInputType != IGC::CodeType::undefined) && ((translationDst == IGC::CodeType::oclGenBin) || (translationSrc == finalizerInputType)); - return (isFclAvailable() || (false == requiresFcl)) && (isIgcAvailable(device) || (false == requiresIgc)) && ((false == requiresFinalizer) || isFinalizerAvailable(device)); + return (isFclAvailable(device) || (false == requiresFcl)) && (isIgcAvailable(device) || (false == requiresIgc)) && ((false == requiresFinalizer) || isFinalizerAvailable(device)); } }; diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 2d1125079c..069d9eca31 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -680,6 +680,7 @@ DECLARE_DEBUG_VARIABLE(int64_t, ReadOnlyAllocationsTypeMask, 0, "0: default, >0 DECLARE_DEBUG_VARIABLE(bool, IgnoreZebinUnknownAttributes, false, "enable to treat unknown zebin attributes as warning instead of error"); DECLARE_DEBUG_VARIABLE(int64_t, FinalizerInputType, 0, "0: default (N/A), input type for finalizer") DECLARE_DEBUG_VARIABLE(std::string, FinalizerLibraryName, std::string("unk"), "Library name for finalizer") +DECLARE_DEBUG_SCOPED_V(int32_t, UseIgcAsFcl, 0, S_RT, "0: platform default, 1: force use IGC, 2: force use FCL") DECLARE_DEBUG_VARIABLE(int32_t, EnableGlobalTimestampViaSubmission, -1, "-1: OS Interface, 0: OS Interface, 1: Submission. This flag sets the type of method to get timestamp for getGlobalTimestamps"); /* Binary Cache */ diff --git a/shared/source/helpers/compiler_product_helper.h b/shared/source/helpers/compiler_product_helper.h index eb38ac3d5d..404c1ec0a8 100644 --- a/shared/source/helpers/compiler_product_helper.h +++ b/shared/source/helpers/compiler_product_helper.h @@ -12,6 +12,7 @@ #include "shared/source/utilities/stackvec.h" #include "igfxfmid.h" +#include "ocl_igc_interface/code_type.h" #include @@ -89,6 +90,8 @@ class CompilerProductHelper { virtual bool isForceBindlessRequired(const HardwareInfo &hwInfo) const = 0; virtual const char *getCustomIgcLibraryName() const = 0; virtual const char *getFinalizerLibraryName() const = 0; + virtual bool useIgcAsFcl() const = 0; + virtual IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation() const = 0; virtual ~CompilerProductHelper() = default; uint32_t getHwIpVersion(const HardwareInfo &hwInfo) const; @@ -143,6 +146,8 @@ class CompilerProductHelperHw : public CompilerProductHelper { bool isForceBindlessRequired(const HardwareInfo &hwInfo) const override; const char *getCustomIgcLibraryName() const override; const char *getFinalizerLibraryName() const override; + bool useIgcAsFcl() const override; + IGC::CodeType::CodeType_t getPreferredIntermediateRepresentation() const override; ~CompilerProductHelperHw() override = default; diff --git a/shared/source/helpers/compiler_product_helper_base.inl b/shared/source/helpers/compiler_product_helper_base.inl index 717b25b7f1..de50c55bc1 100644 --- a/shared/source/helpers/compiler_product_helper_base.inl +++ b/shared/source/helpers/compiler_product_helper_base.inl @@ -319,9 +319,19 @@ const char *CompilerProductHelperHw::getCustomIgcLibraryName() const return nullptr; } +template +bool CompilerProductHelperHw::useIgcAsFcl() const { + return false; +} + template const char *CompilerProductHelperHw::getFinalizerLibraryName() const { return nullptr; } +template +IGC::CodeType::CodeType_t CompilerProductHelperHw::getPreferredIntermediateRepresentation() const { + return IGC::CodeType::spirV; +} + } // namespace NEO diff --git a/shared/test/common/mocks/mock_compiler_interface.h b/shared/test/common/mocks/mock_compiler_interface.h index cc6b0a1870..326154cbcc 100644 --- a/shared/test/common/mocks/mock_compiler_interface.h +++ b/shared/test/common/mocks/mock_compiler_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2024 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -35,6 +35,7 @@ class MockCompilerInterface : public CompilerInterface { using CompilerInterface::customCompilerLibraries; using CompilerInterface::finalizerDeviceContexts; + using CompilerInterface::useIgcAsFcl; bool loadFcl() override { if (failLoadFcl) { diff --git a/shared/test/common/mocks/mock_compiler_product_helper.h b/shared/test/common/mocks/mock_compiler_product_helper.h index 50c50bf62f..94975d4b2c 100644 --- a/shared/test/common/mocks/mock_compiler_product_helper.h +++ b/shared/test/common/mocks/mock_compiler_product_helper.h @@ -24,7 +24,6 @@ class MockCompilerProductHelper : public CompilerProductHelper { public: using BaseClass = CompilerProductHelper; using BaseClass::getDefaultHwIpVersion; - ADDMETHOD_CONST_NOBASE(isMidThreadPreemptionSupported, bool, false, (const HardwareInfo &hwInfo)); ADDMETHOD_CONST_NOBASE(isForceEmuInt32DivRemSPRequired, bool, false, ()); @@ -65,6 +64,8 @@ class MockCompilerProductHelper : public CompilerProductHelper { ADDMETHOD_CONST_NOBASE(getProductConfigFromHwInfo, uint32_t, 0, (const HardwareInfo &hwInfo)); ADDMETHOD_CONST_NOBASE(getCustomIgcLibraryName, const char *, nullptr, ()); ADDMETHOD_CONST_NOBASE(getFinalizerLibraryName, const char *, nullptr, ()); + ADDMETHOD_CONST_NOBASE(useIgcAsFcl, bool, false, ()); + ADDMETHOD_CONST_NOBASE(getPreferredIntermediateRepresentation, IGC::CodeType::CodeType_t, IGC::CodeType::undefined, ()); }; } // namespace NEO diff --git a/shared/test/common/test_files/igdrcl.config b/shared/test/common/test_files/igdrcl.config index 13d1edcc91..909380f52b 100644 --- a/shared/test/common/test_files/igdrcl.config +++ b/shared/test/common/test_files/igdrcl.config @@ -670,4 +670,5 @@ SetMaxBVHLevels = -1 GetSipBinaryFromExternalLib = -1 LogUsmReuse = 0 ExperimentalUSMAllocationReuseLimitThreshold = -1 +UseIgcAsFcl = 0 # Please don't edit below this line diff --git a/shared/test/unit_test/compiler_interface/compiler_interface_tests.cpp b/shared/test/unit_test/compiler_interface/compiler_interface_tests.cpp index 2ce68826b6..aa5609aea8 100644 --- a/shared/test/unit_test/compiler_interface/compiler_interface_tests.cpp +++ b/shared/test/unit_test/compiler_interface/compiler_interface_tests.cpp @@ -246,6 +246,108 @@ TEST_F(CompilerInterfaceTest, WhenCompilingToIrThenSuccessIsReturned) { gEnvironment->fclPopDebugVars(); } +TEST_F(CompilerInterfaceTest, GivenFclRedirectionEnvSetToForceIgcWhenCompilingToIrThenIgcIsBeingUsed) { + DebugManagerStateRestore dbgRestore; + debugManager.flags.UseIgcAsFcl.set(1); + + char bin[1] = {7}; + MockCompilerDebugVars igcDebugVars; + igcDebugVars.binaryToReturn = bin; + igcDebugVars.binaryToReturnSize = 1; + gEnvironment->igcPushDebugVars(igcDebugVars); + + MockCompilerDebugVars fclDebugVars; + fclDebugVars.forceBuildFailure = true; + gEnvironment->fclPushDebugVars(fclDebugVars); + + TranslationOutput translationOutput = {}; + auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); + gEnvironment->fclPopDebugVars(); + gEnvironment->igcPopDebugVars(); + EXPECT_EQ(TranslationOutput::ErrorCode::success, err); + ASSERT_EQ(1U, translationOutput.intermediateRepresentation.size); + EXPECT_EQ(7, translationOutput.intermediateRepresentation.mem[0]); +} + +TEST_F(CompilerInterfaceTest, GivenFclRedirectionEnvSetToForceFclWhenCompilingToIrThenFclIsBeingUsed) { + DebugManagerStateRestore dbgRestore; + debugManager.flags.UseIgcAsFcl.set(2); + + char bin[1] = {7}; + MockCompilerDebugVars igcDebugVars; + igcDebugVars.forceBuildFailure = true; + gEnvironment->igcPushDebugVars(igcDebugVars); + + MockCompilerDebugVars fclDebugVars; + fclDebugVars.binaryToReturn = bin; + fclDebugVars.binaryToReturnSize = 1; + gEnvironment->fclPushDebugVars(fclDebugVars); + + TranslationOutput translationOutput = {}; + auto err = pCompilerInterface->compile(*pDevice, inputArgs, translationOutput); + gEnvironment->fclPopDebugVars(); + gEnvironment->igcPopDebugVars(); + EXPECT_EQ(TranslationOutput::ErrorCode::success, err); + ASSERT_EQ(1U, translationOutput.intermediateRepresentation.size); + EXPECT_EQ(7, translationOutput.intermediateRepresentation.mem[0]); +} + +TEST_F(CompilerInterfaceTest, GivenFclRedirectionDefaultSettingWhenCompilingToIrThenUseCompilerProductHelperDefaults) { + DebugManagerStateRestore dbgRestore; + debugManager.flags.UseIgcAsFcl.set(0); + + EXPECT_EQ(this->pDevice->getCompilerProductHelper().useIgcAsFcl(), pCompilerInterface->useIgcAsFcl(this->pDevice)); +} + +TEST_F(CompilerInterfaceTest, GivenFclRedirectionEnvSetToForceIgcWhenBuildingDeviceBinaryThenOnlyIgcIsBeingUsed) { + DebugManagerStateRestore dbgRestore; + debugManager.flags.UseIgcAsFcl.set(1); + + char bin[1] = {7}; + MockCompilerDebugVars igcDebugVars; + igcDebugVars.binaryToReturn = bin; + igcDebugVars.binaryToReturnSize = 1; + gEnvironment->igcPushDebugVars(igcDebugVars); + + MockCompilerDebugVars fclDebugVars; + fclDebugVars.forceBuildFailure = true; + gEnvironment->fclPushDebugVars(fclDebugVars); + + TranslationOutput translationOutput = {}; + auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); + gEnvironment->fclPopDebugVars(); + gEnvironment->igcPopDebugVars(); + EXPECT_EQ(TranslationOutput::ErrorCode::success, err); + ASSERT_EQ(1U, translationOutput.intermediateRepresentation.size); + EXPECT_EQ(7, translationOutput.intermediateRepresentation.mem[0]); +} + +TEST_F(CompilerInterfaceTest, GivenFclRedirectionEnvSetToForceFclWhenBuildingDeviceBinaryThenFclIsBeingUsedForSourceTranslation) { + DebugManagerStateRestore dbgRestore; + debugManager.flags.UseIgcAsFcl.set(2); + + char fclBin[2] = {3, 5}; + char igcBin[1] = {7}; + MockCompilerDebugVars igcDebugVars; + igcDebugVars.binaryToReturn = igcBin; + igcDebugVars.binaryToReturnSize = 1; + gEnvironment->igcPushDebugVars(igcDebugVars); + + MockCompilerDebugVars fclDebugVars; + fclDebugVars.binaryToReturn = fclBin; + fclDebugVars.binaryToReturnSize = 2; + gEnvironment->fclPushDebugVars(fclDebugVars); + + TranslationOutput translationOutput = {}; + auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput); + gEnvironment->fclPopDebugVars(); + gEnvironment->igcPopDebugVars(); + EXPECT_EQ(TranslationOutput::ErrorCode::success, err); + ASSERT_EQ(2U, translationOutput.intermediateRepresentation.size); + EXPECT_EQ(3, translationOutput.intermediateRepresentation.mem[0]); + EXPECT_EQ(5, translationOutput.intermediateRepresentation.mem[1]); +} + TEST_F(CompilerInterfaceTest, GivenProgramCreatedFromIrWhenCompileIsCalledThenDontRecompile) { TranslationOutput translationOutput = {}; inputArgs.srcType = IGC::CodeType::spirV; @@ -1021,7 +1123,7 @@ HWTEST_F(CompilerInterfaceTest, givenDbgKeyForceUseDifferentPlatformWhenRequestF TEST_F(CompilerInterfaceTest, GivenCompilerWhenGettingCompilerAvailabilityThenCompilerHasCorrectCapabilities) { ASSERT_TRUE(this->pCompilerInterface->defaultIgc.entryPoint && this->pCompilerInterface->fcl.entryPoint); - EXPECT_TRUE(this->pCompilerInterface->isFclAvailable()); + EXPECT_TRUE(this->pCompilerInterface->isFclAvailable(nullptr)); EXPECT_TRUE(this->pCompilerInterface->isIgcAvailable(nullptr)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::spirV)); @@ -1034,7 +1136,7 @@ TEST_F(CompilerInterfaceTest, GivenCompilerWhenGettingCompilerAvailabilityThenCo EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::elf, IGC::CodeType::oclGenBin)); auto befIgcImain = std::move(this->pCompilerInterface->defaultIgc.entryPoint); - EXPECT_TRUE(this->pCompilerInterface->isFclAvailable()); + EXPECT_TRUE(this->pCompilerInterface->isFclAvailable(nullptr)); EXPECT_FALSE(this->pCompilerInterface->isIgcAvailable(nullptr)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_TRUE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::spirV)); @@ -1048,7 +1150,7 @@ TEST_F(CompilerInterfaceTest, GivenCompilerWhenGettingCompilerAvailabilityThenCo this->pCompilerInterface->defaultIgc.entryPoint = std::move(befIgcImain); auto befFclImain = std::move(this->pCompilerInterface->fcl.entryPoint); - EXPECT_FALSE(this->pCompilerInterface->isFclAvailable()); + EXPECT_FALSE(this->pCompilerInterface->isFclAvailable(nullptr)); EXPECT_TRUE(this->pCompilerInterface->isIgcAvailable(nullptr)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::spirV)); @@ -1063,7 +1165,7 @@ TEST_F(CompilerInterfaceTest, GivenCompilerWhenGettingCompilerAvailabilityThenCo befIgcImain = std::move(this->pCompilerInterface->defaultIgc.entryPoint); befFclImain = std::move(this->pCompilerInterface->fcl.entryPoint); - EXPECT_FALSE(this->pCompilerInterface->isFclAvailable()); + EXPECT_FALSE(this->pCompilerInterface->isFclAvailable(nullptr)); EXPECT_FALSE(this->pCompilerInterface->isIgcAvailable(nullptr)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::oclGenBin)); EXPECT_FALSE(this->pCompilerInterface->isCompilerAvailable(nullptr, IGC::CodeType::oclC, IGC::CodeType::spirV));