https://github.com/adurang created https://github.com/llvm/llvm-project/pull/226441
<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub> >From 3aa18fd7354249e7b4d19880037afc068cf12d7b Mon Sep 17 00:00:00 2001 From: "Duran, Alex" <[email protected]> Date: Mon, 7 Sep 2026 03:17:04 -0700 Subject: [PATCH] [OFFLOAD] Add olIterateCompatibleDevices API --- offload/liboffload/API/Program.td | 15 ++++ offload/liboffload/src/OffloadImpl.cpp | 26 +++++++ offload/unittests/OffloadAPI/CMakeLists.txt | 1 + .../program/olIterateCompatibleDevices.cpp | 73 +++++++++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 offload/unittests/OffloadAPI/program/olIterateCompatibleDevices.cpp diff --git a/offload/liboffload/API/Program.td b/offload/liboffload/API/Program.td index ecc8fb73dad3f..9f945872aec3c 100644 --- a/offload/liboffload/API/Program.td +++ b/offload/liboffload/API/Program.td @@ -46,6 +46,21 @@ def olIsValidBinary : Function { let returns = []; } +def olIterateCompatibleDevices : Function { + let desc = "Iterates over all available devices that are compatible with the binary image pointed to by `ProgData`, calling the callback for each device."; + let details = [ + "The provided `ProgData` will not be loaded onto any device", + "If the user-provided callback returns `false`, the iteration is stopped." + ]; + let params = [ + Param<"const void*", "ProgData", "pointer to the program binary data", PARAM_IN>, + Param<"size_t", "ProgDataSize", "size of the program binary in bytes", PARAM_IN>, + Param<"ol_device_iterate_cb_t", "Callback", "User-provided function called for each compatible device", PARAM_IN>, + Param<"void*", "UserData", "Optional user data to pass to the callback", PARAM_IN_OPTIONAL> + ]; + let returns = []; +} + def olDestroyProgram : Function { let desc = "Destroy the program and free all underlying resources."; let details = []; diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp index d1ad05ba0ba40..76f6d54a1fc21 100644 --- a/offload/liboffload/src/OffloadImpl.cpp +++ b/offload/liboffload/src/OffloadImpl.cpp @@ -1158,6 +1158,32 @@ Error olIsValidBinary_impl(ol_device_handle_t Device, const void *ProgData, return Error::success(); } +Error olIterateCompatibleDevices_impl(const void *ProgData, size_t ProgDataSize, + ol_device_iterate_cb_t Callback, + void *UserData) { + StringRef Buffer(reinterpret_cast<const char *>(ProgData), ProgDataSize); + + for (auto &Platform : OffloadContext::get().Platforms) { + if (!Platform->Plugin || !Platform->Plugin->isPluginCompatible(Buffer)) + continue; + + // If the image is compatible, initialize the platform. + if (auto Err = Platform->init()) + return Err; + + for (auto &Device : Platform->Devices) { + if (!Device->Platform.Plugin->isDeviceCompatible(Device->DeviceNum, + Buffer)) + continue; + + if (!Callback(Device.get(), UserData)) + return Error::success(); + } + } + + return Error::success(); +} + Error olDestroyProgram_impl(ol_program_handle_t Program) { auto &Device = Program->Image->getDevice(); if (auto Err = Device.unloadBinary(Program->Image)) diff --git a/offload/unittests/OffloadAPI/CMakeLists.txt b/offload/unittests/OffloadAPI/CMakeLists.txt index 292ea1eb4852f..8bed11be4d85e 100644 --- a/offload/unittests/OffloadAPI/CMakeLists.txt +++ b/offload/unittests/OffloadAPI/CMakeLists.txt @@ -49,6 +49,7 @@ add_offload_unittest("platform" add_offload_unittest("program" program/olCreateProgram.cpp program/olIsValidBinary.cpp + program/olIterateCompatibleDevices.cpp program/olDestroyProgram.cpp) add_offload_unittest("queue" diff --git a/offload/unittests/OffloadAPI/program/olIterateCompatibleDevices.cpp b/offload/unittests/OffloadAPI/program/olIterateCompatibleDevices.cpp new file mode 100644 index 0000000000000..afa26c57d6728 --- /dev/null +++ b/offload/unittests/OffloadAPI/program/olIterateCompatibleDevices.cpp @@ -0,0 +1,73 @@ +//===------- Offload API tests - olIterateCompatibleDevices -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "../common/Fixtures.hpp" +#include <OffloadAPI.h> +#include <gtest/gtest.h> + +using olIterateCompatibleDevicesTest = OffloadDeviceTest; +OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(olIterateCompatibleDevicesTest); + +TEST_P(olIterateCompatibleDevicesTest, Success) { + std::unique_ptr<llvm::MemoryBuffer> DeviceBin; + ASSERT_TRUE(TestEnvironment::loadDeviceBinary("foo", Device, DeviceBin)); + ASSERT_GE(DeviceBin->getBufferSize(), 0lu); + + struct CallbackDataTy { + ol_device_handle_t ExpectedDevice; + bool Found = false; + } CallbackData{Device}; + + ASSERT_SUCCESS(olIterateCompatibleDevices( + DeviceBin->getBufferStart(), DeviceBin->getBufferSize(), + [](ol_device_handle_t D, void *UserData) { + auto *Data = static_cast<CallbackDataTy *>(UserData); + if (D == Data->ExpectedDevice) + Data->Found = true; + return true; + }, + &CallbackData)); + + ASSERT_TRUE(CallbackData.Found); +} + +TEST_P(olIterateCompatibleDevicesTest, SuccessStopIteration) { + std::unique_ptr<llvm::MemoryBuffer> DeviceBin; + ASSERT_TRUE(TestEnvironment::loadDeviceBinary("foo", Device, DeviceBin)); + ASSERT_GE(DeviceBin->getBufferSize(), 0lu); + + uint32_t CallCount = 0; + ASSERT_SUCCESS(olIterateCompatibleDevices( + DeviceBin->getBufferStart(), DeviceBin->getBufferSize(), + [](ol_device_handle_t, void *UserData) { + auto *Count = static_cast<uint32_t *>(UserData); + *Count += 1; + return false; + }, + &CallCount)); + + ASSERT_EQ(CallCount, 1u); +} + +TEST_P(olIterateCompatibleDevicesTest, EmptyBinary) { + std::unique_ptr<llvm::MemoryBuffer> DeviceBin; + ASSERT_TRUE(TestEnvironment::loadDeviceBinary("foo", Device, DeviceBin)); + ASSERT_GE(DeviceBin->getBufferSize(), 0lu); + + uint32_t CallCount = 0; + ASSERT_SUCCESS(olIterateCompatibleDevices( + DeviceBin->getBufferStart(), 0, + [](ol_device_handle_t, void *UserData) { + auto *Count = static_cast<uint32_t *>(UserData); + *Count += 1; + return true; + }, + &CallCount)); + + ASSERT_EQ(CallCount, 0u); +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
