[llvm-branch-commits] [llvm] [offload][omp] Use liboffload queues for memory operations (PR #221278)
Alex Duran via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 4 09:30:20 PDT 2026
https://github.com/adurang created https://github.com/llvm/llvm-project/pull/221278
None
>From 4c59b842d97a70b3dc01de1c4f836134ab5340ba Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 07:43:13 -0700
Subject: [PATCH 01/14] [offload][omp] link libomptarget against liboffload
---
offload/liboffload/exports | 58 ++++++++++++++++++++++++++
offload/liboffload/src/OffloadImpl.cpp | 12 ++++--
offload/libomptarget/CMakeLists.txt | 10 ++---
offload/libomptarget/exports | 6 +++
offload/libomptarget/interface.cpp | 3 ++
5 files changed, 81 insertions(+), 8 deletions(-)
diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index 168341aa7d938..5487e16168681 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -1,6 +1,64 @@
VERS1.0 {
global:
ol*;
+ # Symbols currently used by libomptarget. They should be removed from here as
+ # they become replaced by calls to the liboffload API.
+ # No new symbols should be added here.
+ extern "C++" {
+ error::OffloadError::ID;
+ "error::OffloadErrCategory()";
+ "llvm::omp::target::RPCServerTy::registerCallback(unsigned int (*)(void*, unsigned int))";
+ "llvm::omp::target::plugin::GenericDeviceTy::dataFill(void*, void const*, long, long, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::async_barrier(omp_interop_val_t*)";
+ "llvm::omp::target::plugin::GenericPluginTy::create_event(int, void**)";
+ "llvm::omp::target::plugin::GenericPluginTy::create_interop(int, int, interop_spec_t*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_alloc(int, long, void*, int)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_delete(int, void*, int)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_exchange(int, void*, int, void*, long)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_exchange_async(int, void*, int, void*, long, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_fence(int, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_lock(int, void*, long, void**)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_notify_mapped(int, void*, long)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_notify_unmapped(int, void*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_retrieve_async(int, void*, void*, long, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_submit(int, void*, void*, long)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_submit_async(int, void*, void*, long, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::data_unlock(int, void*)";
+ "llvm::omp::target::plugin::GenericPluginTy::destroy_event(int, void*)";
+ "llvm::omp::target::plugin::GenericPluginTy::flush_queue(omp_interop_val_t*)";
+ "llvm::omp::target::plugin::GenericPluginTy::get_function(__tgt_device_binary, char const*, void**)";
+ "llvm::omp::target::plugin::GenericPluginTy::get_global(__tgt_device_binary, unsigned long, char const*, void**)";
+ "llvm::omp::target::plugin::GenericPluginTy::init()";
+ "llvm::omp::target::plugin::GenericPluginTy::deinit()";
+ "llvm::omp::target::plugin::GenericPluginTy::init_device(int)";
+ "llvm::omp::target::plugin::GenericPluginTy::initialize_record_replay(int, long, void*, bool, bool, bool, bool, char const*, char const*)";
+ "llvm::omp::target::plugin::GenericPluginTy::isDeviceCompatible(int, llvm::StringRef)";
+ "llvm::omp::target::plugin::GenericPluginTy::isPluginCompatible(llvm::StringRef)";
+ "llvm::omp::target::plugin::GenericPluginTy::is_accessible_ptr(int, void const*, unsigned long)";
+ "llvm::omp::target::plugin::GenericPluginTy::is_data_exchangable(int, int)";
+ "llvm::omp::target::plugin::GenericPluginTy::is_device_initialized(int) const";
+ "llvm::omp::target::plugin::GenericPluginTy::is_initialized() const";
+ "llvm::omp::target::plugin::GenericPluginTy::launch_kernel(int, void*, llvm::omp::target::plugin::KernelLaunchArgsTy&, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::load_binary(int, __tgt_device_image*, __tgt_device_binary*)";
+ "llvm::omp::target::plugin::GenericPluginTy::number_of_devices()";
+ "llvm::omp::target::plugin::GenericPluginTy::obtain_device_info(int)";
+ "llvm::omp::target::plugin::GenericPluginTy::print_device_info(int)";
+ "llvm::omp::target::plugin::GenericPluginTy::query_async(int, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::record_event(int, void*, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::release_interop(int, omp_interop_val_t*)";
+ "llvm::omp::target::plugin::GenericPluginTy::set_device_identifier(int, int)";
+ "llvm::omp::target::plugin::GenericPluginTy::sync_barrier(omp_interop_val_t*)";
+ "llvm::omp::target::plugin::GenericPluginTy::sync_event(int, void*)";
+ "llvm::omp::target::plugin::GenericPluginTy::synchronize(int, __tgt_async_info*)";
+ "llvm::omp::target::plugin::GenericPluginTy::use_auto_zero_copy(int)";
+ "llvm::omp::target::plugin::GenericPluginTy::wait_event(int, void*, __tgt_async_info*)";
+ llvm::omp::target::ompt::Initialized;
+ llvm::omp::target::ompt::lookupCallbackByCode;
+ llvm::omp::target::ompt::lookupCallbackByName;
+ createPlugin_*;
+ # Temporary helpers to help transition of libomptarget to liboffload.
+ __ol_tgt_setInfoFlag;
+ };
local:
*;
};
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 5c0c00f0165f1..6e608e3f965c4 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -29,9 +29,9 @@
#ifdef OMPT_SUPPORT
namespace llvm::omp::target {
namespace ompt {
-bool Initialized = false;
-ompt_get_callback_t lookupCallbackByCode = nullptr;
-ompt_function_lookup_t lookupCallbackByName = nullptr;
+LLVM_ATTRIBUTE_WEAK bool Initialized = false;
+LLVM_ATTRIBUTE_WEAK ompt_get_callback_t lookupCallbackByCode = nullptr;
+LLVM_ATTRIBUTE_WEAK ompt_function_lookup_t lookupCallbackByName = nullptr;
} // namespace ompt
} // namespace llvm::omp::target
#endif
@@ -1472,5 +1472,11 @@ Error olQueryQueue_impl(ol_queue_handle_t Queue, bool *IsQueueWorkCompleted) {
return Error::success();
}
+// Temporary helpers to help transition of libomptarget to liboffload
+extern "C" void __ol_tgt_setInfoFlag(uint32_t NewInfoLevel) {
+ std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal();
+ InfoLevel.store(NewInfoLevel);
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libomptarget/CMakeLists.txt b/offload/libomptarget/CMakeLists.txt
index 403b3e5dad269..d0b24c4ff4e65 100644
--- a/offload/libomptarget/CMakeLists.txt
+++ b/offload/libomptarget/CMakeLists.txt
@@ -28,8 +28,12 @@ else()
llvm_map_components_to_libnames(llvm_libs FrontendOpenMP Support Object)
endif()
target_link_libraries(omptarget PRIVATE omp ${llvm_libs})
+target_link_libraries(omptarget PRIVATE LLVMOffload)
target_include_directories(omptarget PRIVATE
- ${LIBOMPTARGET_INCLUDE_DIR} ${LIBOMPTARGET_BINARY_INCLUDE_DIR}
+ ${LIBOMPTARGET_INCLUDE_DIR}
+ ${LIBOMPTARGET_BINARY_INCLUDE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../plugins-nextgen/common/include
+ ${CMAKE_CURRENT_BINARY_DIR}/../plugins-nextgen/common/include
)
if(LLVM_HAVE_LINK_VERSION_SCRIPT)
@@ -42,10 +46,6 @@ target_compile_definitions(omptarget PRIVATE
DEBUG_PREFIX="omptarget"
)
-foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD)
- target_link_libraries(omptarget PRIVATE omptarget.rtl.${plugin})
-endforeach()
-
target_compile_options(omptarget PRIVATE ${offload_compile_flags})
target_link_options(omptarget PRIVATE ${offload_link_flags})
diff --git a/offload/libomptarget/exports b/offload/libomptarget/exports
index 1831c43cc5f29..6aaddc64cf508 100644
--- a/offload/libomptarget/exports
+++ b/offload/libomptarget/exports
@@ -83,6 +83,12 @@ VERS1.0 {
__llvmPushCallConfiguration;
__llvmPopCallConfiguration;
llvmLaunchKernel;
+ # OMPT symbols that currently need to be seen by liboffload.
+ extern "C++" {
+ llvm::omp::target::ompt::Initialized;
+ llvm::omp::target::ompt::lookupCallbackByCode;
+ llvm::omp::target::ompt::lookupCallbackByName;
+ };
local:
*;
};
diff --git a/offload/libomptarget/interface.cpp b/offload/libomptarget/interface.cpp
index 5d7d948711b99..5b5cc310b1b31 100644
--- a/offload/libomptarget/interface.cpp
+++ b/offload/libomptarget/interface.cpp
@@ -585,10 +585,13 @@ EXTERN void __tgt_push_mapper_component(void *RtMapperHandle, void *Base,
MapComponentInfoTy(Base, Begin, Size, Type, Name));
}
+extern "C" void __ol_tgt_setInfoFlag(uint32_t NewInfoLevel);
EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) {
assert(PM && "Runtime not initialized");
std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal();
InfoLevel.store(NewInfoLevel);
+ // Notify the liboffload runtime about the new info level.
+ __ol_tgt_setInfoFlag(NewInfoLevel);
}
EXTERN int __tgt_print_device_info(int64_t DeviceId) {
>From e09a0da04b33c18f988df09c13d60c9a797800bc Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:32:33 -0700
Subject: [PATCH 02/14] [OFFLOAD] Initialize Platforms and Devices lazily
---
offload/liboffload/src/OffloadImpl.cpp | 308 ++++++++++++++++++-------
1 file changed, 226 insertions(+), 82 deletions(-)
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 6e608e3f965c4..670179c21f054 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -56,9 +56,11 @@ struct ol_platform_impl_t {
/// Initialize the associated plugin and devices.
llvm::Error init();
- /// Direct access to the plugin, may be uninitialized if accessed here.
+ bool Initialized = false;
std::unique_ptr<GenericPluginTy> Plugin;
+ bool isInitialized() const { return Initialized; }
+
llvm::SmallVector<std::unique_ptr<ol_device_impl_t>> Devices;
};
@@ -66,20 +68,58 @@ struct ol_platform_impl_t {
// we add some additional data here for now to avoid churn in the plugin
// interface.
struct ol_device_impl_t {
- ol_device_impl_t(int DeviceNum, GenericDeviceTy *Device,
- ol_platform_impl_t &Platform, InfoTreeNode &&DevInfo)
- : DeviceNum(DeviceNum), Device(Device), Platform(Platform),
- Info(std::forward<InfoTreeNode>(DevInfo)) {}
-
+ ol_device_impl_t(int DeviceNum, ol_platform_impl_t &Platform)
+ : DeviceNum(DeviceNum), Platform(Platform) {}
int DeviceNum;
- GenericDeviceTy *Device;
ol_platform_impl_t &Platform;
+
+ llvm::Error init() {
+ if (!Platform.isInitialized()) {
+ if (auto Err = Platform.init())
+ return Err;
+ }
+
+ if (llvm::Error Err = Platform.Plugin->initDevice(DeviceNum))
+ return Err;
+
+ Device = &Platform.Plugin->getDevice(DeviceNum);
+ llvm::Expected<InfoTreeNode> InfoOrErr = Device->obtainInfo();
+ if (!InfoOrErr)
+ return InfoOrErr.takeError();
+ Info = std::move(*InfoOrErr);
+
+ return llvm::Error::success();
+ }
+
+ llvm::Expected<GenericDeviceTy *> getDevice() {
+ if (!Device) {
+ if (llvm::Error Err = init())
+ return Err;
+ }
+
+ return Device;
+ }
+
+ llvm::Expected<InfoTreeNode &> getInfo() {
+ if (!Device) {
+ if (llvm::Error Err = init())
+ return Err;
+ }
+
+ return Info;
+ }
+private:
+ GenericDeviceTy *Device = nullptr;
InfoTreeNode Info;
};
llvm::Error ol_platform_impl_t::destroy() { return Plugin->deinit(); }
llvm::Error ol_platform_impl_t::init() {
+ if (Initialized)
+ return llvm::Error::success();
+ Initialized = true;
+
if (!Plugin)
return llvm::Error::success();
@@ -87,15 +127,7 @@ llvm::Error ol_platform_impl_t::init() {
return Err;
for (auto Id = 0, End = Plugin->getNumDevices(); Id != End; Id++) {
- if (llvm::Error Err = Plugin->initDevice(Id))
- return Err;
-
- GenericDeviceTy *Device = &Plugin->getDevice(Id);
- llvm::Expected<InfoTreeNode> Info = Device->obtainInfo();
- if (llvm::Error Err = Info.takeError())
- return Err;
- Devices.emplace_back(std::make_unique<ol_device_impl_t>(Id, Device, *this,
- std::move(*Info)));
+ Devices.emplace_back(std::make_unique<ol_device_impl_t>(Id, *this));
}
return llvm::Error::success();
@@ -189,10 +221,12 @@ struct ol_context_impl_t {
return nullptr;
auto &Bucket = It->second;
+ GenericDeviceTy *DeviceImpl = llvm::cantFail(Device->getDevice());
+
// As queues are pulled and popped from this list, longer running queues
// naturally bubble to the start of the array. Hence looping backwards.
for (auto Q = Bucket.rbegin(); Q != Bucket.rend(); Q++) {
- if (!Device->Device->hasPendingWork(*Q)) {
+ if (!DeviceImpl->hasPendingWork(*Q)) {
auto OutstandingQueue = *Q;
*Q = Bucket.back();
Bucket.pop_back();
@@ -214,8 +248,13 @@ struct ol_context_impl_t {
llvm::Error Result = Plugin::success();
for (auto &Bucket : OutstandingQueues) {
auto *Device = Bucket.first;
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr) {
+ Result = llvm::joinErrors(std::move(Result), DeviceOrErr.takeError());
+ continue;
+ }
for (auto *AI : Bucket.second)
- if (auto Err = Device->Device->synchronize(AI, /*Release=*/true))
+ if (auto Err = (*DeviceOrErr)->synchronize(AI, /*Release=*/true))
Result = llvm::joinErrors(std::move(Result), std::move(Err));
}
OutstandingQueues.clear();
@@ -326,14 +365,6 @@ Error initPlugins(OffloadContext &Context, const ol_init_args_t *InitArgs) {
} while (false);
#include "Shared/Targets.def"
- // Eagerly initialize all of the plugins and devices. We need to make sure
- // that the platform is initialized at a consistent point to maintain the
- // expected teardown order in the vendor libraries.
- for (auto &Platform : Context.Platforms) {
- if (Error Err = Platform->init())
- return Err;
- }
-
Context.TracingEnabled = std::getenv("OFFLOAD_TRACE");
Context.ValidationEnabled = !std::getenv("OFFLOAD_DISABLE_VALIDATION");
@@ -378,7 +409,8 @@ Error olShutDown_impl() {
for (auto &Platform : OldContext->Platforms) {
// Host plugin is nullptr and has no deinit
- if (!Platform->Plugin || !Platform->Plugin->is_initialized())
+ if (!Platform->isInitialized() || !Platform->Plugin ||
+ !Platform->Plugin->is_initialized())
continue;
if (auto Res = Platform->destroy())
@@ -476,8 +508,11 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
// AMD doesn't provide the global memory size (trivially) with the device info
// struct, so use the plugin interface
case OL_DEVICE_INFO_GLOBAL_MEM_SIZE: {
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
uint64_t Mem;
- if (auto Err = Device->Device->getDeviceMemorySize(Mem))
+ if (auto Err = (*DeviceOrErr)->getDeviceMemorySize(Mem))
return Err;
return Info.write<uint64_t>(Mem);
} break;
@@ -490,7 +525,11 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
return createOffloadError(ErrorCode::INVALID_ENUMERATION,
"getDeviceInfo enum '%i' is invalid", PropName);
- auto EntryOpt = Device->Info.get(static_cast<DeviceInfo>(PropName));
+ auto InfoOrErr = Device->getInfo();
+ if (!InfoOrErr)
+ return InfoOrErr.takeError();
+
+ auto EntryOpt = InfoOrErr->get(static_cast<DeviceInfo>(PropName));
if (!EntryOpt)
return makeError(ErrorCode::UNIMPLEMENTED,
"plugin did not provide a response for this information");
@@ -603,6 +642,8 @@ Error olGetDeviceInfoSize_impl(ol_device_handle_t Device,
Error olIterateDevices_impl(ol_device_iterate_cb_t Callback, void *UserData) {
for (auto &Platform : OffloadContext::get().Platforms) {
+ if (auto Err = Platform->init())
+ return Err;
for (auto &Device : Platform->Devices) {
if (!Callback(Device.get(), UserData)) {
return Error::success();
@@ -626,14 +667,20 @@ Error olCreateContext_impl(size_t DevicesCount, ol_device_handle_t *Devices,
ErrorCode::INVALID_DEVICE,
"all devices in a context must belong to the same platform");
DeviceList.push_back(Devices[I]);
- PluginDevices.push_back(Devices[I]->Device);
+ auto DeviceOrErr = Devices[I]->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ PluginDevices.push_back(*DeviceOrErr);
}
// The host plugin has no GenericPluginTy instance; skip the plugin-side
// context in that case and just record the device set.
std::unique_ptr<plugin::PluginContextTy> PluginCtx;
if (Platform->Plugin) {
- auto PluginCtxOrErr = Platform->Plugin->createPluginContext(PluginDevices);
+ if (auto Err = Platform->init())
+ return Err;
+ auto PluginCtxOrErr =
+ Platform->Plugin->createPluginContext(PluginDevices);
if (!PluginCtxOrErr)
return PluginCtxOrErr.takeError();
PluginCtx = std::move(*PluginCtxOrErr);
@@ -698,13 +745,18 @@ constexpr size_t MAX_ALLOC_TRIES = 50;
Error olMemAllocImplHelper(ol_device_handle_t Device, ol_alloc_type_t Type,
size_t Size, size_t Alignment,
void **AllocationOut) {
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ GenericDeviceTy *DeviceImpl = *DeviceOrErr;
+
SmallVector<void *> Rejects;
// Repeat the allocation up to a certain amount of times. If it happens to
// already be allocated (e.g. by a device from another vendor) throw it away
// and try again.
for (size_t Count = 0; Count < MAX_ALLOC_TRIES; Count++) {
- auto NewAlloc = Device->Device->dataAlloc(
+ auto NewAlloc = DeviceImpl->dataAlloc(
Size, nullptr, convertOlToPluginAllocTy(Type), Alignment);
if (!NewAlloc)
return NewAlloc.takeError();
@@ -736,7 +788,7 @@ Error olMemAllocImplHelper(ol_device_handle_t Device, ol_alloc_type_t Type,
for (void *R : Rejects)
if (auto Err =
- Device->Device->dataDelete(R, convertOlToPluginAllocTy(Type)))
+ DeviceImpl->dataDelete(R, convertOlToPluginAllocTy(Type)))
return Err;
return Error::success();
}
@@ -800,8 +852,12 @@ Error olMemFree_impl(void *Address) {
Bases.erase(std::lower_bound(Bases.begin(), Bases.end(), Address));
}
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
if (auto Res =
- Device->Device->dataDelete(Address, convertOlToPluginAllocTy(Type)))
+ (*DeviceOrErr)->dataDelete(Address, convertOlToPluginAllocTy(Type)))
return Res;
return Error::success();
@@ -868,16 +924,20 @@ Error olCreateQueue_impl(ol_context_handle_t Context, ol_device_handle_t Device,
auto CreatedQueue =
std::make_unique<ol_queue_impl_t>(nullptr, Context, Device);
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
auto OutstandingQueue = Context->getOutstandingQueue(Device);
if (OutstandingQueue) {
// The queue is empty, but we still need to sync it to release any temporary
// memory allocations or do other cleanup.
if (auto Err =
- Device->Device->synchronize(OutstandingQueue, /*Release=*/false))
+ (*DeviceOrErr)->synchronize(OutstandingQueue, /*Release=*/false))
return Err;
CreatedQueue->AsyncInfo = OutstandingQueue;
} else if (auto Err = Context->PluginCtx->initAsyncInfo(
- *Device->Device, &(CreatedQueue->AsyncInfo))) {
+ **DeviceOrErr, &(CreatedQueue->AsyncInfo))) {
return Err;
}
@@ -888,17 +948,22 @@ Error olCreateQueue_impl(ol_context_handle_t Context, ol_device_handle_t Device,
Error olDestroyQueue_impl(ol_queue_handle_t Queue) {
auto *Device = Queue->Device;
auto *Context = Queue->Context;
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *DeviceImpl = *DeviceOrErr;
+
// This is safe; as soon as olDestroyQueue is called it is not possible to add
// any more work to the queue, so if it's finished now it will remain finished
// forever.
- auto Res = Device->Device->hasPendingWork(Queue->AsyncInfo);
+ auto Res = DeviceImpl->hasPendingWork(Queue->AsyncInfo);
if (!Res)
return Res.takeError();
if (!*Res) {
// The queue is complete, so sync it and throw it back into the pool.
- if (auto Err = Device->Device->synchronize(Queue->AsyncInfo,
- /*Release=*/true))
+ if (auto Err = DeviceImpl->synchronize(Queue->AsyncInfo,
+ /*Release=*/true))
return Err;
} else {
// The queue still has outstanding work. Store it so we can check it later.
@@ -915,7 +980,10 @@ Error olSyncQueue_impl(ol_queue_handle_t Queue) {
// We don't need to release the queue and we would like the ability for
// other offload threads to submit work concurrently, so pass "false" here
// so we don't release the underlying queue object.
- if (auto Err = Queue->Device->Device->synchronize(Queue->AsyncInfo, false))
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ if (auto Err = (*DeviceOrErr)->synchronize(Queue->AsyncInfo, false))
return Err;
}
@@ -924,7 +992,10 @@ Error olSyncQueue_impl(ol_queue_handle_t Queue) {
Error olWaitEvents_impl(ol_queue_handle_t Queue, ol_event_handle_t *Events,
size_t NumEvents) {
- auto *Device = Queue->Device->Device;
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *Device = *DeviceOrErr;
for (size_t I = 0; I < NumEvents; I++) {
auto *Event = Events[I];
@@ -956,7 +1027,10 @@ Error olGetQueueInfoImplDetail(ol_queue_handle_t Queue,
case OL_QUEUE_INFO_CONTEXT:
return Info.write<ol_context_handle_t>(Queue->Context);
case OL_QUEUE_INFO_EMPTY: {
- auto Pending = Queue->Device->Device->hasPendingWork(Queue->AsyncInfo);
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto Pending = (*DeviceOrErr)->hasPendingWork(Queue->AsyncInfo);
if (auto Err = Pending.takeError())
return Err;
return Info.write<bool>(!*Pending);
@@ -984,7 +1058,11 @@ Error olSyncEvent_impl(ol_event_handle_t Event) {
if (!Event->EventInfo)
return Plugin::success();
- if (auto Res = Event->Device->Device->syncEvent(Event->EventInfo))
+ auto DeviceOrErr = Event->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
+ if (auto Res = (*DeviceOrErr)->syncEvent(Event->EventInfo))
return Res;
return Error::success();
@@ -1004,7 +1082,11 @@ Error olGetEventElapsedTime_impl(ol_event_handle_t StartEvent,
ErrorCode::INVALID_DEVICE,
"StartEvent and EndEvent must belong to the same device");
- auto ElapsedTimeOrErr = StartEvent->Device->Device->getEventElapsedTime(
+ auto DeviceOrErr = StartEvent->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
+ auto ElapsedTimeOrErr = (*DeviceOrErr)->getEventElapsedTime(
StartEvent->EventInfo, EndEvent->EventInfo);
if (!ElapsedTimeOrErr)
return ElapsedTimeOrErr.takeError();
@@ -1014,10 +1096,14 @@ Error olGetEventElapsedTime_impl(ol_event_handle_t StartEvent,
}
Error olDestroyEvent_impl(ol_event_handle_t Event) {
- if (Event->EventInfo)
- if (auto Res = Event->Device->Device->destroyEvent(Event->EventInfo,
- Event->ProfilingEnabled))
+ if (Event->EventInfo) {
+ auto DeviceOrErr = Event->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ if (auto Res = (*DeviceOrErr)->destroyEvent(Event->EventInfo,
+ Event->ProfilingEnabled))
return Res;
+ }
return olDestroy(Event);
}
@@ -1037,8 +1123,11 @@ Error olGetEventInfoImplDetail(ol_event_handle_t Event,
if (!Event->EventInfo)
return Info.write<bool>(true);
- auto Res = Queue->Device->Device->isEventComplete(Event->EventInfo,
- Queue->AsyncInfo);
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto Res = (*DeviceOrErr)->isEventComplete(Event->EventInfo,
+ Queue->AsyncInfo);
if (auto Err = Res.takeError())
return Err;
return Info.write<bool>(*Res);
@@ -1067,14 +1156,18 @@ Error olCreateEvent_impl(ol_queue_handle_t Queue, ol_event_flags_t Flags,
auto Event = std::make_unique<ol_event_impl_t>(nullptr, Queue->Device, Queue,
EnableProfiling);
- if (auto Err = Queue->Device->Device->createEvent(&Event->EventInfo,
- EnableProfiling))
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *DeviceImpl = *DeviceOrErr;
+
+ if (auto Err = DeviceImpl->createEvent(&Event->EventInfo, EnableProfiling))
return Err;
- if (auto Err = Queue->Device->Device->recordEvent(
+ if (auto Err = DeviceImpl->recordEvent(
Event->EventInfo, Queue->AsyncInfo, EnableProfiling)) {
if (Event->EventInfo) {
- if (auto DestroyErr = Queue->Device->Device->destroyEvent(
+ if (auto DestroyErr = DeviceImpl->destroyEvent(
Event->EventInfo, EnableProfiling))
return joinErrors(std::move(Err), std::move(DestroyErr));
}
@@ -1092,14 +1185,26 @@ Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr,
bool IsDstHost = DstDevice->Platform.BackendType == OL_PLATFORM_BACKEND_HOST;
bool IsSrcHost = SrcDevice->Platform.BackendType == OL_PLATFORM_BACKEND_HOST;
+ auto DstDeviceImplOrErr = DstDevice->getDevice();
+ if (!DstDeviceImplOrErr)
+ return DstDeviceImplOrErr.takeError();
+ auto SrcDeviceImplOrErr = SrcDevice->getDevice();
+ if (!SrcDeviceImplOrErr)
+ return SrcDeviceImplOrErr.takeError();
+ auto *DstDeviceImpl = *DstDeviceImplOrErr;
+ auto *SrcDeviceImpl = *SrcDeviceImplOrErr;
+
if (IsDstHost && IsSrcHost) {
if (!Queue) {
std::memcpy(DstPtr, SrcPtr, Size);
return Error::success();
}
- return Queue->Device->Device->dataMemcpy(DstPtr, SrcPtr, Size,
- Queue->AsyncInfo);
+ auto QueueDeviceOrErr = Queue->Device->getDevice();
+ if (!QueueDeviceOrErr)
+ return QueueDeviceOrErr.takeError();
+ return (*QueueDeviceOrErr)->dataMemcpy(DstPtr, SrcPtr, Size,
+ Queue->AsyncInfo);
}
// If no queue is given the memcpy will be synchronous
@@ -1107,18 +1212,19 @@ Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr,
if (IsDstHost) {
if (auto Res =
- SrcDevice->Device->dataRetrieve(DstPtr, SrcPtr, Size, QueueImpl))
+ SrcDeviceImpl->dataRetrieve(DstPtr, SrcPtr, Size, QueueImpl))
return Res;
} else if (IsSrcHost) {
if (auto Res =
- DstDevice->Device->dataSubmit(DstPtr, SrcPtr, Size, QueueImpl))
+ DstDeviceImpl->dataSubmit(DstPtr, SrcPtr, Size, QueueImpl))
return Res;
- } else if (SrcDevice->Platform.Plugin == DstDevice->Platform.Plugin &&
+ } else if (SrcDevice->Platform.Plugin ==
+ DstDevice->Platform.Plugin &&
SrcDevice->Platform.Plugin->isDataExchangable(
- SrcDevice->Device->getDeviceId(),
- DstDevice->Device->getDeviceId())) {
- if (auto Res = SrcDevice->Device->dataExchange(SrcPtr, *DstDevice->Device,
- DstPtr, Size, QueueImpl))
+ SrcDeviceImpl->getDeviceId(),
+ DstDeviceImpl->getDeviceId())) {
+ if (auto Res = SrcDeviceImpl->dataExchange(SrcPtr, *DstDeviceImpl,
+ DstPtr, Size, QueueImpl))
return Res;
} else {
if (Queue)
@@ -1129,9 +1235,9 @@ Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr,
if (!Buffer)
return createOffloadError(ErrorCode::OUT_OF_RESOURCES,
"Couldn't allocate a buffer for transfer");
- Error Res = SrcDevice->Device->dataRetrieve(Buffer, SrcPtr, Size, nullptr);
+ Error Res = SrcDeviceImpl->dataRetrieve(Buffer, SrcPtr, Size, nullptr);
if (!Res)
- Res = DstDevice->Device->dataSubmit(DstPtr, Buffer, Size, nullptr);
+ Res = DstDeviceImpl->dataSubmit(DstPtr, Buffer, Size, nullptr);
free(Buffer);
return Res;
@@ -1142,8 +1248,11 @@ Error olMemcpy_impl(ol_queue_handle_t Queue, void *DstPtr,
Error olMemFill_impl(ol_queue_handle_t Queue, void *Ptr, size_t PatternSize,
const void *PatternPtr, size_t FillSize) {
- return Queue->Device->Device->dataFill(Ptr, PatternPtr, PatternSize, FillSize,
- Queue->AsyncInfo);
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ return (*DeviceOrErr)->dataFill(Ptr, PatternPtr, PatternSize, FillSize,
+ Queue->AsyncInfo);
}
Error olMemPrefetch_impl(ol_queue_handle_t Queue, size_t Count,
@@ -1153,8 +1262,11 @@ Error olMemPrefetch_impl(ol_queue_handle_t Queue, size_t Count,
return Error::success();
bool ToHost = (Flags & OL_MEM_MIGRATION_FLAG_DEVICE_TO_HOST) != 0;
- return Queue->Device->Device->dataPrefetch(Count, Mems, Sizes, ToHost,
- Queue->AsyncInfo);
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ return (*DeviceOrErr)->dataPrefetch(Count, Mems, Sizes, ToHost,
+ Queue->AsyncInfo);
}
Error olCreateProgram_impl(ol_context_handle_t Context,
@@ -1165,8 +1277,13 @@ Error olCreateProgram_impl(ol_context_handle_t Context,
"device does not belong to the given context");
StringRef Buffer(reinterpret_cast<const char *>(ProgData), ProgDataSize);
- Expected<plugin::DeviceImageTy *> Res = Device->Device->loadBinary(
- Device->Device->Plugin, Buffer, Context->PluginCtx.get());
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *DeviceImpl = *DeviceOrErr;
+
+ Expected<plugin::DeviceImageTy *> Res = DeviceImpl->loadBinary(
+ DeviceImpl->Plugin, Buffer, Context->PluginCtx.get());
if (!Res)
return Res.takeError();
assert(*Res && "loadBinary returned nullptr");
@@ -1178,9 +1295,12 @@ Error olCreateProgram_impl(ol_context_handle_t Context,
Error olIsValidBinary_impl(ol_device_handle_t Device, const void *ProgData,
size_t ProgDataSize, bool *IsValid) {
StringRef Buffer(reinterpret_cast<const char *>(ProgData), ProgDataSize);
- *IsValid = Device->Device ? Device->Device->Plugin.isDeviceCompatible(
- Device->Device->getDeviceId(), Buffer)
- : false;
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *DeviceImpl = *DeviceOrErr;
+ *IsValid =
+ DeviceImpl->Plugin.isDeviceCompatible(DeviceImpl->getDeviceId(), Buffer);
return Error::success();
}
@@ -1205,7 +1325,11 @@ Error olCalculateOptimalOccupancy_impl(ol_device_handle_t Device,
"provided symbol is not a kernel");
auto *KernelImpl = std::get<GenericKernelTy *>(Kernel->PluginImpl);
- auto Res = KernelImpl->maxGroupSize(*Device->Device, DynamicMemSize);
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
+ auto Res = KernelImpl->maxGroupSize(**DeviceOrErr, DynamicMemSize);
if (auto Err = Res.takeError())
return Err;
@@ -1222,7 +1346,10 @@ Error olGetKernelMaxCooperativeGroupCount_impl(
return createOffloadError(ErrorCode::SYMBOL_KIND,
"provided symbol is not a kernel");
- GenericDeviceTy *DeviceImpl = Device->Device;
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ GenericDeviceTy *DeviceImpl = *DeviceOrErr;
auto *KernelImpl = std::get<GenericKernelTy *>(Kernel->PluginImpl);
// Extract work group size from LaunchSizeArgs
@@ -1248,7 +1375,6 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device,
const ol_kernel_launch_prop_t *Properties,
size_t NumArgs, void **ArgPtrs,
const size_t *ArgSizes) {
- auto *DeviceImpl = Device->Device;
if (Queue && Device != Queue->Device) {
return createOffloadError(
ErrorCode::INVALID_DEVICE,
@@ -1259,6 +1385,11 @@ Error olLaunchKernel_impl(ol_queue_handle_t Queue, ol_device_handle_t Device,
return createOffloadError(ErrorCode::SYMBOL_KIND,
"provided symbol is not a kernel");
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ auto *DeviceImpl = *DeviceOrErr;
+
auto *QueueImpl = Queue ? Queue->AsyncInfo : nullptr;
KernelLaunchArgsTy LaunchArgs{};
LaunchArgs.NumArgs = static_cast<uint32_t>(NumArgs);
@@ -1438,13 +1569,20 @@ Error olGetSymbolInfoSize_impl(ol_symbol_handle_t Symbol,
Error olLaunchHostFunction_impl(ol_queue_handle_t Queue,
ol_host_function_cb_t Callback,
void *UserData) {
- return Queue->Device->Device->enqueueHostCall(Callback, UserData,
- Queue->AsyncInfo);
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ return (*DeviceOrErr)->enqueueHostCall(Callback, UserData,
+ Queue->AsyncInfo);
}
Error olMemRegister_impl(ol_device_handle_t Device, void *Ptr, size_t Size,
ol_memory_register_flags_t Flags, void **LockedPtr) {
- Expected<void *> LockedPtrOrErr = Device->Device->registerMemory(
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+
+ Expected<void *> LockedPtrOrErr = (*DeviceOrErr)->registerMemory(
Ptr, Size, Flags & OL_MEMORY_REGISTER_FLAG_LOCK_MEMORY);
if (!LockedPtrOrErr)
return LockedPtrOrErr.takeError();
@@ -1456,14 +1594,20 @@ Error olMemRegister_impl(ol_device_handle_t Device, void *Ptr, size_t Size,
Error olMemUnregister_impl(ol_device_handle_t Device, void *Ptr,
ol_memory_register_flags_t Flags) {
- return Device->Device->unregisterMemory(
+ auto DeviceOrErr = Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ return (*DeviceOrErr)->unregisterMemory(
Ptr, Flags & OL_MEMORY_REGISTER_FLAG_UNLOCK_MEMORY);
}
Error olQueryQueue_impl(ol_queue_handle_t Queue, bool *IsQueueWorkCompleted) {
if (Queue->AsyncInfo->Queue) {
- if (auto Err = Queue->Device->Device->queryAsync(Queue->AsyncInfo, false,
- IsQueueWorkCompleted))
+ auto DeviceOrErr = Queue->Device->getDevice();
+ if (!DeviceOrErr)
+ return DeviceOrErr.takeError();
+ if (auto Err = (*DeviceOrErr)->queryAsync(Queue->AsyncInfo, false,
+ IsQueueWorkCompleted))
return Err;
} else if (IsQueueWorkCompleted) {
// No underlying queue means there's no work to complete.
>From ffefd3cf7b2fd1e2fe12d126e6a8a23d60ee519f Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:39:20 -0700
Subject: [PATCH 03/14] [OFFLOAD]add olIteratePlatforms
---
offload/liboffload/API/Platform.td | 23 +++++++++++++++++++++++
offload/liboffload/src/OffloadImpl.cpp | 11 +++++++++++
2 files changed, 34 insertions(+)
diff --git a/offload/liboffload/API/Platform.td b/offload/liboffload/API/Platform.td
index 62810e8fdb7ca..65efec2b8af4a 100644
--- a/offload/liboffload/API/Platform.td
+++ b/offload/liboffload/API/Platform.td
@@ -97,3 +97,26 @@ def olPlatformRegisterRPCCallback : Function {
"RPC callback function pointer", PARAM_IN>];
let returns = [Return<"OL_ERRC_INVALID_PLATFORM">, Return<"OL_ERRC_SUCCESS">];
}
+
+def ol_platform_iterate_cb_t : FptrTypedef {
+ let desc = "User-provided function to be used with `olIteratePlatforms`";
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "the platform handle of the current iteration", PARAM_IN>,
+ Param<"void*", "UserData", "optional user data", PARAM_IN_OPTIONAL>
+ ];
+ let return = "bool";
+}
+
+def olIteratePlatforms : Function {
+ let desc = "Iterates over all available platforms, calling the callback for each platform.";
+ let details = [
+ "If the user-provided callback returns `false`, the iteration is stopped."
+ ];
+ let params = [
+ Param<"ol_platform_iterate_cb_t", "Callback", "User-provided function called for each available platform", PARAM_IN>,
+ Param<"void*", "UserData", "Optional user data to pass to the callback", PARAM_IN_OPTIONAL>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_PLATFORM">
+ ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 670179c21f054..e06bd8d445bc3 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -468,6 +468,17 @@ Error olPlatformRegisterRPCCallback_impl(ol_platform_handle_t Platform,
return Error::success();
}
+Error olIteratePlatforms_impl(ol_platform_iterate_cb_t Callback,
+ void *UserData) {
+ for (auto &Platform : OffloadContext::get().Platforms) {
+ if (!Callback(Platform.get(), UserData)) {
+ return Error::success();
+ }
+ }
+
+ return Error::success();
+}
+
Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
ol_device_info_t PropName, size_t PropSize,
void *PropValue, size_t *PropSizeRet) {
>From 9951e27875c24fc8a0d984f1c848bfbe5ed3c55a Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:55:00 -0700
Subject: [PATCH 04/14] [offload][omp] Load plugins through liboffload
---
offload/include/PluginManager.h | 3 ++-
offload/liboffload/exports | 2 +-
offload/liboffload/src/OffloadImpl.cpp | 5 ++++
offload/libompaccsupport/PluginManager.cpp | 29 +++++++++++++---------
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index 6c6fdebe76dff..eea8b62a8c39d 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -13,6 +13,7 @@
#ifndef OMPTARGET_PLUGIN_MANAGER_H
#define OMPTARGET_PLUGIN_MANAGER_H
+#include "OffloadAPI.h"
#include "PluginInterface.h"
#include "DeviceImage.h"
@@ -155,7 +156,7 @@ struct PluginManager {
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
// List of all plugins, in use or not.
- llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins;
+ llvm::SmallVector<GenericPluginTy *> Plugins;
// Mapping of plugins to the OpenMP device identifier.
llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index 5487e16168681..75b1cfd049c82 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -55,9 +55,9 @@ global:
llvm::omp::target::ompt::Initialized;
llvm::omp::target::ompt::lookupCallbackByCode;
llvm::omp::target::ompt::lookupCallbackByName;
- createPlugin_*;
# Temporary helpers to help transition of libomptarget to liboffload.
__ol_tgt_setInfoFlag;
+ __ol_tgt_GetPluginFromPlatform;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index e06bd8d445bc3..6e403df9544e3 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1633,5 +1633,10 @@ extern "C" void __ol_tgt_setInfoFlag(uint32_t NewInfoLevel) {
InfoLevel.store(NewInfoLevel);
}
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
+ return Platform->Plugin.get();
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 41b653a60adfd..b0cb40fb32e8d 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -26,9 +26,8 @@ using namespace llvm::omp::target::debug;
PluginManager *PM = nullptr;
-// Every plugin exports this method to create an instance of the plugin type.
-#define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name();
-#include "Shared/Targets.def"
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
void PluginManager::init() {
TIMESCOPE();
@@ -38,14 +37,21 @@ void PluginManager::init() {
}
ODBG(ODT_Init) << "Loading RTLs";
-
- // Attempt to create an instance of each supported plugin.
-#define PLUGIN_TARGET(Name) \
- do { \
- Plugins.emplace_back( \
- std::unique_ptr<GenericPluginTy>(createPlugin_##Name())); \
- } while (false);
-#include "Shared/Targets.def"
+ if (ol_result_t Res = olInit(nullptr))
+ REPORT() << "Failed to initialize liboffload: " << Res->Details;
+
+
+ if (ol_result_t Res = olIteratePlatforms(
+ [](ol_platform_handle_t Platform, void *Data) {
+ auto *PM = static_cast<PluginManager *>(Data);
+ auto *Plugin = __ol_tgt_GetPluginFromPlatform(Platform);
+ ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
+ << " from liboffload";
+ PM->Plugins.push_back(Plugin);
+ return true;
+ },
+ this))
+ REPORT() << "Failed to iterate platforms: " << Res->Details;
ODBG(ODT_Init) << "RTLs loaded!";
}
@@ -62,7 +68,6 @@ void PluginManager::deinit() {
std::string InfoMsg = toString(std::move(Err));
ODBG(ODT_Deinit) << "Failed to deinit plugin: " << InfoMsg;
}
- Plugin.release();
}
ODBG(ODT_Deinit) << "RTLs unloaded!";
>From 3d5895acbe4e736e78e48fc5d32f2a94b4295af8 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:56:25 -0700
Subject: [PATCH 05/14] add test
---
.../platform/olIteratePlatforms.cpp | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
diff --git a/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp b/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
new file mode 100644
index 0000000000000..4f8f4e35df23b
--- /dev/null
+++ b/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
@@ -0,0 +1,45 @@
+//===------- Offload API tests - olIteratePlatforms -----------------------===//
+//
+// 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 olIteratePlatformsTest = OffloadTest;
+
+TEST_F(olIteratePlatformsTest, SuccessEmptyCallback) {
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t, void *) { return false; }, nullptr));
+}
+
+TEST_F(olIteratePlatformsTest, SuccessGetPlatform) {
+ uint32_t PlatformCount = 0;
+ ol_platform_handle_t Platform = nullptr;
+
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t, void *Data) {
+ auto Count = static_cast<uint32_t *>(Data);
+ *Count += 1;
+ return true;
+ },
+ &PlatformCount));
+
+ if (PlatformCount == 0) {
+ GTEST_SKIP() << "No available platforms.";
+ }
+
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t P, void *Data) {
+ auto PlatformPtr = static_cast<ol_platform_handle_t *>(Data);
+ *PlatformPtr = P;
+ return true;
+ },
+ &Platform));
+
+ ASSERT_NE(Platform, nullptr);
+}
>From 2fb211366d56097e84b5eb4f7349771246489c6c Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:55:00 -0700
Subject: [PATCH 06/14] [offload][omp] Load plugins through liboffload
---
offload/include/PluginManager.h | 3 ++-
offload/liboffload/exports | 2 +-
offload/liboffload/src/OffloadImpl.cpp | 5 ++++
offload/libompaccsupport/PluginManager.cpp | 29 +++++++++++++---------
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index 6c6fdebe76dff..eea8b62a8c39d 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -13,6 +13,7 @@
#ifndef OMPTARGET_PLUGIN_MANAGER_H
#define OMPTARGET_PLUGIN_MANAGER_H
+#include "OffloadAPI.h"
#include "PluginInterface.h"
#include "DeviceImage.h"
@@ -155,7 +156,7 @@ struct PluginManager {
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
// List of all plugins, in use or not.
- llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins;
+ llvm::SmallVector<GenericPluginTy *> Plugins;
// Mapping of plugins to the OpenMP device identifier.
llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index 5487e16168681..75b1cfd049c82 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -55,9 +55,9 @@ global:
llvm::omp::target::ompt::Initialized;
llvm::omp::target::ompt::lookupCallbackByCode;
llvm::omp::target::ompt::lookupCallbackByName;
- createPlugin_*;
# Temporary helpers to help transition of libomptarget to liboffload.
__ol_tgt_setInfoFlag;
+ __ol_tgt_GetPluginFromPlatform;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index e06bd8d445bc3..6e403df9544e3 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1633,5 +1633,10 @@ extern "C" void __ol_tgt_setInfoFlag(uint32_t NewInfoLevel) {
InfoLevel.store(NewInfoLevel);
}
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
+ return Platform->Plugin.get();
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 41b653a60adfd..b0cb40fb32e8d 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -26,9 +26,8 @@ using namespace llvm::omp::target::debug;
PluginManager *PM = nullptr;
-// Every plugin exports this method to create an instance of the plugin type.
-#define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name();
-#include "Shared/Targets.def"
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
void PluginManager::init() {
TIMESCOPE();
@@ -38,14 +37,21 @@ void PluginManager::init() {
}
ODBG(ODT_Init) << "Loading RTLs";
-
- // Attempt to create an instance of each supported plugin.
-#define PLUGIN_TARGET(Name) \
- do { \
- Plugins.emplace_back( \
- std::unique_ptr<GenericPluginTy>(createPlugin_##Name())); \
- } while (false);
-#include "Shared/Targets.def"
+ if (ol_result_t Res = olInit(nullptr))
+ REPORT() << "Failed to initialize liboffload: " << Res->Details;
+
+
+ if (ol_result_t Res = olIteratePlatforms(
+ [](ol_platform_handle_t Platform, void *Data) {
+ auto *PM = static_cast<PluginManager *>(Data);
+ auto *Plugin = __ol_tgt_GetPluginFromPlatform(Platform);
+ ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
+ << " from liboffload";
+ PM->Plugins.push_back(Plugin);
+ return true;
+ },
+ this))
+ REPORT() << "Failed to iterate platforms: " << Res->Details;
ODBG(ODT_Init) << "RTLs loaded!";
}
@@ -62,7 +68,6 @@ void PluginManager::deinit() {
std::string InfoMsg = toString(std::move(Err));
ODBG(ODT_Deinit) << "Failed to deinit plugin: " << InfoMsg;
}
- Plugin.release();
}
ODBG(ODT_Deinit) << "RTLs unloaded!";
>From 8c787fbc0924057160ab05b5fc928e5ca6dad0da Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Fri, 4 Sep 2026 07:31:12 -0700
Subject: [PATCH 07/14] [offload][omp] Initialize devices through liboffload
---
offload/include/PluginManager.h | 12 +-
offload/include/device.h | 5 +-
offload/liboffload/API/Program.td | 15 +
offload/liboffload/exports | 5 +-
offload/liboffload/src/OffloadImpl.cpp | 30 ++
offload/libompaccsupport/PluginManager.cpp | 256 +++++++++---------
offload/libompaccsupport/device.cpp | 17 +-
.../common/include/PluginInterface.h | 6 -
.../common/src/PluginInterface.cpp | 15 -
9 files changed, 197 insertions(+), 164 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index eea8b62a8c39d..f1937a368186f 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -120,11 +120,9 @@ struct PluginManager {
return Devices.getExclusiveAccessor();
}
- /// Initialize \p Plugin. Returns true on success.
- bool initializePlugin(GenericPluginTy &Plugin);
-
- /// Initialize device \p DeviceNo of \p Plugin. Returns true on success.
- bool initializeDevice(GenericPluginTy &Plugin, int32_t DeviceId);
+ /// Initialize device \p DeviceHandle as on OpenMP device. Returns true on
+ /// success.
+ bool initializeDevice(ol_device_handle_t DeviceHandle);
/// Eagerly initialize all plugins and their devices.
void initializeAllDevices();
@@ -158,8 +156,8 @@ struct PluginManager {
// List of all plugins, in use or not.
llvm::SmallVector<GenericPluginTy *> Plugins;
- // Mapping of plugins to the OpenMP device identifier.
- llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
+ // Mapping of device handles to the OpenMP device identifier.
+ llvm::DenseMap<ol_device_handle_t, int32_t>
DeviceIds;
// Set of all device images currently in use.
diff --git a/offload/include/device.h b/offload/include/device.h
index 266a2a675df0c..ca32a7b26d1b4 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -34,6 +34,7 @@
#include "llvm/ADT/SmallVector.h"
#include "GlobalHandler.h"
+#include "OffloadAPI.h"
#include "PluginInterface.h"
using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy;
@@ -48,8 +49,10 @@ struct DeviceTy {
int32_t DeviceID;
GenericPluginTy *RTL;
int32_t RTLDeviceID;
+ ol_device_handle_t DeviceHandle;
- DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID);
+ DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID,
+ ol_device_handle_t DeviceHandle);
// DeviceTy is not copyable
DeviceTy(const DeviceTy &D) = delete;
DeviceTy &operator=(const DeviceTy &D) = delete;
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/exports b/offload/liboffload/exports
index 75b1cfd049c82..c43fbc7830393 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -28,15 +28,11 @@ global:
"llvm::omp::target::plugin::GenericPluginTy::flush_queue(omp_interop_val_t*)";
"llvm::omp::target::plugin::GenericPluginTy::get_function(__tgt_device_binary, char const*, void**)";
"llvm::omp::target::plugin::GenericPluginTy::get_global(__tgt_device_binary, unsigned long, char const*, void**)";
- "llvm::omp::target::plugin::GenericPluginTy::init()";
- "llvm::omp::target::plugin::GenericPluginTy::deinit()";
- "llvm::omp::target::plugin::GenericPluginTy::init_device(int)";
"llvm::omp::target::plugin::GenericPluginTy::initialize_record_replay(int, long, void*, bool, bool, bool, bool, char const*, char const*)";
"llvm::omp::target::plugin::GenericPluginTy::isDeviceCompatible(int, llvm::StringRef)";
"llvm::omp::target::plugin::GenericPluginTy::isPluginCompatible(llvm::StringRef)";
"llvm::omp::target::plugin::GenericPluginTy::is_accessible_ptr(int, void const*, unsigned long)";
"llvm::omp::target::plugin::GenericPluginTy::is_data_exchangable(int, int)";
- "llvm::omp::target::plugin::GenericPluginTy::is_device_initialized(int) const";
"llvm::omp::target::plugin::GenericPluginTy::is_initialized() const";
"llvm::omp::target::plugin::GenericPluginTy::launch_kernel(int, void*, llvm::omp::target::plugin::KernelLaunchArgsTy&, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::load_binary(int, __tgt_device_image*, __tgt_device_binary*)";
@@ -58,6 +54,7 @@ global:
# Temporary helpers to help transition of libomptarget to liboffload.
__ol_tgt_setInfoFlag;
__ol_tgt_GetPluginFromPlatform;
+ __ol_tgt_GetPluginDeviceId;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 6e403df9544e3..2005c5b4b2034 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1315,6 +1315,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))
@@ -1638,5 +1664,9 @@ __ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
return Platform->Plugin.get();
}
+extern "C" int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
+ return Device->DeviceNum;
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index b0cb40fb32e8d..bb81ede7031e2 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -28,6 +28,7 @@ PluginManager *PM = nullptr;
extern "C" GenericPluginTy *
__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
+extern "C" int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device);
void PluginManager::init() {
TIMESCOPE();
@@ -60,48 +61,35 @@ void PluginManager::deinit() {
TIMESCOPE();
ODBG(ODT_Deinit) << "Unloading RTLs...";
- for (auto &Plugin : Plugins) {
- if (!Plugin->is_initialized())
- continue;
-
- if (auto Err = Plugin->deinit()) {
- std::string InfoMsg = toString(std::move(Err));
- ODBG(ODT_Deinit) << "Failed to deinit plugin: " << InfoMsg;
- }
- }
+ Plugins.clear();
+ if (auto Res = olShutDown())
+ REPORT() << "Failed to deinitialize liboffload: " << Res->Details;
ODBG(ODT_Deinit) << "RTLs unloaded!";
}
-bool PluginManager::initializePlugin(GenericPluginTy &Plugin) {
- if (Plugin.is_initialized())
+bool PluginManager::initializeDevice(ol_device_handle_t DeviceHandle) {
+ if (PM->DeviceIds.find(DeviceHandle) != PM->DeviceIds.end()) {
+ auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
+ (*ExclusiveDevicesAccessor)[PM->DeviceIds[DeviceHandle]]
+ ->setHasPendingImages(true);
return true;
+ }
- if (auto Err = Plugin.init()) {
- std::string InfoMsg = toString(std::move(Err));
- ODBG(ODT_Init) << "Failed to init plugin: " << InfoMsg;
+ ol_platform_handle_t PlatformHandle;
+ if (auto Ret = olGetDeviceInfo(DeviceHandle, OL_DEVICE_INFO_PLATFORM,
+ sizeof(PlatformHandle), &PlatformHandle);
+ Ret != OL_SUCCESS) {
+ REPORT() << "Failed to get platform while initializing device "
+ << DeviceHandle;
return false;
}
- ODBG(ODT_Init) << "Registered plugin " << Plugin.getName() << " with "
- << Plugin.number_of_devices() << " visible device(s)";
+ GenericPluginTy &Plugin = *__ol_tgt_GetPluginFromPlatform(PlatformHandle);
+ int32_t DeviceId = __ol_tgt_GetPluginDeviceId(DeviceHandle);
- return true;
-}
-
-bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
- int32_t DeviceId) {
- if (Plugin.is_device_initialized(DeviceId)) {
- auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
- (*ExclusiveDevicesAccessor)[PM->DeviceIds[std::make_pair(&Plugin,
- DeviceId)]]
- ->setHasPendingImages(true);
- return true;
- }
-
- // Initialize the device information for the RTL we are about to use.
auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
-
+ // Initialize the device information for the RTL we are about to use.
int32_t UserId = ExclusiveDevicesAccessor->size();
// Set the device identifier offset in the plugin.
@@ -109,7 +97,8 @@ bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
Plugin.set_device_identifier(UserId, DeviceId);
#endif
- auto Device = std::make_unique<DeviceTy>(&Plugin, UserId, DeviceId);
+ auto Device =
+ std::make_unique<DeviceTy>(&Plugin, UserId, DeviceId, DeviceHandle);
if (auto Err = Device->init()) {
std::string InfoMsg = toString(std::move(Err));
ODBG(ODT_Init) << "Failed to init device " << DeviceId << ": " << InfoMsg;
@@ -120,21 +109,18 @@ bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
// We need to map between the plugin's device identifier and the one
// that OpenMP will use.
- PM->DeviceIds[std::make_pair(&Plugin, DeviceId)] = UserId;
+ PM->DeviceIds[DeviceHandle] = UserId;
return true;
}
void PluginManager::initializeAllDevices() {
- for (auto &Plugin : plugins()) {
- if (!initializePlugin(Plugin))
- continue;
-
- for (int32_t DeviceId = 0; DeviceId < Plugin.number_of_devices();
- ++DeviceId) {
- initializeDevice(Plugin, DeviceId);
- }
- }
+ olIterateDevices(
+ [](ol_device_handle_t Device, void *UserData) {
+ PM->initializeDevice(Device);
+ return true;
+ },
+ nullptr);
// After all plugins are initialized, register atExit cleanup handlers
std::atexit([]() {
// Interop cleanup should be done before the plugins are deinitialized as
@@ -216,91 +202,115 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
PM->addDeviceImage(*Desc, Desc->DeviceImages[i]);
// Register the images with the RTLs that understand them, if any.
- llvm::DenseMap<GenericPluginTy *, llvm::DenseSet<int32_t>> UsedDevices;
+ llvm::SmallVector<ol_device_handle_t> UsedDevices;
for (int32_t i = 0; i < Desc->NumDeviceImages; ++i) {
// Obtain the image and information that was previously extracted.
__tgt_device_image *Img = &Desc->DeviceImages[i];
- GenericPluginTy *FoundRTL = nullptr;
-
- // Scan the RTLs that have associated images until we find one that supports
- // the current image.
- for (auto &R : plugins()) {
- StringRef Buffer(reinterpret_cast<const char *>(Img->ImageStart),
- utils::getPtrDiff(Img->ImageEnd, Img->ImageStart));
-
- if (!R.isPluginCompatible(Buffer))
- continue;
-
- if (!initializePlugin(R))
- continue;
-
- if (!R.number_of_devices()) {
- ODBG(ODT_Init) << "Skipping plugin " << R.getName()
- << " with no visible devices";
- continue;
- }
-
- for (int32_t DeviceId = 0; DeviceId < R.number_of_devices(); ++DeviceId) {
- // We only want a single matching image to be registered for each binary
- // descriptor. This prevents multiple of the same image from being
- // registered for the same device in the case that they are mutually
- // compatible, such as sm_80 and sm_89.
- if (UsedDevices[&R].contains(DeviceId)) {
- ODBG(ODT_Init) << "Image " << Img->ImageStart
- << " is a duplicate, not loaded on RTL " << R.getName()
- << " device " << DeviceId;
- continue;
- }
-
- if (!R.isDeviceCompatible(DeviceId, Buffer))
- continue;
-
- ODBG(ODT_Init) << "Image " << Img->ImageStart
- << " is compatible with RTL " << R.getName()
- << " device " << DeviceId;
-
- if (!initializeDevice(R, DeviceId))
- continue;
-
- // Initialize (if necessary) translation table for this library.
- PM->TrlTblMtx.lock();
- if (!PM->HostEntriesBeginToTransTable.count(Desc->HostEntriesBegin)) {
- PM->HostEntriesBeginRegistrationOrder.push_back(
- Desc->HostEntriesBegin);
- TranslationTable &TT =
- (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin];
- TT.HostTable.EntriesBegin = Desc->HostEntriesBegin;
- TT.HostTable.EntriesEnd = Desc->HostEntriesEnd;
- }
-
- // Retrieve translation table for this library.
- TranslationTable &TT =
- (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin];
-
- ODBG(ODT_Init) << "Registering image " << Img->ImageStart
- << " with RTL " << R.getName();
-
- auto UserId = PM->DeviceIds[std::make_pair(&R, DeviceId)];
- if (TT.TargetsTable.size() < static_cast<size_t>(UserId + 1)) {
- TT.DeviceTables.resize(UserId + 1, {});
- TT.TargetsImages.resize(UserId + 1, nullptr);
- TT.TargetsEntries.resize(UserId + 1, {});
- TT.TargetsTable.resize(UserId + 1, nullptr);
- }
-
- // Register the image for this target type and invalidate the table.
- TT.TargetsImages[UserId] = Img;
- TT.TargetsTable[UserId] = nullptr;
-
- UsedDevices[&R].insert(DeviceId);
- PM->UsedImages.insert(Img);
- FoundRTL = &R;
-
- PM->TrlTblMtx.unlock();
- }
- }
- if (!FoundRTL)
+ struct RegisterImageState {
+ __tgt_bin_desc *Desc;
+ __tgt_device_image *Img;
+ llvm::SmallVector<ol_device_handle_t> &UsedDevices;
+ bool FoundRTL = false;
+ } State{Desc, Img, UsedDevices, false};
+
+ if (ol_result_t Res = olIterateCompatibleDevices(
+ Img->ImageStart, utils::getPtrDiff(Img->ImageEnd, Img->ImageStart),
+ [](ol_device_handle_t DeviceHandle, void *Data) {
+ auto &State = *static_cast<RegisterImageState *>(Data);
+
+ ol_platform_handle_t PlatformHandle;
+ if (auto Res =
+ olGetDeviceInfo(DeviceHandle, OL_DEVICE_INFO_PLATFORM,
+ sizeof(PlatformHandle), &PlatformHandle);
+ Res != OL_SUCCESS) {
+ REPORT() << "Failed to get platform info for device "
+ << DeviceHandle << ":" << Res->Details;
+ PlatformHandle = nullptr;
+ }
+
+ llvm::SmallString<256> PlatformName("Unknown");
+ if (PlatformHandle) {
+ size_t PlatformNameSize = 0;
+ if (auto Res = olGetPlatformInfoSize(PlatformHandle,
+ OL_PLATFORM_INFO_NAME,
+ &PlatformNameSize);
+ Res != OL_SUCCESS)
+ PlatformNameSize = 0;
+
+ PlatformName.resize(PlatformNameSize);
+ if (PlatformNameSize > 0) {
+ if (auto Res = olGetPlatformInfo(
+ PlatformHandle, OL_PLATFORM_INFO_NAME,
+ PlatformNameSize, PlatformName.data());
+ Res != OL_SUCCESS)
+ PlatformName = "Unknown";
+ } else
+ PlatformName = "Unknown";
+ }
+
+ // We only want a single matching image to be registered for each
+ // binary descriptor. This prevents multiple of the same image
+ // from being registered for the same device in the case that
+ // they are mutually compatible, such as sm_80 and sm_89.
+ if (llvm::is_contained(State.UsedDevices, DeviceHandle)) {
+ ODBG(ODT_Init) << "Image " << State.Img->ImageStart
+ << " is a duplicate, not loaded on RTL "
+ << PlatformName << " on device " << DeviceHandle;
+ return true;
+ }
+
+ ODBG(ODT_Init)
+ << "Image " << State.Img->ImageStart << " with RTL "
+ << PlatformName << " on device " << DeviceHandle;
+
+ PM->initializeDevice(DeviceHandle);
+
+ // Initialize (if necessary) translation table for this library.
+ PM->TrlTblMtx.lock();
+ if (!PM->HostEntriesBeginToTransTable.count(
+ State.Desc->HostEntriesBegin)) {
+ PM->HostEntriesBeginRegistrationOrder.push_back(
+ State.Desc->HostEntriesBegin);
+ TranslationTable &TT =
+ (PM->HostEntriesBeginToTransTable)[State.Desc
+ ->HostEntriesBegin];
+ TT.HostTable.EntriesBegin = State.Desc->HostEntriesBegin;
+ TT.HostTable.EntriesEnd = State.Desc->HostEntriesEnd;
+ }
+
+ // Retrieve translation table for this library.
+ TranslationTable &TT =
+ (PM->HostEntriesBeginToTransTable)[State.Desc
+ ->HostEntriesBegin];
+
+ ODBG(ODT_Init) << "Registering image " << State.Img->ImageStart
+ << " with RTL " << PlatformName;
+
+ auto UserId = PM->DeviceIds[DeviceHandle];
+ if (TT.TargetsTable.size() < static_cast<size_t>(UserId + 1)) {
+ TT.DeviceTables.resize(UserId + 1, {});
+ TT.TargetsImages.resize(UserId + 1, nullptr);
+ TT.TargetsEntries.resize(UserId + 1, {});
+ TT.TargetsTable.resize(UserId + 1, nullptr);
+ }
+
+ // Register the image for this target type and invalidate the
+ // table.
+ TT.TargetsImages[UserId] = State.Img;
+ TT.TargetsTable[UserId] = nullptr;
+
+ State.UsedDevices.push_back(DeviceHandle);
+ PM->UsedImages.insert(State.Img);
+ State.FoundRTL = true;
+
+ PM->TrlTblMtx.unlock();
+ return true;
+ },
+ &State))
+ REPORT() << "Failed to iterate compatible devices: " << Res->Details;
+
+ if (!State.FoundRTL)
ODBG(ODT_Init) << "No RTL found for image " << Img->ImageStart << "!";
}
PM->RTLsMtx.unlock();
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index 688746477861c..51d1194d94882 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -68,9 +68,10 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device,
return OFFLOAD_SUCCESS;
}
-DeviceTy::DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID)
+DeviceTy::DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID,
+ ol_device_handle_t DeviceHandle)
: DeviceID(DeviceID), RTL(RTL), RTLDeviceID(RTLDeviceID),
- MappingInfo(*this) {}
+ DeviceHandle(DeviceHandle), MappingInfo(*this) {}
DeviceTy::~DeviceTy() {
if (DeviceID == -1 || !(getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE))
@@ -81,11 +82,11 @@ DeviceTy::~DeviceTy() {
}
llvm::Error DeviceTy::init() {
- int32_t Ret = RTL->init_device(RTLDeviceID);
- if (Ret != OFFLOAD_SUCCESS)
- return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
- "failed to initialize device %d\n",
- DeviceID);
+ // TODO: Remove this once all device operations go through liboffload
+ // This just ensures the device is initialized for cases where we go through the
+ // plugin interface.
+ size_t Size = 0;
+ olGetDeviceInfoSize(DeviceHandle, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, &Size);
// Enables recording kernels if set.
BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false);
@@ -105,7 +106,7 @@ llvm::Error DeviceTy::init() {
bool EmitReport =
OMPX_EmitRecordReport || !OMPX_RecordReportFilename.get().empty();
- Ret = RTL->initialize_record_replay(
+ int32_t Ret = RTL->initialize_record_replay(
RTLDeviceID, OMPX_RecordMemSize, nullptr,
/*IsRecord=*/true, /*IsNative=*/true, OMPX_RecordOutput, EmitReport,
OMPX_RecordReportFilename.get().c_str(),
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 7b7a62bc2d467..bb196fc7e0df7 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1703,12 +1703,6 @@ struct GenericPluginTy {
/// Returns non-zero if the \p Image is compatible with the device.
int32_t isDeviceCompatible(int32_t DeviceId, StringRef Image);
- /// Returns non-zero if the plugin device has been initialized.
- int32_t is_device_initialized(int32_t DeviceId) const;
-
- /// Initialize the device inside of the plugin.
- int32_t init_device(int32_t DeviceId);
-
/// Return the number of devices this plugin can support.
int32_t number_of_devices();
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 573369dc3ba57..1b1764e557d7a 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1498,21 +1498,6 @@ int32_t GenericPluginTy::isDeviceCompatible(int32_t DeviceId, StringRef Image) {
}
}
-int32_t GenericPluginTy::is_device_initialized(int32_t DeviceId) const {
- return isValidDeviceId(DeviceId) && Devices[DeviceId] != nullptr;
-}
-
-int32_t GenericPluginTy::init_device(int32_t DeviceId) {
- auto Err = initDevice(DeviceId);
- if (Err) {
- REPORT() << "Failure to initialize device " << DeviceId << ": "
- << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); }
int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId,
>From 5310f78f51e7d3f7ca593608ff487cbaa125f2b0 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Fri, 4 Sep 2026 08:59:52 -0700
Subject: [PATCH 08/14] don't initialize devices when validating the image
---
offload/liboffload/src/OffloadImpl.cpp | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 670179c21f054..62f9878e7cd2b 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1295,12 +1295,8 @@ Error olCreateProgram_impl(ol_context_handle_t Context,
Error olIsValidBinary_impl(ol_device_handle_t Device, const void *ProgData,
size_t ProgDataSize, bool *IsValid) {
StringRef Buffer(reinterpret_cast<const char *>(ProgData), ProgDataSize);
- auto DeviceOrErr = Device->getDevice();
- if (!DeviceOrErr)
- return DeviceOrErr.takeError();
- auto *DeviceImpl = *DeviceOrErr;
*IsValid =
- DeviceImpl->Plugin.isDeviceCompatible(DeviceImpl->getDeviceId(), Buffer);
+ Device->Platform.Plugin->isDeviceCompatible(Device->DeviceNum, Buffer);
return Error::success();
}
>From 80ab4cdb51a82a703bbbe792082013805a712586 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:39:20 -0700
Subject: [PATCH 09/14] [OFFLOAD]add olIteratePlatforms
---
offload/liboffload/API/Platform.td | 23 +++++++++++++++++++++++
offload/liboffload/src/OffloadImpl.cpp | 11 +++++++++++
2 files changed, 34 insertions(+)
diff --git a/offload/liboffload/API/Platform.td b/offload/liboffload/API/Platform.td
index 62810e8fdb7ca..65efec2b8af4a 100644
--- a/offload/liboffload/API/Platform.td
+++ b/offload/liboffload/API/Platform.td
@@ -97,3 +97,26 @@ def olPlatformRegisterRPCCallback : Function {
"RPC callback function pointer", PARAM_IN>];
let returns = [Return<"OL_ERRC_INVALID_PLATFORM">, Return<"OL_ERRC_SUCCESS">];
}
+
+def ol_platform_iterate_cb_t : FptrTypedef {
+ let desc = "User-provided function to be used with `olIteratePlatforms`";
+ let params = [
+ Param<"ol_platform_handle_t", "Platform", "the platform handle of the current iteration", PARAM_IN>,
+ Param<"void*", "UserData", "optional user data", PARAM_IN_OPTIONAL>
+ ];
+ let return = "bool";
+}
+
+def olIteratePlatforms : Function {
+ let desc = "Iterates over all available platforms, calling the callback for each platform.";
+ let details = [
+ "If the user-provided callback returns `false`, the iteration is stopped."
+ ];
+ let params = [
+ Param<"ol_platform_iterate_cb_t", "Callback", "User-provided function called for each available platform", PARAM_IN>,
+ Param<"void*", "UserData", "Optional user data to pass to the callback", PARAM_IN_OPTIONAL>
+ ];
+ let returns = [
+ Return<"OL_ERRC_INVALID_PLATFORM">
+ ];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 62f9878e7cd2b..775b4b9ac2f95 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -468,6 +468,17 @@ Error olPlatformRegisterRPCCallback_impl(ol_platform_handle_t Platform,
return Error::success();
}
+Error olIteratePlatforms_impl(ol_platform_iterate_cb_t Callback,
+ void *UserData) {
+ for (auto &Platform : OffloadContext::get().Platforms) {
+ if (!Callback(Platform.get(), UserData)) {
+ return Error::success();
+ }
+ }
+
+ return Error::success();
+}
+
Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
ol_device_info_t PropName, size_t PropSize,
void *PropValue, size_t *PropSizeRet) {
>From ed5966525f7e71dad216fb585c89a0b93ae51b0c Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:56:25 -0700
Subject: [PATCH 10/14] add test
---
.../platform/olIteratePlatforms.cpp | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
diff --git a/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp b/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
new file mode 100644
index 0000000000000..4f8f4e35df23b
--- /dev/null
+++ b/offload/unittests/OffloadAPI/platform/olIteratePlatforms.cpp
@@ -0,0 +1,45 @@
+//===------- Offload API tests - olIteratePlatforms -----------------------===//
+//
+// 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 olIteratePlatformsTest = OffloadTest;
+
+TEST_F(olIteratePlatformsTest, SuccessEmptyCallback) {
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t, void *) { return false; }, nullptr));
+}
+
+TEST_F(olIteratePlatformsTest, SuccessGetPlatform) {
+ uint32_t PlatformCount = 0;
+ ol_platform_handle_t Platform = nullptr;
+
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t, void *Data) {
+ auto Count = static_cast<uint32_t *>(Data);
+ *Count += 1;
+ return true;
+ },
+ &PlatformCount));
+
+ if (PlatformCount == 0) {
+ GTEST_SKIP() << "No available platforms.";
+ }
+
+ ASSERT_SUCCESS(olIteratePlatforms(
+ [](ol_platform_handle_t P, void *Data) {
+ auto PlatformPtr = static_cast<ol_platform_handle_t *>(Data);
+ *PlatformPtr = P;
+ return true;
+ },
+ &Platform));
+
+ ASSERT_NE(Platform, nullptr);
+}
>From cf68ec1391130fa116ec4016cc712e3ad810309f Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:55:00 -0700
Subject: [PATCH 11/14] [offload][omp] Load plugins through liboffload
---
offload/include/PluginManager.h | 3 ++-
offload/liboffload/exports | 2 +-
offload/liboffload/src/OffloadImpl.cpp | 5 ++++
offload/libompaccsupport/PluginManager.cpp | 29 +++++++++++++---------
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index 6c6fdebe76dff..eea8b62a8c39d 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -13,6 +13,7 @@
#ifndef OMPTARGET_PLUGIN_MANAGER_H
#define OMPTARGET_PLUGIN_MANAGER_H
+#include "OffloadAPI.h"
#include "PluginInterface.h"
#include "DeviceImage.h"
@@ -155,7 +156,7 @@ struct PluginManager {
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
// List of all plugins, in use or not.
- llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins;
+ llvm::SmallVector<GenericPluginTy *> Plugins;
// Mapping of plugins to the OpenMP device identifier.
llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index 5487e16168681..75b1cfd049c82 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -55,9 +55,9 @@ global:
llvm::omp::target::ompt::Initialized;
llvm::omp::target::ompt::lookupCallbackByCode;
llvm::omp::target::ompt::lookupCallbackByName;
- createPlugin_*;
# Temporary helpers to help transition of libomptarget to liboffload.
__ol_tgt_setInfoFlag;
+ __ol_tgt_GetPluginFromPlatform;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 775b4b9ac2f95..b5cc82a764806 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1629,5 +1629,10 @@ extern "C" void __ol_tgt_setInfoFlag(uint32_t NewInfoLevel) {
InfoLevel.store(NewInfoLevel);
}
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
+ return Platform->Plugin.get();
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 41b653a60adfd..b0cb40fb32e8d 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -26,9 +26,8 @@ using namespace llvm::omp::target::debug;
PluginManager *PM = nullptr;
-// Every plugin exports this method to create an instance of the plugin type.
-#define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name();
-#include "Shared/Targets.def"
+extern "C" GenericPluginTy *
+__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
void PluginManager::init() {
TIMESCOPE();
@@ -38,14 +37,21 @@ void PluginManager::init() {
}
ODBG(ODT_Init) << "Loading RTLs";
-
- // Attempt to create an instance of each supported plugin.
-#define PLUGIN_TARGET(Name) \
- do { \
- Plugins.emplace_back( \
- std::unique_ptr<GenericPluginTy>(createPlugin_##Name())); \
- } while (false);
-#include "Shared/Targets.def"
+ if (ol_result_t Res = olInit(nullptr))
+ REPORT() << "Failed to initialize liboffload: " << Res->Details;
+
+
+ if (ol_result_t Res = olIteratePlatforms(
+ [](ol_platform_handle_t Platform, void *Data) {
+ auto *PM = static_cast<PluginManager *>(Data);
+ auto *Plugin = __ol_tgt_GetPluginFromPlatform(Platform);
+ ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
+ << " from liboffload";
+ PM->Plugins.push_back(Plugin);
+ return true;
+ },
+ this))
+ REPORT() << "Failed to iterate platforms: " << Res->Details;
ODBG(ODT_Init) << "RTLs loaded!";
}
@@ -62,7 +68,6 @@ void PluginManager::deinit() {
std::string InfoMsg = toString(std::move(Err));
ODBG(ODT_Deinit) << "Failed to deinit plugin: " << InfoMsg;
}
- Plugin.release();
}
ODBG(ODT_Deinit) << "RTLs unloaded!";
>From a91e909fd957893da9818887a8970a9f9a9e1edb Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Thu, 3 Sep 2026 10:55:00 -0700
Subject: [PATCH 12/14] [offload][omp] Load plugins through liboffload
>From 236bf828ef9a39b1d9bab83a175738a0b1d4b18d Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Fri, 4 Sep 2026 07:31:12 -0700
Subject: [PATCH 13/14] [offload][omp] Initialize devices through liboffload
---
offload/include/PluginManager.h | 12 +-
offload/include/device.h | 5 +-
offload/liboffload/API/Program.td | 15 +
offload/liboffload/exports | 5 +-
offload/liboffload/src/OffloadImpl.cpp | 30 ++
offload/libompaccsupport/PluginManager.cpp | 256 +++++++++---------
offload/libompaccsupport/device.cpp | 17 +-
.../common/include/PluginInterface.h | 6 -
.../common/src/PluginInterface.cpp | 15 -
9 files changed, 197 insertions(+), 164 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index eea8b62a8c39d..f1937a368186f 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -120,11 +120,9 @@ struct PluginManager {
return Devices.getExclusiveAccessor();
}
- /// Initialize \p Plugin. Returns true on success.
- bool initializePlugin(GenericPluginTy &Plugin);
-
- /// Initialize device \p DeviceNo of \p Plugin. Returns true on success.
- bool initializeDevice(GenericPluginTy &Plugin, int32_t DeviceId);
+ /// Initialize device \p DeviceHandle as on OpenMP device. Returns true on
+ /// success.
+ bool initializeDevice(ol_device_handle_t DeviceHandle);
/// Eagerly initialize all plugins and their devices.
void initializeAllDevices();
@@ -158,8 +156,8 @@ struct PluginManager {
// List of all plugins, in use or not.
llvm::SmallVector<GenericPluginTy *> Plugins;
- // Mapping of plugins to the OpenMP device identifier.
- llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
+ // Mapping of device handles to the OpenMP device identifier.
+ llvm::DenseMap<ol_device_handle_t, int32_t>
DeviceIds;
// Set of all device images currently in use.
diff --git a/offload/include/device.h b/offload/include/device.h
index 266a2a675df0c..ca32a7b26d1b4 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -34,6 +34,7 @@
#include "llvm/ADT/SmallVector.h"
#include "GlobalHandler.h"
+#include "OffloadAPI.h"
#include "PluginInterface.h"
using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy;
@@ -48,8 +49,10 @@ struct DeviceTy {
int32_t DeviceID;
GenericPluginTy *RTL;
int32_t RTLDeviceID;
+ ol_device_handle_t DeviceHandle;
- DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID);
+ DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID,
+ ol_device_handle_t DeviceHandle);
// DeviceTy is not copyable
DeviceTy(const DeviceTy &D) = delete;
DeviceTy &operator=(const DeviceTy &D) = delete;
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/exports b/offload/liboffload/exports
index 75b1cfd049c82..c43fbc7830393 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -28,15 +28,11 @@ global:
"llvm::omp::target::plugin::GenericPluginTy::flush_queue(omp_interop_val_t*)";
"llvm::omp::target::plugin::GenericPluginTy::get_function(__tgt_device_binary, char const*, void**)";
"llvm::omp::target::plugin::GenericPluginTy::get_global(__tgt_device_binary, unsigned long, char const*, void**)";
- "llvm::omp::target::plugin::GenericPluginTy::init()";
- "llvm::omp::target::plugin::GenericPluginTy::deinit()";
- "llvm::omp::target::plugin::GenericPluginTy::init_device(int)";
"llvm::omp::target::plugin::GenericPluginTy::initialize_record_replay(int, long, void*, bool, bool, bool, bool, char const*, char const*)";
"llvm::omp::target::plugin::GenericPluginTy::isDeviceCompatible(int, llvm::StringRef)";
"llvm::omp::target::plugin::GenericPluginTy::isPluginCompatible(llvm::StringRef)";
"llvm::omp::target::plugin::GenericPluginTy::is_accessible_ptr(int, void const*, unsigned long)";
"llvm::omp::target::plugin::GenericPluginTy::is_data_exchangable(int, int)";
- "llvm::omp::target::plugin::GenericPluginTy::is_device_initialized(int) const";
"llvm::omp::target::plugin::GenericPluginTy::is_initialized() const";
"llvm::omp::target::plugin::GenericPluginTy::launch_kernel(int, void*, llvm::omp::target::plugin::KernelLaunchArgsTy&, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::load_binary(int, __tgt_device_image*, __tgt_device_binary*)";
@@ -58,6 +54,7 @@ global:
# Temporary helpers to help transition of libomptarget to liboffload.
__ol_tgt_setInfoFlag;
__ol_tgt_GetPluginFromPlatform;
+ __ol_tgt_GetPluginDeviceId;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index b5cc82a764806..08318e98d49ee 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1311,6 +1311,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))
@@ -1634,5 +1660,9 @@ __ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
return Platform->Plugin.get();
}
+extern "C" int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
+ return Device->DeviceNum;
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index b0cb40fb32e8d..bb81ede7031e2 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -28,6 +28,7 @@ PluginManager *PM = nullptr;
extern "C" GenericPluginTy *
__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
+extern "C" int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device);
void PluginManager::init() {
TIMESCOPE();
@@ -60,48 +61,35 @@ void PluginManager::deinit() {
TIMESCOPE();
ODBG(ODT_Deinit) << "Unloading RTLs...";
- for (auto &Plugin : Plugins) {
- if (!Plugin->is_initialized())
- continue;
-
- if (auto Err = Plugin->deinit()) {
- std::string InfoMsg = toString(std::move(Err));
- ODBG(ODT_Deinit) << "Failed to deinit plugin: " << InfoMsg;
- }
- }
+ Plugins.clear();
+ if (auto Res = olShutDown())
+ REPORT() << "Failed to deinitialize liboffload: " << Res->Details;
ODBG(ODT_Deinit) << "RTLs unloaded!";
}
-bool PluginManager::initializePlugin(GenericPluginTy &Plugin) {
- if (Plugin.is_initialized())
+bool PluginManager::initializeDevice(ol_device_handle_t DeviceHandle) {
+ if (PM->DeviceIds.find(DeviceHandle) != PM->DeviceIds.end()) {
+ auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
+ (*ExclusiveDevicesAccessor)[PM->DeviceIds[DeviceHandle]]
+ ->setHasPendingImages(true);
return true;
+ }
- if (auto Err = Plugin.init()) {
- std::string InfoMsg = toString(std::move(Err));
- ODBG(ODT_Init) << "Failed to init plugin: " << InfoMsg;
+ ol_platform_handle_t PlatformHandle;
+ if (auto Ret = olGetDeviceInfo(DeviceHandle, OL_DEVICE_INFO_PLATFORM,
+ sizeof(PlatformHandle), &PlatformHandle);
+ Ret != OL_SUCCESS) {
+ REPORT() << "Failed to get platform while initializing device "
+ << DeviceHandle;
return false;
}
- ODBG(ODT_Init) << "Registered plugin " << Plugin.getName() << " with "
- << Plugin.number_of_devices() << " visible device(s)";
+ GenericPluginTy &Plugin = *__ol_tgt_GetPluginFromPlatform(PlatformHandle);
+ int32_t DeviceId = __ol_tgt_GetPluginDeviceId(DeviceHandle);
- return true;
-}
-
-bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
- int32_t DeviceId) {
- if (Plugin.is_device_initialized(DeviceId)) {
- auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
- (*ExclusiveDevicesAccessor)[PM->DeviceIds[std::make_pair(&Plugin,
- DeviceId)]]
- ->setHasPendingImages(true);
- return true;
- }
-
- // Initialize the device information for the RTL we are about to use.
auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
-
+ // Initialize the device information for the RTL we are about to use.
int32_t UserId = ExclusiveDevicesAccessor->size();
// Set the device identifier offset in the plugin.
@@ -109,7 +97,8 @@ bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
Plugin.set_device_identifier(UserId, DeviceId);
#endif
- auto Device = std::make_unique<DeviceTy>(&Plugin, UserId, DeviceId);
+ auto Device =
+ std::make_unique<DeviceTy>(&Plugin, UserId, DeviceId, DeviceHandle);
if (auto Err = Device->init()) {
std::string InfoMsg = toString(std::move(Err));
ODBG(ODT_Init) << "Failed to init device " << DeviceId << ": " << InfoMsg;
@@ -120,21 +109,18 @@ bool PluginManager::initializeDevice(GenericPluginTy &Plugin,
// We need to map between the plugin's device identifier and the one
// that OpenMP will use.
- PM->DeviceIds[std::make_pair(&Plugin, DeviceId)] = UserId;
+ PM->DeviceIds[DeviceHandle] = UserId;
return true;
}
void PluginManager::initializeAllDevices() {
- for (auto &Plugin : plugins()) {
- if (!initializePlugin(Plugin))
- continue;
-
- for (int32_t DeviceId = 0; DeviceId < Plugin.number_of_devices();
- ++DeviceId) {
- initializeDevice(Plugin, DeviceId);
- }
- }
+ olIterateDevices(
+ [](ol_device_handle_t Device, void *UserData) {
+ PM->initializeDevice(Device);
+ return true;
+ },
+ nullptr);
// After all plugins are initialized, register atExit cleanup handlers
std::atexit([]() {
// Interop cleanup should be done before the plugins are deinitialized as
@@ -216,91 +202,115 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
PM->addDeviceImage(*Desc, Desc->DeviceImages[i]);
// Register the images with the RTLs that understand them, if any.
- llvm::DenseMap<GenericPluginTy *, llvm::DenseSet<int32_t>> UsedDevices;
+ llvm::SmallVector<ol_device_handle_t> UsedDevices;
for (int32_t i = 0; i < Desc->NumDeviceImages; ++i) {
// Obtain the image and information that was previously extracted.
__tgt_device_image *Img = &Desc->DeviceImages[i];
- GenericPluginTy *FoundRTL = nullptr;
-
- // Scan the RTLs that have associated images until we find one that supports
- // the current image.
- for (auto &R : plugins()) {
- StringRef Buffer(reinterpret_cast<const char *>(Img->ImageStart),
- utils::getPtrDiff(Img->ImageEnd, Img->ImageStart));
-
- if (!R.isPluginCompatible(Buffer))
- continue;
-
- if (!initializePlugin(R))
- continue;
-
- if (!R.number_of_devices()) {
- ODBG(ODT_Init) << "Skipping plugin " << R.getName()
- << " with no visible devices";
- continue;
- }
-
- for (int32_t DeviceId = 0; DeviceId < R.number_of_devices(); ++DeviceId) {
- // We only want a single matching image to be registered for each binary
- // descriptor. This prevents multiple of the same image from being
- // registered for the same device in the case that they are mutually
- // compatible, such as sm_80 and sm_89.
- if (UsedDevices[&R].contains(DeviceId)) {
- ODBG(ODT_Init) << "Image " << Img->ImageStart
- << " is a duplicate, not loaded on RTL " << R.getName()
- << " device " << DeviceId;
- continue;
- }
-
- if (!R.isDeviceCompatible(DeviceId, Buffer))
- continue;
-
- ODBG(ODT_Init) << "Image " << Img->ImageStart
- << " is compatible with RTL " << R.getName()
- << " device " << DeviceId;
-
- if (!initializeDevice(R, DeviceId))
- continue;
-
- // Initialize (if necessary) translation table for this library.
- PM->TrlTblMtx.lock();
- if (!PM->HostEntriesBeginToTransTable.count(Desc->HostEntriesBegin)) {
- PM->HostEntriesBeginRegistrationOrder.push_back(
- Desc->HostEntriesBegin);
- TranslationTable &TT =
- (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin];
- TT.HostTable.EntriesBegin = Desc->HostEntriesBegin;
- TT.HostTable.EntriesEnd = Desc->HostEntriesEnd;
- }
-
- // Retrieve translation table for this library.
- TranslationTable &TT =
- (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin];
-
- ODBG(ODT_Init) << "Registering image " << Img->ImageStart
- << " with RTL " << R.getName();
-
- auto UserId = PM->DeviceIds[std::make_pair(&R, DeviceId)];
- if (TT.TargetsTable.size() < static_cast<size_t>(UserId + 1)) {
- TT.DeviceTables.resize(UserId + 1, {});
- TT.TargetsImages.resize(UserId + 1, nullptr);
- TT.TargetsEntries.resize(UserId + 1, {});
- TT.TargetsTable.resize(UserId + 1, nullptr);
- }
-
- // Register the image for this target type and invalidate the table.
- TT.TargetsImages[UserId] = Img;
- TT.TargetsTable[UserId] = nullptr;
-
- UsedDevices[&R].insert(DeviceId);
- PM->UsedImages.insert(Img);
- FoundRTL = &R;
-
- PM->TrlTblMtx.unlock();
- }
- }
- if (!FoundRTL)
+ struct RegisterImageState {
+ __tgt_bin_desc *Desc;
+ __tgt_device_image *Img;
+ llvm::SmallVector<ol_device_handle_t> &UsedDevices;
+ bool FoundRTL = false;
+ } State{Desc, Img, UsedDevices, false};
+
+ if (ol_result_t Res = olIterateCompatibleDevices(
+ Img->ImageStart, utils::getPtrDiff(Img->ImageEnd, Img->ImageStart),
+ [](ol_device_handle_t DeviceHandle, void *Data) {
+ auto &State = *static_cast<RegisterImageState *>(Data);
+
+ ol_platform_handle_t PlatformHandle;
+ if (auto Res =
+ olGetDeviceInfo(DeviceHandle, OL_DEVICE_INFO_PLATFORM,
+ sizeof(PlatformHandle), &PlatformHandle);
+ Res != OL_SUCCESS) {
+ REPORT() << "Failed to get platform info for device "
+ << DeviceHandle << ":" << Res->Details;
+ PlatformHandle = nullptr;
+ }
+
+ llvm::SmallString<256> PlatformName("Unknown");
+ if (PlatformHandle) {
+ size_t PlatformNameSize = 0;
+ if (auto Res = olGetPlatformInfoSize(PlatformHandle,
+ OL_PLATFORM_INFO_NAME,
+ &PlatformNameSize);
+ Res != OL_SUCCESS)
+ PlatformNameSize = 0;
+
+ PlatformName.resize(PlatformNameSize);
+ if (PlatformNameSize > 0) {
+ if (auto Res = olGetPlatformInfo(
+ PlatformHandle, OL_PLATFORM_INFO_NAME,
+ PlatformNameSize, PlatformName.data());
+ Res != OL_SUCCESS)
+ PlatformName = "Unknown";
+ } else
+ PlatformName = "Unknown";
+ }
+
+ // We only want a single matching image to be registered for each
+ // binary descriptor. This prevents multiple of the same image
+ // from being registered for the same device in the case that
+ // they are mutually compatible, such as sm_80 and sm_89.
+ if (llvm::is_contained(State.UsedDevices, DeviceHandle)) {
+ ODBG(ODT_Init) << "Image " << State.Img->ImageStart
+ << " is a duplicate, not loaded on RTL "
+ << PlatformName << " on device " << DeviceHandle;
+ return true;
+ }
+
+ ODBG(ODT_Init)
+ << "Image " << State.Img->ImageStart << " with RTL "
+ << PlatformName << " on device " << DeviceHandle;
+
+ PM->initializeDevice(DeviceHandle);
+
+ // Initialize (if necessary) translation table for this library.
+ PM->TrlTblMtx.lock();
+ if (!PM->HostEntriesBeginToTransTable.count(
+ State.Desc->HostEntriesBegin)) {
+ PM->HostEntriesBeginRegistrationOrder.push_back(
+ State.Desc->HostEntriesBegin);
+ TranslationTable &TT =
+ (PM->HostEntriesBeginToTransTable)[State.Desc
+ ->HostEntriesBegin];
+ TT.HostTable.EntriesBegin = State.Desc->HostEntriesBegin;
+ TT.HostTable.EntriesEnd = State.Desc->HostEntriesEnd;
+ }
+
+ // Retrieve translation table for this library.
+ TranslationTable &TT =
+ (PM->HostEntriesBeginToTransTable)[State.Desc
+ ->HostEntriesBegin];
+
+ ODBG(ODT_Init) << "Registering image " << State.Img->ImageStart
+ << " with RTL " << PlatformName;
+
+ auto UserId = PM->DeviceIds[DeviceHandle];
+ if (TT.TargetsTable.size() < static_cast<size_t>(UserId + 1)) {
+ TT.DeviceTables.resize(UserId + 1, {});
+ TT.TargetsImages.resize(UserId + 1, nullptr);
+ TT.TargetsEntries.resize(UserId + 1, {});
+ TT.TargetsTable.resize(UserId + 1, nullptr);
+ }
+
+ // Register the image for this target type and invalidate the
+ // table.
+ TT.TargetsImages[UserId] = State.Img;
+ TT.TargetsTable[UserId] = nullptr;
+
+ State.UsedDevices.push_back(DeviceHandle);
+ PM->UsedImages.insert(State.Img);
+ State.FoundRTL = true;
+
+ PM->TrlTblMtx.unlock();
+ return true;
+ },
+ &State))
+ REPORT() << "Failed to iterate compatible devices: " << Res->Details;
+
+ if (!State.FoundRTL)
ODBG(ODT_Init) << "No RTL found for image " << Img->ImageStart << "!";
}
PM->RTLsMtx.unlock();
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index 688746477861c..51d1194d94882 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -68,9 +68,10 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device,
return OFFLOAD_SUCCESS;
}
-DeviceTy::DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID)
+DeviceTy::DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID,
+ ol_device_handle_t DeviceHandle)
: DeviceID(DeviceID), RTL(RTL), RTLDeviceID(RTLDeviceID),
- MappingInfo(*this) {}
+ DeviceHandle(DeviceHandle), MappingInfo(*this) {}
DeviceTy::~DeviceTy() {
if (DeviceID == -1 || !(getInfoLevel() & OMP_INFOTYPE_DUMP_TABLE))
@@ -81,11 +82,11 @@ DeviceTy::~DeviceTy() {
}
llvm::Error DeviceTy::init() {
- int32_t Ret = RTL->init_device(RTLDeviceID);
- if (Ret != OFFLOAD_SUCCESS)
- return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
- "failed to initialize device %d\n",
- DeviceID);
+ // TODO: Remove this once all device operations go through liboffload
+ // This just ensures the device is initialized for cases where we go through the
+ // plugin interface.
+ size_t Size = 0;
+ olGetDeviceInfoSize(DeviceHandle, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, &Size);
// Enables recording kernels if set.
BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false);
@@ -105,7 +106,7 @@ llvm::Error DeviceTy::init() {
bool EmitReport =
OMPX_EmitRecordReport || !OMPX_RecordReportFilename.get().empty();
- Ret = RTL->initialize_record_replay(
+ int32_t Ret = RTL->initialize_record_replay(
RTLDeviceID, OMPX_RecordMemSize, nullptr,
/*IsRecord=*/true, /*IsNative=*/true, OMPX_RecordOutput, EmitReport,
OMPX_RecordReportFilename.get().c_str(),
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 7b7a62bc2d467..bb196fc7e0df7 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1703,12 +1703,6 @@ struct GenericPluginTy {
/// Returns non-zero if the \p Image is compatible with the device.
int32_t isDeviceCompatible(int32_t DeviceId, StringRef Image);
- /// Returns non-zero if the plugin device has been initialized.
- int32_t is_device_initialized(int32_t DeviceId) const;
-
- /// Initialize the device inside of the plugin.
- int32_t init_device(int32_t DeviceId);
-
/// Return the number of devices this plugin can support.
int32_t number_of_devices();
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 573369dc3ba57..1b1764e557d7a 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1498,21 +1498,6 @@ int32_t GenericPluginTy::isDeviceCompatible(int32_t DeviceId, StringRef Image) {
}
}
-int32_t GenericPluginTy::is_device_initialized(int32_t DeviceId) const {
- return isValidDeviceId(DeviceId) && Devices[DeviceId] != nullptr;
-}
-
-int32_t GenericPluginTy::init_device(int32_t DeviceId) {
- auto Err = initDevice(DeviceId);
- if (Err) {
- REPORT() << "Failure to initialize device " << DeviceId << ": "
- << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); }
int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId,
>From b13ff37fe0faaaa373b1f263a0e769e72ae86d8d Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Fri, 4 Sep 2026 09:27:41 -0700
Subject: [PATCH 14/14] [offload][omp] Use liboffload queues for memory
operations- #8
---
offload/include/PluginManager.h | 6 ++
offload/include/device.h | 7 +-
offload/include/omptarget.h | 21 +++--
offload/liboffload/exports | 9 +-
offload/liboffload/src/OffloadImpl.cpp | 31 ++-----
offload/libompaccsupport/PluginManager.cpp | 64 ++++++++++---
offload/libompaccsupport/device.cpp | 84 +++++++++++++----
offload/libomptarget/OpenMP/API.cpp | 33 +++----
offload/libomptarget/omptarget.cpp | 29 +++++-
.../common/include/PluginInterface.h | 31 -------
.../common/src/PluginInterface.cpp | 90 -------------------
offload/tools/kernelreplay/CMakeLists.txt | 1 +
12 files changed, 188 insertions(+), 218 deletions(-)
diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index f1937a368186f..ab4726b391843 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -149,6 +149,8 @@ struct PluginManager {
return count;
}
+ ol_device_handle_t getHostDevice();
+
private:
bool RTLsLoaded = false;
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
@@ -180,6 +182,10 @@ struct PluginManager {
std::list<llvm::SmallVector<__tgt_device_image, 0>> LegacyImages;
llvm::DenseMap<__tgt_bin_desc *, __tgt_bin_desc> UpgradedDescriptors;
__tgt_bin_desc *upgradeLegacyEntries(__tgt_bin_desc *Desc);
+
+ // Platform and device handles for host device operations.
+ ol_platform_handle_t HostPlatform = nullptr;
+ ol_device_handle_t HostDevice = nullptr;
};
/// Initialize the plugin manager and OpenMP runtime.
diff --git a/offload/include/device.h b/offload/include/device.h
index ca32a7b26d1b4..a7293013e0daf 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -50,6 +50,7 @@ struct DeviceTy {
GenericPluginTy *RTL;
int32_t RTLDeviceID;
ol_device_handle_t DeviceHandle;
+ ol_context_handle_t Context;
DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID,
ol_device_handle_t DeviceHandle);
@@ -62,6 +63,9 @@ struct DeviceTy {
/// Try to initialize the device and return any failure.
llvm::Error init();
+ /// Deinitialize the OpenMP device.
+ llvm::Error deinit();
+
/// Provide access to the mapping handler.
MappingInfoTy &getMappingInfo() { return MappingInfo; }
@@ -188,9 +192,6 @@ struct DeviceTy {
}
private:
- /// Deinitialize the device (and plugin).
- void deinit();
-
/// All offload entries available on this device.
using DeviceOffloadEntriesMapTy =
llvm::DenseMap<llvm::StringRef, OffloadEntryTy>;
diff --git a/offload/include/omptarget.h b/offload/include/omptarget.h
index db9590844b2fd..73f89c6ef176f 100644
--- a/offload/include/omptarget.h
+++ b/offload/include/omptarget.h
@@ -14,6 +14,8 @@
#ifndef _OMPTARGET_H_
#define _OMPTARGET_H_
+#include "OffloadAPI.h"
+
#include "Shared/APITypes.h"
#include "Shared/Environment.h"
#include "Shared/SourceInfo.h"
@@ -112,6 +114,11 @@ enum TargetAllocTy : int32_t {
struct DeviceTy;
+// temporary helper from liboffload until all usage of AsyncInfo
+// are migrated to use liboffload queues.
+extern "C" __tgt_async_info *
+__ol__tgt_GetAsyncInfoFromQueue(ol_queue_handle_t Queue);
+
/// The libomptarget wrapper around a __tgt_async_info object directly
/// associated with a libomptarget layer device. RAII semantics to avoid
/// mistakes.
@@ -130,20 +137,24 @@ class AsyncInfoTy {
using PostProcFuncTy = std::function<int()>;
llvm::SmallVector<PostProcFuncTy> PostProcessingFunctions;
- __tgt_async_info AsyncInfo;
+ ol_queue_handle_t Queue;
DeviceTy &Device;
public:
/// Synchronization method to be used.
SyncTy SyncType;
- AsyncInfoTy(DeviceTy &Device, SyncTy SyncType = SyncTy::BLOCKING)
- : Device(Device), SyncType(SyncType) {}
- ~AsyncInfoTy() { synchronize(); }
+ AsyncInfoTy(DeviceTy &Device, SyncTy SyncType = SyncTy::BLOCKING);
+ ~AsyncInfoTy();
/// Implicit conversion to the __tgt_async_info which is used in the
/// plugin interface.
- operator __tgt_async_info *() { return &AsyncInfo; }
+ operator __tgt_async_info *() {
+ return __ol__tgt_GetAsyncInfoFromQueue(Queue);
+ }
+
+ /// Get the underlying queue handle.
+ ol_queue_handle_t getQueue() const { return Queue; }
/// Synchronize all pending actions.
///
diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index c43fbc7830393..97ac4b32b041b 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -8,21 +8,15 @@ global:
error::OffloadError::ID;
"error::OffloadErrCategory()";
"llvm::omp::target::RPCServerTy::registerCallback(unsigned int (*)(void*, unsigned int))";
- "llvm::omp::target::plugin::GenericDeviceTy::dataFill(void*, void const*, long, long, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::async_barrier(omp_interop_val_t*)";
"llvm::omp::target::plugin::GenericPluginTy::create_event(int, void**)";
"llvm::omp::target::plugin::GenericPluginTy::create_interop(int, int, interop_spec_t*)";
"llvm::omp::target::plugin::GenericPluginTy::data_alloc(int, long, void*, int)";
"llvm::omp::target::plugin::GenericPluginTy::data_delete(int, void*, int)";
- "llvm::omp::target::plugin::GenericPluginTy::data_exchange(int, void*, int, void*, long)";
- "llvm::omp::target::plugin::GenericPluginTy::data_exchange_async(int, void*, int, void*, long, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::data_fence(int, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::data_lock(int, void*, long, void**)";
"llvm::omp::target::plugin::GenericPluginTy::data_notify_mapped(int, void*, long)";
"llvm::omp::target::plugin::GenericPluginTy::data_notify_unmapped(int, void*)";
- "llvm::omp::target::plugin::GenericPluginTy::data_retrieve_async(int, void*, void*, long, __tgt_async_info*)";
- "llvm::omp::target::plugin::GenericPluginTy::data_submit(int, void*, void*, long)";
- "llvm::omp::target::plugin::GenericPluginTy::data_submit_async(int, void*, void*, long, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::data_unlock(int, void*)";
"llvm::omp::target::plugin::GenericPluginTy::destroy_event(int, void*)";
"llvm::omp::target::plugin::GenericPluginTy::flush_queue(omp_interop_val_t*)";
@@ -39,13 +33,11 @@ global:
"llvm::omp::target::plugin::GenericPluginTy::number_of_devices()";
"llvm::omp::target::plugin::GenericPluginTy::obtain_device_info(int)";
"llvm::omp::target::plugin::GenericPluginTy::print_device_info(int)";
- "llvm::omp::target::plugin::GenericPluginTy::query_async(int, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::record_event(int, void*, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::release_interop(int, omp_interop_val_t*)";
"llvm::omp::target::plugin::GenericPluginTy::set_device_identifier(int, int)";
"llvm::omp::target::plugin::GenericPluginTy::sync_barrier(omp_interop_val_t*)";
"llvm::omp::target::plugin::GenericPluginTy::sync_event(int, void*)";
- "llvm::omp::target::plugin::GenericPluginTy::synchronize(int, __tgt_async_info*)";
"llvm::omp::target::plugin::GenericPluginTy::use_auto_zero_copy(int)";
"llvm::omp::target::plugin::GenericPluginTy::wait_event(int, void*, __tgt_async_info*)";
llvm::omp::target::ompt::Initialized;
@@ -55,6 +47,7 @@ global:
__ol_tgt_setInfoFlag;
__ol_tgt_GetPluginFromPlatform;
__ol_tgt_GetPluginDeviceId;
+ __ol__tgt_GetAsyncInfoFromQueue;
};
local:
*;
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index c307315d13a02..46c2f658b8bec 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1337,32 +1337,6 @@ Error olIterateCompatibleDevices_impl(const void *ProgData, size_t ProgDataSize,
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))
@@ -1690,5 +1664,10 @@ extern "C" int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
return Device->DeviceNum;
}
+extern "C" __tgt_async_info *
+__ol__tgt_GetAsyncInfoFromQueue(ol_queue_handle_t Queue) {
+ return Queue->AsyncInfo;
+}
+
} // namespace offload
} // namespace llvm
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index bb81ede7031e2..94f2beb6a703d 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -41,17 +41,21 @@ void PluginManager::init() {
if (ol_result_t Res = olInit(nullptr))
REPORT() << "Failed to initialize liboffload: " << Res->Details;
-
if (ol_result_t Res = olIteratePlatforms(
[](ol_platform_handle_t Platform, void *Data) {
- auto *PM = static_cast<PluginManager *>(Data);
- auto *Plugin = __ol_tgt_GetPluginFromPlatform(Platform);
- ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
+ auto *PM = static_cast<PluginManager *>(Data);
+ auto *Plugin = __ol_tgt_GetPluginFromPlatform(Platform);
+ ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
<< " from liboffload";
- PM->Plugins.push_back(Plugin);
- return true;
- },
- this))
+ PM->Plugins.push_back(Plugin);
+ ol_platform_backend_t Backend;
+ olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,
+ sizeof(Backend), &Backend);
+ if (Backend == OL_PLATFORM_BACKEND_HOST)
+ PM->HostPlatform = Platform;
+ return true;
+ },
+ this))
REPORT() << "Failed to iterate platforms: " << Res->Details;
ODBG(ODT_Init) << "RTLs loaded!";
@@ -61,6 +65,12 @@ void PluginManager::deinit() {
TIMESCOPE();
ODBG(ODT_Deinit) << "Unloading RTLs...";
+ auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
+ for (auto &Device : *ExclusiveDevicesAccessor)
+ if (auto Err = Device->deinit())
+ REPORT() << "Failed to deinitialize device " << Device->DeviceID
+ << ": " << toString(std::move(Err));
+
Plugins.clear();
if (auto Res = olShutDown())
REPORT() << "Failed to deinitialize liboffload: " << Res->Details;
@@ -68,6 +78,33 @@ void PluginManager::deinit() {
ODBG(ODT_Deinit) << "RTLs unloaded!";
}
+ol_device_handle_t PluginManager::getHostDevice() {
+ if (!HostDevice) {
+ olIterateDevices(
+ [](ol_device_handle_t D, void *Data) {
+ ol_platform_handle_t Platform;
+ olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),
+ &Platform);
+ ol_platform_backend_t Backend;
+ olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND, sizeof(Backend),
+ &Backend);
+
+ if (Backend == OL_PLATFORM_BACKEND_HOST) {
+ GenericPluginTy *HostPlugin =
+ __ol_tgt_GetPluginFromPlatform(Platform);
+ HostPlugin->set_device_identifier(omp_initial_device, 0);
+ *(static_cast<ol_device_handle_t *>(Data)) = D;
+ return false;
+ }
+
+ return true;
+ },
+ &HostDevice);
+ }
+
+ return HostDevice;
+}
+
bool PluginManager::initializeDevice(ol_device_handle_t DeviceHandle) {
if (PM->DeviceIds.find(DeviceHandle) != PM->DeviceIds.end()) {
auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
@@ -467,11 +504,14 @@ static int loadImagesOntoDevice(DeviceTy &Device) {
if (!(Entry.Flags & OMP_DECLARE_TARGET_INDIRECT_VTABLE) &&
!(Entry.Flags & OMP_DECLARE_TARGET_INDIRECT) &&
((PM->getRequirements() & OMP_REQ_UNIFIED_SHARED_MEMORY) ||
- (PM->getRequirements() & OMPX_REQ_AUTO_ZERO_COPY)))
- if (Device.RTL->data_submit(DeviceId, DeviceEntry.Address,
- Entry.Address,
- Entry.Size) != OFFLOAD_SUCCESS)
+ (PM->getRequirements() & OMPX_REQ_AUTO_ZERO_COPY))) {
+ AsyncInfoTy AsyncInfo(Device);
+ if (Device.submitData(DeviceEntry.Address,
+ Entry.Address,
+ Entry.Size,
+ AsyncInfo) != OFFLOAD_SUCCESS)
REPORT() << "Failed to write symbol for USM " << Entry.SymbolName;
+ }
} else if (Entry.Address) {
if (Device.RTL->get_function(Binary, Entry.SymbolName,
&DeviceEntry.Address) != OFFLOAD_SUCCESS)
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index 51d1194d94882..254021f30041f 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -82,11 +82,11 @@ DeviceTy::~DeviceTy() {
}
llvm::Error DeviceTy::init() {
- // TODO: Remove this once all device operations go through liboffload
- // This just ensures the device is initialized for cases where we go through the
- // plugin interface.
- size_t Size = 0;
- olGetDeviceInfoSize(DeviceHandle, OL_DEVICE_INFO_GLOBAL_MEM_SIZE, &Size);
+ if (olCreateContext(1, &DeviceHandle, &Context)) {
+ return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
+ "failed to create context for device %d\n",
+ DeviceID);
+ }
// Enables recording kernels if set.
BoolEnvar OMPX_RecordKernel("LIBOMPTARGET_RECORD", false);
@@ -120,6 +120,15 @@ llvm::Error DeviceTy::init() {
return llvm::Error::success();
}
+llvm::Error DeviceTy::deinit() {
+ if (olDestroyContext(Context)) {
+ return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
+ "failed to destroy context for device %d\n",
+ DeviceID);
+ }
+ return llvm::Error::success();
+}
+
// Extract the mapping of host function pointers to device function pointers
// from the entry table. Functions marked as 'indirect' in OpenMP will have
// offloading entries generated for them which map the host's function pointer
@@ -292,8 +301,18 @@ int32_t DeviceTy::submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size,
omp_initial_device, HstPtrBegin, DeviceID, TgtPtrBegin, Size,
/*CodePtr=*/OMPT_GET_RETURN_ADDRESS);)
- return RTL->data_submit_async(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size,
- AsyncInfo);
+ ol_queue_handle_t queue = AsyncInfo.getQueue();
+ if (!queue)
+ return OFFLOAD_FAIL;
+
+ if (auto Res = olMemcpy(queue, TgtPtrBegin, DeviceHandle, HstPtrBegin,
+ PM->getHostDevice(), Size)) {
+ REPORT() << "Failure to copy data from host to device. Pointers: host "
+ << "= " << HstPtrBegin << ", device = " << TgtPtrBegin
+ << ", size = " << Size << ": " << Res->Details;
+ return OFFLOAD_FAIL;
+ }
+ return OFFLOAD_SUCCESS;
}
// Retrieve data from device
@@ -312,8 +331,17 @@ int32_t DeviceTy::retrieveData(void *HstPtrBegin, void *TgtPtrBegin,
DeviceID, TgtPtrBegin, omp_initial_device, HstPtrBegin, Size,
/*CodePtr=*/OMPT_GET_RETURN_ADDRESS);)
- return RTL->data_retrieve_async(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size,
- AsyncInfo);
+ ol_queue_handle_t queue = AsyncInfo.getQueue();
+ if (!queue)
+ return OFFLOAD_FAIL;
+ if (auto Res = olMemcpy(queue, HstPtrBegin, PM->getHostDevice(), TgtPtrBegin,
+ DeviceHandle, Size)) {
+ REPORT() << "Failure to copy data from device to host. Pointers: host "
+ << "= " << HstPtrBegin << ", device = " << TgtPtrBegin
+ << ", size = " << Size << ": " << Res->Details;
+ return OFFLOAD_FAIL;
+ }
+ return OFFLOAD_SUCCESS;
}
// Copy data from current device to destination device directly
@@ -330,12 +358,19 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
RegionInterface.getCallbacks<ompt_target_data_transfer_from_device>(),
RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size,
/*CodePtr=*/OMPT_GET_RETURN_ADDRESS);)
- if (!AsyncInfo) {
- return RTL->data_exchange(RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr,
- Size);
+
+ ol_queue_handle_t queue = AsyncInfo.getQueue();
+ if (!queue)
+ return OFFLOAD_FAIL;
+ if (auto Res = olMemcpy(queue, DstPtr, DstDev.DeviceHandle, SrcPtr,
+ DeviceHandle, Size)) {
+ REPORT() << "Failure to copy data from device (" << RTLDeviceID
+ << ") to device (" << DstDev.RTLDeviceID
+ << "). Pointers: host = " << SrcPtr << ", device = " << DstPtr
+ << ", size = " << Size << ": " << Res->Details;
+ return OFFLOAD_FAIL;
}
- return RTL->data_exchange_async(RTLDeviceID, SrcPtr, DstDev.RTLDeviceID,
- DstPtr, Size, AsyncInfo);
+ return OFFLOAD_SUCCESS;
}
int32_t DeviceTy::dataFence(AsyncInfoTy &AsyncInfo) {
@@ -463,11 +498,28 @@ bool DeviceTy::isDataExchangable(const DeviceTy &DstDevice) {
}
int32_t DeviceTy::synchronize(AsyncInfoTy &AsyncInfo) {
- return RTL->synchronize(RTLDeviceID, AsyncInfo);
+ ol_queue_handle_t Queue = AsyncInfo.getQueue();
+ if (!Queue)
+ return OFFLOAD_SUCCESS;
+ if (auto Res = olSyncQueue(Queue)) {
+ REPORT() << "Failure to synchronize stream " << Queue << ": "
+ << Res->Details;
+ return OFFLOAD_FAIL;
+ }
+ return OFFLOAD_SUCCESS;
}
int32_t DeviceTy::queryAsync(AsyncInfoTy &AsyncInfo) {
- return RTL->query_async(RTLDeviceID, AsyncInfo);
+ ol_queue_handle_t Queue = AsyncInfo.getQueue();
+ if (!Queue)
+ return OFFLOAD_SUCCESS;
+
+ bool isComplete;
+ if (auto Res = olQueryQueue(Queue, &isComplete)) {
+ REPORT() << "Failure to query stream " << Queue << ": " << Res->Details;
+ return OFFLOAD_FAIL;
+ }
+ return OFFLOAD_SUCCESS;
}
int32_t DeviceTy::createEvent(void **Event) {
diff --git a/offload/libomptarget/OpenMP/API.cpp b/offload/libomptarget/OpenMP/API.cpp
index 1590aab702e26..80a0325a788d1 100644
--- a/offload/libomptarget/OpenMP/API.cpp
+++ b/offload/libomptarget/OpenMP/API.cpp
@@ -335,31 +335,13 @@ EXTERN int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
if (!SrcDeviceOrErr)
FATAL_MESSAGE(SrcDevice, "%s",
toString(SrcDeviceOrErr.takeError()).c_str());
- AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
auto DstDeviceOrErr = PM->getDevice(DstDevice);
if (!DstDeviceOrErr)
FATAL_MESSAGE(DstDevice, "%s",
toString(DstDeviceOrErr.takeError()).c_str());
- // First try to use D2D memcpy which is more efficient. If fails, fall back
- // to inefficient way.
- if (SrcDeviceOrErr->isDataExchangable(*DstDeviceOrErr)) {
- AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
- Rc = SrcDeviceOrErr->dataExchange(SrcAddr, *DstDeviceOrErr, DstAddr,
+ AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
+ Rc = SrcDeviceOrErr->dataExchange(SrcAddr, *DstDeviceOrErr, DstAddr,
Length, AsyncInfo);
- if (Rc == OFFLOAD_SUCCESS)
- return OFFLOAD_SUCCESS;
- }
-
- void *Buffer = malloc(Length);
- {
- AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
- Rc = SrcDeviceOrErr->retrieveData(Buffer, SrcAddr, Length, AsyncInfo);
- }
- if (Rc == OFFLOAD_SUCCESS) {
- AsyncInfoTy AsyncInfo(*DstDeviceOrErr);
- Rc = DstDeviceOrErr->submitData(DstAddr, Buffer, Length, AsyncInfo);
- }
- free(Buffer);
}
ODBG(ODT_Interface) << __func__ << " returns " << Rc;
@@ -486,10 +468,15 @@ EXTERN void *omp_target_memset(void *Ptr, int ByteVal, size_t NumBytes,
if (!DeviceOrErr)
FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str());
AsyncInfoTy AsyncInfo(*DeviceOrErr);
- if (auto Error = DeviceOrErr->RTL->getDevice(DeviceOrErr->RTLDeviceID)
- .dataFill(Ptr, &ByteVal, 1, NumBytes, AsyncInfo)) {
+ ol_queue_handle_t Queue = AsyncInfo.getQueue();
+ if (!Queue) {
+ ODBG(ODT_Interface) << "Failed to get queue for async memset on device " << DeviceNum;
+ return Ptr;
+ }
+ if (auto Res = olMemFill(Queue, Ptr, 1, &ByteVal, NumBytes)) {
ODBG(ODT_Interface)
- << __func__ << " failed to fill memory due to error with dataFill";
+ << __func__ << " failed to fill memory due to error with dataFill:"
+ << Res->Details;
// If the dataFill failed, let's just not do anything.
// omp_target_memset does not have any good way to fail.
// Depending on the RTL implementation, the application will
diff --git a/offload/libomptarget/omptarget.cpp b/offload/libomptarget/omptarget.cpp
index 9e93bca77b292..07286cd75cfae 100644
--- a/offload/libomptarget/omptarget.cpp
+++ b/offload/libomptarget/omptarget.cpp
@@ -43,6 +43,23 @@ using namespace llvm::omp::target::ompt;
#endif
using namespace llvm::omp::target::debug;
+AsyncInfoTy::AsyncInfoTy(DeviceTy &Device, SyncTy SyncType)
+ : Device(Device), SyncType(SyncType) {
+
+ if (auto Res = olCreateQueue(Device.Context, Device.DeviceHandle, &Queue)) {
+ REPORT() << "Failed to create queue for device " << Device.DeviceHandle
+ << ": " << Res->Details;
+ Queue = nullptr;
+ }
+}
+
+AsyncInfoTy::~AsyncInfoTy() {
+ if (Queue) {
+ synchronize();
+ olDestroyQueue(Queue);
+ }
+}
+
int AsyncInfoTy::synchronize() {
int Result = OFFLOAD_SUCCESS;
if (!isQueueEmpty()) {
@@ -50,9 +67,6 @@ int AsyncInfoTy::synchronize() {
case SyncTy::BLOCKING:
// If we have a queue we need to synchronize it now.
Result = Device.synchronize(*this);
- assert(AsyncInfo.Queue == nullptr &&
- "The device plugin should have nulled the queue to indicate there "
- "are no outstanding actions!");
break;
case SyncTy::NON_BLOCKING:
Result = Device.queryAsync(*this);
@@ -93,7 +107,14 @@ int32_t AsyncInfoTy::runPostProcessing() {
return OFFLOAD_SUCCESS;
}
-bool AsyncInfoTy::isQueueEmpty() const { return AsyncInfo.Queue == nullptr; }
+bool AsyncInfoTy::isQueueEmpty() const {
+ bool isComplete;
+ if (auto Res = olQueryQueue(Queue, &isComplete)) {
+ REPORT() << "Failed to query queue " << Queue << ": " << Res->Details;
+ return false;
+ }
+ return isComplete;
+}
/* All begin addresses for partially mapped structs must be aligned, up to 16,
* in order to ensure proper alignment of members. E.g.
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index bb196fc7e0df7..a53672f0f1288 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1739,31 +1739,6 @@ struct GenericPluginTy {
/// Notify t he runtime about a mapping that has been deleted.
int32_t data_notify_unmapped(int32_t DeviceId, void *HstPtr);
- /// Copy data to the given device.
- int32_t data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr,
- int64_t Size);
-
- /// Copy data to the given device asynchronously.
- int32_t data_submit_async(int32_t DeviceId, void *TgtPtr, void *HstPtr,
- int64_t Size, __tgt_async_info *AsyncInfoPtr);
-
- /// Copy data from the given device.
- int32_t data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr,
- int64_t Size);
-
- /// Copy data from the given device asynchronously.
- int32_t data_retrieve_async(int32_t DeviceId, void *HstPtr, void *TgtPtr,
- int64_t Size, __tgt_async_info *AsyncInfoPtr);
-
- /// Exchange memory addresses between two devices.
- int32_t data_exchange(int32_t SrcDeviceId, void *SrcPtr, int32_t DstDeviceId,
- void *DstPtr, int64_t Size);
-
- /// Exchange memory addresses between two devices asynchronously.
- int32_t data_exchange_async(int32_t SrcDeviceId, void *SrcPtr,
- int DstDeviceId, void *DstPtr, int64_t Size,
- __tgt_async_info *AsyncInfo);
-
/// Places a fence between previous data movements and following data
/// movements if necessary on the device
int32_t data_fence(int32_t DeviceId, __tgt_async_info *AsyncInfo);
@@ -1773,12 +1748,6 @@ struct GenericPluginTy {
KernelLaunchArgsTy &LaunchArgs,
__tgt_async_info *AsyncInfoPtr);
- /// Synchronize an asyncrhonous queue with the plugin runtime.
- int32_t synchronize(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr);
-
- /// Query the current state of an asynchronous queue.
- int32_t query_async(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr);
-
/// Obtain information about the given device.
InfoTreeNode obtain_device_info(int32_t DeviceId);
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 1b1764e557d7a..390c0d266aa9b 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1627,72 +1627,6 @@ int32_t GenericPluginTy::data_notify_unmapped(int32_t DeviceId, void *HstPtr) {
return OFFLOAD_SUCCESS;
}
-int32_t GenericPluginTy::data_submit(int32_t DeviceId, void *TgtPtr,
- void *HstPtr, int64_t Size) {
- return data_submit_async(DeviceId, TgtPtr, HstPtr, Size,
- /*AsyncInfoPtr=*/nullptr);
-}
-
-int32_t GenericPluginTy::data_submit_async(int32_t DeviceId, void *TgtPtr,
- void *HstPtr, int64_t Size,
- __tgt_async_info *AsyncInfoPtr) {
- auto Err = getDevice(DeviceId).dataSubmit(TgtPtr, HstPtr, Size, AsyncInfoPtr);
- if (Err) {
- REPORT() << "Failure to copy data from host to device. Pointers: host "
- << "= " << HstPtr << ", device = " << TgtPtr << ", size = " << Size
- << ": " << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::data_retrieve(int32_t DeviceId, void *HstPtr,
- void *TgtPtr, int64_t Size) {
- return data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size,
- /*AsyncInfoPtr=*/nullptr);
-}
-
-int32_t GenericPluginTy::data_retrieve_async(int32_t DeviceId, void *HstPtr,
- void *TgtPtr, int64_t Size,
- __tgt_async_info *AsyncInfoPtr) {
- auto Err =
- getDevice(DeviceId).dataRetrieve(HstPtr, TgtPtr, Size, AsyncInfoPtr);
- if (Err) {
- REPORT() << "Failure to copy data from device to host. Pointers: host "
- << "= " << HstPtr << ", device = " << TgtPtr << ", size = " << Size
- << ": " << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::data_exchange(int32_t SrcDeviceId, void *SrcPtr,
- int32_t DstDeviceId, void *DstPtr,
- int64_t Size) {
- return data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, Size,
- /*AsyncInfoPtr=*/nullptr);
-}
-
-int32_t GenericPluginTy::data_exchange_async(int32_t SrcDeviceId, void *SrcPtr,
- int DstDeviceId, void *DstPtr,
- int64_t Size,
- __tgt_async_info *AsyncInfo) {
- GenericDeviceTy &SrcDevice = getDevice(SrcDeviceId);
- GenericDeviceTy &DstDevice = getDevice(DstDeviceId);
- auto Err = SrcDevice.dataExchange(SrcPtr, DstDevice, DstPtr, Size, AsyncInfo);
- if (Err) {
- REPORT() << "Failure to copy data from device (" << SrcDeviceId
- << ") to device (" << DstDeviceId
- << "). Pointers: host = " << SrcPtr << ", device = " << DstPtr
- << ", size = " << Size << ": " << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
int32_t GenericPluginTy::launch_kernel(int32_t DeviceId, void *TgtEntryPtr,
KernelLaunchArgsTy &LaunchArgs,
__tgt_async_info *AsyncInfoPtr) {
@@ -1707,30 +1641,6 @@ int32_t GenericPluginTy::launch_kernel(int32_t DeviceId, void *TgtEntryPtr,
return OFFLOAD_SUCCESS;
}
-int32_t GenericPluginTy::synchronize(int32_t DeviceId,
- __tgt_async_info *AsyncInfoPtr) {
- auto Err = getDevice(DeviceId).synchronize(AsyncInfoPtr);
- if (Err) {
- REPORT() << "Failure to synchronize stream " << AsyncInfoPtr->Queue << ": "
- << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::query_async(int32_t DeviceId,
- __tgt_async_info *AsyncInfoPtr) {
- auto Err = getDevice(DeviceId).queryAsync(AsyncInfoPtr);
- if (Err) {
- REPORT() << "Failure to query stream " << AsyncInfoPtr->Queue << ": "
- << toString(std::move(Err));
- return OFFLOAD_FAIL;
- }
-
- return OFFLOAD_SUCCESS;
-}
-
InfoTreeNode GenericPluginTy::obtain_device_info(int32_t DeviceId) {
auto InfoOrErr = getDevice(DeviceId).obtainInfo();
if (auto Err = InfoOrErr.takeError()) {
diff --git a/offload/tools/kernelreplay/CMakeLists.txt b/offload/tools/kernelreplay/CMakeLists.txt
index 66c4b2159822a..d3825ed6801f2 100644
--- a/offload/tools/kernelreplay/CMakeLists.txt
+++ b/offload/tools/kernelreplay/CMakeLists.txt
@@ -6,6 +6,7 @@ llvm_update_compile_flags(llvm-omp-kernel-replay)
target_include_directories(llvm-omp-kernel-replay PRIVATE
${LIBOMPTARGET_INCLUDE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/../../liboffload/API
)
target_link_libraries(llvm-omp-kernel-replay PRIVATE
LLVMSupport
More information about the llvm-branch-commits
mailing list