Skip to content

Commit e0ccf22

Browse files
fix: indirect access in external functions
Read indirect_stateless_count in module external functions. If greater than 0, mark all kernels that have the has_stack_calls flag set from this module as having indirect accesses. Related-To: NEO-7712 Signed-off-by: Dominik Dabek <[email protected]>
1 parent af59777 commit e0ccf22

File tree

12 files changed

+123
-4
lines changed

12 files changed

+123
-4
lines changed

level_zero/core/source/kernel/kernel_imp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ ze_result_t KernelImp::initialize(const ze_kernel_desc_t *desc) {
11091109
kernelDescriptor.kernelAttributes.hasNonKernelArgStore ||
11101110
kernelDescriptor.kernelAttributes.hasNonKernelArgAtomic ||
11111111
kernelDescriptor.kernelAttributes.hasIndirectStatelessAccess ||
1112+
(moduleImp->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists && kernelDescriptor.kernelAttributes.flags.useStackCalls) ||
11121113
NEO::KernelHelper::isAnyArgumentPtrByValue(kernelDescriptor);
11131114
} else {
11141115
kernelHasIndirectAccess = true;

level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,7 @@ TEST_F(KernelIndirectPropertiesFromIGCTests, givenDetectIndirectAccessInKernelEn
13871387
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false;
13881388
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false;
13891389
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = false;
1390+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = false;
13901391

13911392
kernel->initialize(&desc);
13921393

@@ -1404,6 +1405,7 @@ TEST_F(KernelIndirectPropertiesFromIGCTests, givenDetectIndirectAccessInKernelEn
14041405
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = true;
14051406
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false;
14061407
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = false;
1408+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = false;
14071409

14081410
kernel->initialize(&desc);
14091411

@@ -1421,6 +1423,7 @@ TEST_F(KernelIndirectPropertiesFromIGCTests, givenDetectIndirectAccessInKernelEn
14211423
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false;
14221424
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = true;
14231425
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = false;
1426+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = false;
14241427

14251428
kernel->initialize(&desc);
14261429

@@ -1438,6 +1441,45 @@ TEST_F(KernelIndirectPropertiesFromIGCTests, givenDetectIndirectAccessInKernelEn
14381441
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false;
14391442
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false;
14401443
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = true;
1444+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = false;
1445+
1446+
kernel->initialize(&desc);
1447+
1448+
EXPECT_TRUE(kernel->hasIndirectAccess());
1449+
}
1450+
1451+
{
1452+
std::unique_ptr<ModuleImmutableDataFixture::MockKernel> kernel;
1453+
kernel = std::make_unique<ModuleImmutableDataFixture::MockKernel>(module.get());
1454+
1455+
ze_kernel_desc_t desc = {};
1456+
desc.pKernelName = kernelName.c_str();
1457+
1458+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = false;
1459+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false;
1460+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false;
1461+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = false;
1462+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = true;
1463+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.flags.useStackCalls = false;
1464+
1465+
kernel->initialize(&desc);
1466+
1467+
EXPECT_FALSE(kernel->hasIndirectAccess());
1468+
}
1469+
1470+
{
1471+
std::unique_ptr<ModuleImmutableDataFixture::MockKernel> kernel;
1472+
kernel = std::make_unique<ModuleImmutableDataFixture::MockKernel>(module.get());
1473+
1474+
ze_kernel_desc_t desc = {};
1475+
desc.pKernelName = kernelName.c_str();
1476+
1477+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgLoad = false;
1478+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgStore = false;
1479+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasNonKernelArgAtomic = false;
1480+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.hasIndirectStatelessAccess = false;
1481+
module->getTranslationUnit()->programInfo.functionPointerWithIndirectAccessExists = true;
1482+
module->mockKernelImmData->mockKernelDescriptor->kernelAttributes.flags.useStackCalls = true;
14411483

14421484
kernel->initialize(&desc);
14431485

opencl/source/kernel/kernel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ cl_int Kernel::initialize() {
296296
kernelDescriptor.kernelAttributes.hasNonKernelArgStore ||
297297
kernelDescriptor.kernelAttributes.hasNonKernelArgAtomic ||
298298
kernelDescriptor.kernelAttributes.hasIndirectStatelessAccess ||
299+
(program->getFunctionPointerWithIndirectAccessExists() && kernelDescriptor.kernelAttributes.flags.useStackCalls) ||
299300
NEO::KernelHelper::isAnyArgumentPtrByValue(kernelDescriptor);
300301
} else {
301302
this->kernelHasIndirectAccess = true;

opencl/source/program/process_device_binary.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) {
289289
}
290290

291291
indirectDetectionVersion = src.indirectDetectionVersion;
292+
functionPointerWithIndirectAccessExists = src.functionPointerWithIndirectAccessExists;
292293

293294
return linkBinary(&clDevice.getDevice(), src.globalConstants.initData, src.globalConstants.size, src.globalVariables.initData,
294295
src.globalVariables.size, src.globalStrings, src.externalFunctions);

opencl/source/program/program.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ class Program : public BaseObject<_cl_program> {
247247
MOCKABLE_VIRTUAL std::string getInternalOptions() const;
248248
uint32_t getMaxRootDeviceIndex() const { return maxRootDeviceIndex; }
249249
uint32_t getIndirectDetectionVersion() const { return indirectDetectionVersion; }
250+
bool getFunctionPointerWithIndirectAccessExists() const { return functionPointerWithIndirectAccessExists; }
250251
void retainForKernel() {
251252
std::unique_lock<std::mutex> lock{lockMutex};
252253
exposedKernels++;
@@ -372,6 +373,7 @@ class Program : public BaseObject<_cl_program> {
372373
ClDeviceVector clDevicesInProgram;
373374

374375
uint32_t indirectDetectionVersion = 0u;
376+
bool functionPointerWithIndirectAccessExists = false;
375377
bool isBuiltIn = false;
376378
bool isGeneratedByIgc = true;
377379

opencl/test/unit_test/kernel/kernel_tests.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2018-2023 Intel Corporation
2+
* Copyright (C) 2018-2024 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -1776,6 +1776,66 @@ HWTEST_F(KernelResidencyTest, givenKernelWithNoKernelArgLoadNorKernelArgStoreNor
17761776
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
17771777
}
17781778

1779+
HWTEST_F(KernelResidencyTest, givenKernelWithExternalFunctionWithIndirectAccessAndDetectIndirectAccessInKernelEnabledThenKernelHasIndirectAccessIsSetToTrue) {
1780+
DebugManagerStateRestore restorer;
1781+
debugManager.flags.DetectIndirectAccessInKernel.set(1);
1782+
auto pKernelInfo = std::make_unique<KernelInfo>();
1783+
pKernelInfo->kernelDescriptor.kernelAttributes.simdSize = 1;
1784+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgLoad = false;
1785+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgStore = false;
1786+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgAtomic = false;
1787+
pKernelInfo->kernelDescriptor.kernelAttributes.hasIndirectStatelessAccess = false;
1788+
pKernelInfo->kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
1789+
1790+
auto &commandStreamReceiver = pDevice->getUltCommandStreamReceiver<FamilyType>();
1791+
commandStreamReceiver.storeMakeResidentAllocations = true;
1792+
1793+
auto memoryManager = commandStreamReceiver.getMemoryManager();
1794+
pKernelInfo->kernelAllocation = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{pDevice->getRootDeviceIndex(), MemoryConstants::pageSize});
1795+
1796+
MockProgram program(toClDeviceVector(*pClDevice));
1797+
MockContext ctx;
1798+
program.setContext(&ctx);
1799+
program.buildInfos[pDevice->getRootDeviceIndex()].globalSurface = new MockGraphicsAllocation();
1800+
program.functionPointerWithIndirectAccessExists = true;
1801+
std::unique_ptr<MockKernel> kernel(new MockKernel(&program, *pKernelInfo, *pClDevice));
1802+
ASSERT_EQ(CL_SUCCESS, kernel->initialize());
1803+
1804+
EXPECT_TRUE(kernel->getHasIndirectAccess());
1805+
1806+
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
1807+
}
1808+
1809+
HWTEST_F(KernelResidencyTest, givenKernelWithExternalFunctionWithIndirectAccessButNoUseStackCallsAndDetectIndirectAccessInKernelEnabledThenKernelHasIndirectAccessIsSetToFalse) {
1810+
DebugManagerStateRestore restorer;
1811+
debugManager.flags.DetectIndirectAccessInKernel.set(1);
1812+
auto pKernelInfo = std::make_unique<KernelInfo>();
1813+
pKernelInfo->kernelDescriptor.kernelAttributes.simdSize = 1;
1814+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgLoad = false;
1815+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgStore = false;
1816+
pKernelInfo->kernelDescriptor.kernelAttributes.hasNonKernelArgAtomic = false;
1817+
pKernelInfo->kernelDescriptor.kernelAttributes.hasIndirectStatelessAccess = false;
1818+
pKernelInfo->kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
1819+
1820+
auto &commandStreamReceiver = pDevice->getUltCommandStreamReceiver<FamilyType>();
1821+
commandStreamReceiver.storeMakeResidentAllocations = true;
1822+
1823+
auto memoryManager = commandStreamReceiver.getMemoryManager();
1824+
pKernelInfo->kernelAllocation = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{pDevice->getRootDeviceIndex(), MemoryConstants::pageSize});
1825+
1826+
MockProgram program(toClDeviceVector(*pClDevice));
1827+
MockContext ctx;
1828+
program.setContext(&ctx);
1829+
program.buildInfos[pDevice->getRootDeviceIndex()].globalSurface = new MockGraphicsAllocation();
1830+
program.functionPointerWithIndirectAccessExists = true;
1831+
std::unique_ptr<MockKernel> kernel(new MockKernel(&program, *pKernelInfo, *pClDevice));
1832+
ASSERT_EQ(CL_SUCCESS, kernel->initialize());
1833+
1834+
EXPECT_FALSE(kernel->getHasIndirectAccess());
1835+
1836+
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
1837+
}
1838+
17791839
HWTEST_F(KernelResidencyTest, givenKernelWithPtrByValueArgumentAndDetectIndirectAccessInKernelEnabledThenKernelHasIndirectAccessIsSetToTrue) {
17801840
DebugManagerStateRestore restorer;
17811841
debugManager.flags.DetectIndirectAccessInKernel.set(1);

opencl/test/unit_test/mocks/mock_program.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2018-2023 Intel Corporation
2+
* Copyright (C) 2018-2024 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -55,6 +55,7 @@ class MockProgram : public Program {
5555
using Program::deviceBuildInfos;
5656
using Program::disableZebinIfVmeEnabled;
5757
using Program::extractInternalOptions;
58+
using Program::functionPointerWithIndirectAccessExists;
5859
using Program::getKernelInfo;
5960
using Program::getModuleAllocations;
6061
using Program::internalOptionsToExtract;

shared/source/device_binary_format/zebin/zeinfo_decoder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "shared/source/compiler_interface/external_functions.h"
1111
#include "shared/source/debug_settings/debug_settings_manager.h"
12+
#include "shared/source/device_binary_format/zebin/zebin_elf.h"
1213
#include "shared/source/device_binary_format/zebin/zeinfo_enum_lookup.h"
1314
#include "shared/source/helpers/aligned_memory.h"
1415
#include "shared/source/helpers/basic_math.h"
@@ -494,6 +495,9 @@ DecodeError decodeZeInfoKernels(ProgramInfo &dst, Yaml::YamlParser &parser, cons
494495
if (DecodeError::success != zeInfoErr) {
495496
return zeInfoErr;
496497
}
498+
if (kernelInfo->kernelDescriptor.kernelMetadata.kernelName == Zebin::Elf::SectionNames::externalFunctions) {
499+
dst.functionPointerWithIndirectAccessExists |= kernelInfo->kernelDescriptor.kernelAttributes.hasIndirectStatelessAccess;
500+
}
497501

498502
dst.kernelInfos.push_back(kernelInfo.release());
499503
}

shared/source/program/program_info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct ProgramInfo {
4848
uint32_t minScratchSpaceSize = 0U;
4949
uint32_t indirectDetectionVersion = 0U;
5050
size_t kernelMiscInfoPos = std::string::npos;
51+
bool functionPointerWithIndirectAccessExists = false;
5152
};
5253

5354
size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo);

shared/test/common/mocks/mock_modules_zebin.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2020-2023 Intel Corporation
2+
* Copyright (C) 2020-2024 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -69,6 +69,7 @@ struct ZebinWithExternalFunctionsInfo {
6969
- name: Intel_Symbol_Table_Void_Program
7070
execution_env:
7171
simd_size: 8
72+
indirect_stateless_count: 1
7273
functions:
7374
- name: fun0
7475
execution_env:

0 commit comments

Comments
 (0)