[llvm-branch-commits] [llvm] [offload][omp] Manage events through liboffload (PR #226444)

Alex Duran via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Oct 7 00:25:28 PDT 2026


https://github.com/adurang updated https://github.com/llvm/llvm-project/pull/226444

>From a6ce40f59a7b1b2e61ee6293cd01937ecca95342 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Mon, 7 Sep 2026 03:18:41 -0700
Subject: [PATCH 1/7] [offload][omp] Use olIterateCompatibleDevices for device
 init and image registration

---
 offload/include/PluginManager.h               |  13 +-
 offload/include/device.h                      |   5 +-
 offload/liboffload/src/OffloadImpl.cpp        |   4 +
 offload/libompaccsupport/PluginManager.cpp    | 246 ++++++++++--------
 offload/libompaccsupport/device.cpp           |  17 +-
 .../common/include/PluginInterface.h          |   6 -
 .../common/src/PluginInterface.cpp            |  15 --
 7 files changed, 154 insertions(+), 152 deletions(-)

diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index eea8b62a8c39da..36b8f7d3c914ba 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,9 +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>
-      DeviceIds;
+  // 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.
   llvm::DenseSet<const __tgt_device_image *> UsedImages;
diff --git a/offload/include/device.h b/offload/include/device.h
index 283f49c5191e89..8b53c7fabc4abd 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;
@@ -89,8 +90,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/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 6eca51f49ecf13..e79c1e2d8832e7 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1528,6 +1528,10 @@ namespace tmp {
 GenericPluginTy *__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform) {
   return Platform->Plugin.get();
 }
+
+int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
+  return Device->DeviceNum;
+}
 } // namespace tmp
 
 } // namespace offload
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index d008be8d72954d..7c4b554e075f61 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -37,6 +37,7 @@ PluginManager *PM = nullptr;
 
 namespace llvm::offload::tmp {
 GenericPluginTy *__ol_tgt_GetPluginFromPlatform(ol_platform_handle_t Platform);
+int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device);
 } // namespace llvm::offload::tmp
 
 void PluginManager::init() {
@@ -83,38 +84,34 @@ void PluginManager::deinit() {
   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)";
-
-  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;
-  }
+  GenericPluginTy &Plugin =
+      *llvm::offload::tmp::__ol_tgt_GetPluginFromPlatform(PlatformHandle);
+  int32_t DeviceId =
+      llvm::offload::tmp::__ol_tgt_GetPluginDeviceId(DeviceHandle);
 
-  // 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();
 
-  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;
@@ -125,21 +122,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
@@ -221,91 +215,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 cf73d504611984..e064cbdeef8588 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -70,9 +70,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))
@@ -83,11 +84,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);
 
   OMPT_IF_BUILT_AND_INITIALIZED({
     GenericDeviceTy &GenericDevice = RTL->getDevice(RTLDeviceID);
@@ -115,7 +116,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 3f8050bcfbc322..f0c67599c0e1e9 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1644,12 +1644,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 c28b0df8b6d5ad..01891f5ddbae74 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1219,21 +1219,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 6fc908fde2ba9c89ac7bcfdf2a6eb09517e63dc3 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Mon, 7 Sep 2026 22:38:35 -0700
Subject: [PATCH 2/7] remove two export lines

---
 offload/liboffload/exports | 56 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index 168341aa7d9380..dd7c0881c94b10 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -1,6 +1,62 @@
 VERS1.0 {
 global:
   ol*;
+<<<<<<< HEAD
+=======
+  # 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::initialize_record_replay(int, long, void*, bool, bool, bool, bool, char const*, char const*)";
+    "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_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;
+    # Temporary helpers to help transition of libomptarget to liboffload.
+    __ol_tgt_setInfoFlag;
+    __ol_tgt_GetPluginFromPlatform;
+    __ol_tgt_GetPluginDeviceId;
+  };
+>>>>>>> 885a6c290ea9 (remove two export lines)
 local:
   *;
 };

>From 26677d68f49cada70d6b14486bb1856d87b557d5 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Fri, 25 Sep 2026 02:07:25 -0700
Subject: [PATCH 3/7] restore export file

---
 offload/liboffload/exports                 | 56 ----------------------
 offload/libompaccsupport/PluginManager.cpp |  7 +--
 offload/libompaccsupport/device.cpp        |  6 ---
 3 files changed, 4 insertions(+), 65 deletions(-)

diff --git a/offload/liboffload/exports b/offload/liboffload/exports
index dd7c0881c94b10..168341aa7d9380 100644
--- a/offload/liboffload/exports
+++ b/offload/liboffload/exports
@@ -1,62 +1,6 @@
 VERS1.0 {
 global:
   ol*;
-<<<<<<< HEAD
-=======
-  # 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::initialize_record_replay(int, long, void*, bool, bool, bool, bool, char const*, char const*)";
-    "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_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;
-    # Temporary helpers to help transition of libomptarget to liboffload.
-    __ol_tgt_setInfoFlag;
-    __ol_tgt_GetPluginFromPlatform;
-    __ol_tgt_GetPluginDeviceId;
-  };
->>>>>>> 885a6c290ea9 (remove two export lines)
 local:
   *;
 };
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 7c4b554e075f61..efbdb2f47a0633 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -106,8 +106,9 @@ bool PluginManager::initializeDevice(ol_device_handle_t DeviceHandle) {
   int32_t DeviceId =
       llvm::offload::tmp::__ol_tgt_GetPluginDeviceId(DeviceHandle);
 
-  auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
   // Initialize the device information for the RTL we are about to use.
+  auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
+
   int32_t UserId = ExclusiveDevicesAccessor->size();
 
   auto Device =
@@ -120,8 +121,8 @@ bool PluginManager::initializeDevice(ol_device_handle_t DeviceHandle) {
 
   ExclusiveDevicesAccessor->push_back(std::move(Device));
 
-  // We need to map between the plugin's device identifier and the one
-  // that OpenMP will use.
+  // We need to map between the liboffload device handle and the OpenMP device
+  // id.
   PM->DeviceIds[DeviceHandle] = UserId;
 
   return true;
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index e064cbdeef8588..af30aa757a15a2 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -84,12 +84,6 @@ 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);
-
   OMPT_IF_BUILT_AND_INITIALIZED({
     GenericDeviceTy &GenericDevice = RTL->getDevice(RTLDeviceID);
     std::string ComputeUnitKind = GenericDevice.getComputeUnitKind();

>From a6d02105881bd571e74d02d38e823ca1ad6c0b8d Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Mon, 5 Oct 2026 13:24:58 -0700
Subject: [PATCH 4/7] move lambda to helper

---
 offload/include/PluginManager.h            |   8 +
 offload/libompaccsupport/PluginManager.cpp | 172 ++++++++++-----------
 2 files changed, 92 insertions(+), 88 deletions(-)

diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index 36b8f7d3c914ba..ee299c1cf4af29 100644
--- a/offload/include/PluginManager.h
+++ b/offload/include/PluginManager.h
@@ -179,6 +179,14 @@ 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);
+
+  /// Register the image \p Img from \p Desc on the compatible device
+  /// \p DeviceHandle, unless the device is already in \p UsedDevices. Returns
+  /// true if the image was registered.
+  bool
+  registerImageOnDevice(ol_device_handle_t DeviceHandle, __tgt_bin_desc *Desc,
+                        __tgt_device_image *Img,
+                        llvm::SmallVectorImpl<ol_device_handle_t> &UsedDevices);
 };
 
 /// Initialize the plugin manager and OpenMP runtime.
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index efbdb2f47a0633..9732b0ce98de1b 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -198,6 +198,86 @@ __tgt_bin_desc *PluginManager::upgradeLegacyEntries(__tgt_bin_desc *Desc) {
   return &NewDesc;
 }
 
+bool PluginManager::registerImageOnDevice(
+    ol_device_handle_t DeviceHandle, __tgt_bin_desc *Desc,
+    __tgt_device_image *Img,
+    llvm::SmallVectorImpl<ol_device_handle_t> &UsedDevices) {
+
+  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(UsedDevices, DeviceHandle)) {
+    ODBG(ODT_Init) << "Image " << Img->ImageStart
+                   << " is a duplicate, not loaded on RTL " << PlatformName
+                   << " on device " << DeviceHandle;
+    return false;
+  }
+
+  ODBG(ODT_Init) << "Image " << Img->ImageStart << " with RTL " << PlatformName
+                 << " on device " << DeviceHandle;
+
+  initializeDevice(DeviceHandle);
+
+  // Initialize (if necessary) translation table for this library.
+  std::lock_guard<std::mutex> LG(TrlTblMtx);
+  if (!HostEntriesBeginToTransTable.count(Desc->HostEntriesBegin)) {
+    HostEntriesBeginRegistrationOrder.push_back(Desc->HostEntriesBegin);
+    TranslationTable &TT = HostEntriesBeginToTransTable[Desc->HostEntriesBegin];
+    TT.HostTable.EntriesBegin = Desc->HostEntriesBegin;
+    TT.HostTable.EntriesEnd = Desc->HostEntriesEnd;
+  }
+
+  // Retrieve translation table for this library.
+  TranslationTable &TT = HostEntriesBeginToTransTable[Desc->HostEntriesBegin];
+
+  ODBG(ODT_Init) << "Registering image " << Img->ImageStart << " with RTL "
+                 << PlatformName;
+
+  auto UserId = 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] = Img;
+  TT.TargetsTable[UserId] = nullptr;
+
+  UsedDevices.push_back(DeviceHandle);
+  UsedImages.insert(Img);
+  return true;
+}
+
 void PluginManager::registerLib(__tgt_bin_desc *Desc) {
   PM->RTLsMtx.lock();
 
@@ -224,7 +304,7 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
     struct RegisterImageState {
       __tgt_bin_desc *Desc;
       __tgt_device_image *Img;
-      llvm::SmallVector<ol_device_handle_t> &UsedDevices;
+      llvm::SmallVectorImpl<ol_device_handle_t> &UsedDevices;
       bool FoundRTL = false;
     } State{Desc, Img, UsedDevices, false};
 
@@ -232,93 +312,9 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) {
             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();
+              if (PM->registerImageOnDevice(DeviceHandle, State.Desc, State.Img,
+                                            State.UsedDevices))
+                State.FoundRTL = true;
               return true;
             },
             &State))

>From 6033262dc26de4f3b6575ccb3874e1a137a723c9 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Mon, 7 Sep 2026 03:26:53 -0700
Subject: [PATCH 5/7] [offload][omp] memory operations through liboffload

---
 offload/include/PluginManager.h               |  6 ++
 offload/include/device.h                      |  4 +
 offload/include/omptarget.h                   | 21 +++--
 offload/liboffload/src/OffloadImpl.cpp        |  5 ++
 offload/libompaccsupport/AsyncInfo.cpp        | 29 +++++-
 offload/libompaccsupport/PluginManager.cpp    | 47 ++++++++--
 offload/libompaccsupport/device.cpp           | 80 ++++++++++++++---
 offload/libomptarget/OpenMP/API.cpp           | 36 +++-----
 .../common/include/PluginInterface.h          | 31 -------
 .../common/src/PluginInterface.cpp            | 90 -------------------
 offload/tools/kernelreplay/CMakeLists.txt     |  1 +
 11 files changed, 180 insertions(+), 170 deletions(-)

diff --git a/offload/include/PluginManager.h b/offload/include/PluginManager.h
index ee299c1cf4af29..955bbefef7cecf 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 {
   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;
+
   /// Register the image \p Img from \p Desc on the compatible device
   /// \p DeviceHandle, unless the device is already in \p UsedDevices. Returns
   /// true if the image was registered.
diff --git a/offload/include/device.h b/offload/include/device.h
index 8b53c7fabc4abd..0488fedb616e65 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -91,6 +91,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);
@@ -103,6 +104,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; }
 
diff --git a/offload/include/omptarget.h b/offload/include/omptarget.h
index 6bd61036cc4b34..5299b7eabe4b5d 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/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index e79c1e2d8832e7..7132d71a7e18f3 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1534,5 +1534,10 @@ int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
 }
 } // namespace tmp
 
+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/AsyncInfo.cpp b/offload/libompaccsupport/AsyncInfo.cpp
index 4a08cc67fcb231..791bc92be412ce 100644
--- a/offload/libompaccsupport/AsyncInfo.cpp
+++ b/offload/libompaccsupport/AsyncInfo.cpp
@@ -16,6 +16,23 @@
 
 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()) {
@@ -23,9 +40,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);
@@ -66,4 +80,11 @@ 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;
+}
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 9732b0ce98de1b..1de5c0663681d2 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -59,6 +59,11 @@ void PluginManager::init() {
             ODBG(ODT_Init) << "Adding plugin " << Plugin->getName()
                            << " from liboffload";
             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))
@@ -71,11 +76,15 @@ void PluginManager::deinit() {
   TIMESCOPE();
   ODBG(ODT_Deinit) << "Unloading RTLs...";
 
+  auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
   OMPT_IF_BUILT_AND_INITIALIZED({
-    auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
     for (DeviceTy &Device : devices(ExclusiveDevicesAccessor))
       performOmptCallback(device_finalize, Device.DeviceID);
   });
+  for (auto &Device : *ExclusiveDevicesAccessor)
+    if (auto Err = Device->deinit())
+      REPORT() << "Failed to deinitialize device " << Device->DeviceID << ": "
+               << toString(std::move(Err));
 
   Plugins.clear();
   if (auto Err = olShutDown())
@@ -84,6 +93,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();
@@ -477,11 +513,12 @@ 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) !=
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index af30aa757a15a2..4dbc2351abf4f7 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -84,6 +84,12 @@ DeviceTy::~DeviceTy() {
 }
 
 llvm::Error DeviceTy::init() {
+  if (olCreateContext(1, &DeviceHandle, &Context)) {
+    return error::createOffloadError(error::ErrorCode::BACKEND_FAILURE,
+                                     "failed to create context for device %d\n",
+                                     DeviceID);
+  }
+
   OMPT_IF_BUILT_AND_INITIALIZED({
     GenericDeviceTy &GenericDevice = RTL->getDevice(RTLDeviceID);
     std::string ComputeUnitKind = GenericDevice.getComputeUnitKind();
@@ -124,6 +130,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
@@ -304,8 +319,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
@@ -324,8 +349,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
@@ -342,12 +376,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) {
@@ -877,11 +918,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 1590aab702e267..0f1c0a68534af7 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,
-                                        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);
+    AsyncInfoTy AsyncInfo(*SrcDeviceOrErr);
+    Rc = SrcDeviceOrErr->dataExchange(SrcAddr, *DstDeviceOrErr, DstAddr, Length,
+                                      AsyncInfo);
   }
 
   ODBG(ODT_Interface) << __func__ << " returns " << Rc;
@@ -486,10 +468,16 @@ 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/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index f0c67599c0e1e9..60495495248dc4 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1680,31 +1680,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);
@@ -1714,12 +1689,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 01891f5ddbae74..8404f8bceacdac 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1347,72 +1347,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) {
@@ -1427,30 +1361,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 c789c8ff018593..e4e359cdf5ff79 100644
--- a/offload/tools/kernelreplay/CMakeLists.txt
+++ b/offload/tools/kernelreplay/CMakeLists.txt
@@ -6,6 +6,7 @@ add_offload_tool(llvm-omp-kernel-replay llvm-omp-kernel-replay.cpp
 
 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
   omp

>From 0572ceedcc60fb20f33cbd77beaf067788098a37 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Tue, 8 Sep 2026 03:13:36 -0700
Subject: [PATCH 6/7] Remove isDataExchangable and any associated code Rename
 helper

---
 offload/include/device.h                               |  3 ---
 offload/include/omptarget.h                            |  4 ++--
 offload/liboffload/src/OffloadImpl.cpp                 |  2 +-
 offload/libompaccsupport/PluginManager.cpp             |  3 ---
 offload/libompaccsupport/device.cpp                    | 10 ----------
 .../plugins-nextgen/common/include/PluginInterface.h   |  3 ---
 offload/plugins-nextgen/common/src/PluginInterface.cpp |  5 -----
 7 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/offload/include/device.h b/offload/include/device.h
index 0488fedb616e65..d848d21ae74e13 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -143,9 +143,6 @@ struct DeviceTy {
                        HostDataToTargetTy *Entry = nullptr,
                        MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr);
 
-  // Return true if data can be copied to DstDevice directly
-  bool isDataExchangable(const DeviceTy &DstDevice);
-
   // Copy data from current device to destination device directly
   int32_t dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr,
                        int64_t Size, AsyncInfoTy &AsyncInfo);
diff --git a/offload/include/omptarget.h b/offload/include/omptarget.h
index 5299b7eabe4b5d..f833e3f7ffbb29 100644
--- a/offload/include/omptarget.h
+++ b/offload/include/omptarget.h
@@ -117,7 +117,7 @@ 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);
+__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
@@ -150,7 +150,7 @@ class AsyncInfoTy {
   /// Implicit conversion to the __tgt_async_info which is used in the
   /// plugin interface.
   operator __tgt_async_info *() {
-    return __ol__tgt_GetAsyncInfoFromQueue(Queue);
+    return __ol_tgt_GetAsyncInfoFromQueue(Queue);
   }
 
   /// Get the underlying queue handle.
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 7132d71a7e18f3..8e4b129706b5ea 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -1535,7 +1535,7 @@ int32_t __ol_tgt_GetPluginDeviceId(ol_device_handle_t Device) {
 } // namespace tmp
 
 extern "C" __tgt_async_info *
-__ol__tgt_GetAsyncInfoFromQueue(ol_queue_handle_t Queue) {
+__ol_tgt_GetAsyncInfoFromQueue(ol_queue_handle_t Queue) {
   return Queue->AsyncInfo;
 }
 
diff --git a/offload/libompaccsupport/PluginManager.cpp b/offload/libompaccsupport/PluginManager.cpp
index 1de5c0663681d2..90d08d41382762 100644
--- a/offload/libompaccsupport/PluginManager.cpp
+++ b/offload/libompaccsupport/PluginManager.cpp
@@ -105,9 +105,6 @@ ol_device_handle_t PluginManager::getHostDevice() {
                             &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;
           }
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index 4dbc2351abf4f7..d0bfe383681524 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -907,16 +907,6 @@ bool DeviceTy::printDeviceInfo() {
   return true;
 }
 
-// Whether data can be copied to DstDevice directly
-bool DeviceTy::isDataExchangable(const DeviceTy &DstDevice) {
-  if (RTL != DstDevice.RTL)
-    return false;
-
-  if (RTL->is_data_exchangable(RTLDeviceID, DstDevice.RTLDeviceID))
-    return true;
-  return false;
-}
-
 int32_t DeviceTy::synchronize(AsyncInfoTy &AsyncInfo) {
   ol_queue_handle_t Queue = AsyncInfo.getQueue();
   if (!Queue)
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 60495495248dc4..f702e338441aa6 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1647,9 +1647,6 @@ struct GenericPluginTy {
   /// Return the number of devices this plugin can support.
   int32_t number_of_devices();
 
-  /// Returns non-zero if the data can be exchanged between the two devices.
-  int32_t is_data_exchangable(int32_t SrcDeviceId, int32_t DstDeviceId);
-
   /// Initializes the record and replay mechanism inside the plugin.
   int32_t initialize_record_replay(int32_t DeviceId, int64_t MemorySize,
                                    void *VAddr, bool IsRecord, bool IsNative,
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index 8404f8bceacdac..f8290acab83330 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1221,11 +1221,6 @@ int32_t GenericPluginTy::isDeviceCompatible(int32_t DeviceId, StringRef Image) {
 
 int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); }
 
-int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId,
-                                             int32_t DstDeviceId) {
-  return isDataExchangable(SrcDeviceId, DstDeviceId);
-}
-
 int32_t GenericPluginTy::initialize_record_replay(
     int32_t DeviceId, int64_t MemorySize, void *VAddr, bool IsRecord,
     bool IsNative, bool SaveOutput, bool EmitReport, const char *ReportFilename,

>From 772de766637892a459c5e7c3af215846169a5e67 Mon Sep 17 00:00:00 2001
From: "Duran, Alex" <alejandro.duran at intel.com>
Date: Mon, 7 Sep 2026 08:27:58 -0700
Subject: [PATCH 7/7] [offload][omp] Manage events through liboffload

---
 offload/include/device.h                      |  9 +--
 offload/libompaccsupport/device.cpp           | 53 +++++++++-----
 .../common/include/PluginInterface.h          | 21 ------
 .../common/src/PluginInterface.cpp            | 73 -------------------
 4 files changed, 39 insertions(+), 117 deletions(-)

diff --git a/offload/include/device.h b/offload/include/device.h
index d848d21ae74e13..68b9c25cd9eb92 100644
--- a/offload/include/device.h
+++ b/offload/include/device.h
@@ -180,12 +180,11 @@ struct DeviceTy {
 
   /// Event related interfaces.
   /// {
-  /// Create an event.
-  int32_t createEvent(void **Event);
-
   /// Record the event based on status in AsyncInfo->Queue at the moment the
-  /// function is called.
-  int32_t recordEvent(void *Event, AsyncInfoTy &AsyncInfo);
+  /// function is called. If \p Event already holds an event, it is replaced
+  /// with a new one representing the current queue state and the old event
+  /// is destroyed.
+  int32_t recordEvent(void **Event, AsyncInfoTy &AsyncInfo);
 
   /// Wait for an event. This function can be blocking or non-blocking,
   /// depending on the implementation. It is expected to set a dependence on the
diff --git a/offload/libompaccsupport/device.cpp b/offload/libompaccsupport/device.cpp
index d0bfe383681524..add6e1a267ac89 100644
--- a/offload/libompaccsupport/device.cpp
+++ b/offload/libompaccsupport/device.cpp
@@ -49,23 +49,16 @@ int HostDataToTargetTy::addEventIfNecessary(DeviceTy &Device,
   if (!MappingConfig::get().UseEventsForAtomicTransfers)
     return OFFLOAD_SUCCESS;
 
-  void *Event = getEvent();
-  bool NeedNewEvent = Event == nullptr;
-  if (NeedNewEvent && Device.createEvent(&Event) != OFFLOAD_SUCCESS) {
-    REPORT() << "Failed to create event";
-    return OFFLOAD_FAIL;
-  }
-
   // We cannot assume the event should not be nullptr because we don't
   // know if the target support event. But if a target doesn't,
   // recordEvent should always return success.
-  if (Device.recordEvent(Event, AsyncInfo) != OFFLOAD_SUCCESS) {
+  void *Event = getEvent();
+  if (Device.recordEvent(&Event, AsyncInfo) != OFFLOAD_SUCCESS) {
     REPORT() << "Failed to set dependence on event " << Event;
     return OFFLOAD_FAIL;
   }
 
-  if (NeedNewEvent)
-    setEvent(Event);
+  setEvent(Event);
 
   return OFFLOAD_SUCCESS;
 }
@@ -932,24 +925,48 @@ int32_t DeviceTy::queryAsync(AsyncInfoTy &AsyncInfo) {
   return OFFLOAD_SUCCESS;
 }
 
-int32_t DeviceTy::createEvent(void **Event) {
-  return RTL->create_event(RTLDeviceID, Event);
-}
+int32_t DeviceTy::recordEvent(void **Event, AsyncInfoTy &AsyncInfo) {
+  ol_event_handle_t NewEvent;
+  if (auto Res =
+          olCreateEvent(AsyncInfo.getQueue(), OL_EVENT_FLAGS_NONE, &NewEvent)) {
+    REPORT() << "Failure to record event: " << Res->Details;
+    return OFFLOAD_FAIL;
+  }
 
-int32_t DeviceTy::recordEvent(void *Event, AsyncInfoTy &AsyncInfo) {
-  return RTL->record_event(RTLDeviceID, Event, AsyncInfo);
+  if (*Event) {
+    if (auto Res = olDestroyEvent(static_cast<ol_event_handle_t>(*Event)))
+      REPORT() << "Failure to destroy previous event " << *Event << ": "
+               << Res->Details;
+  }
+
+  *Event = NewEvent;
+  return OFFLOAD_SUCCESS;
 }
 
 int32_t DeviceTy::waitEvent(void *Event, AsyncInfoTy &AsyncInfo) {
-  return RTL->wait_event(RTLDeviceID, Event, AsyncInfo);
+  ol_event_handle_t E = static_cast<ol_event_handle_t>(Event);
+  if (auto Res = olWaitEvents(AsyncInfo.getQueue(), &E, 1)) {
+    REPORT() << "Failure to wait for event " << Event << ": " << Res->Details;
+    return OFFLOAD_FAIL;
+  }
+  return OFFLOAD_SUCCESS;
 }
 
 int32_t DeviceTy::syncEvent(void *Event) {
-  return RTL->sync_event(RTLDeviceID, Event);
+  if (auto Res = olSyncEvent(static_cast<ol_event_handle_t>(Event))) {
+    REPORT() << "Failure to synchronize event " << Event << ": "
+             << Res->Details;
+    return OFFLOAD_FAIL;
+  }
+  return OFFLOAD_SUCCESS;
 }
 
 int32_t DeviceTy::destroyEvent(void *Event) {
-  return RTL->destroy_event(RTLDeviceID, Event);
+  if (auto Res = olDestroyEvent(static_cast<ol_event_handle_t>(Event))) {
+    REPORT() << "Failure to destroy event " << Event << ": " << Res->Details;
+    return OFFLOAD_FAIL;
+  }
+  return OFFLOAD_SUCCESS;
 }
 
 void DeviceTy::dumpOffloadEntries() {
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index f702e338441aa6..7176a932d1ff17 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -1692,27 +1692,6 @@ struct GenericPluginTy {
   /// Prints information about the given devices supported by the plugin.
   void print_device_info(int32_t DeviceId);
 
-  /// Creates an event in the given plugin if supported.
-  int32_t create_event(int32_t DeviceId, void **EventPtr);
-
-  /// Records an event that has occurred.
-  int32_t record_event(int32_t DeviceId, void *EventPtr,
-                       __tgt_async_info *AsyncInfoPtr);
-
-  /// Wait until an event has occurred.
-  int32_t wait_event(int32_t DeviceId, void *EventPtr,
-                     __tgt_async_info *AsyncInfoPtr);
-
-  /// Synchronize execution until an event is done.
-  int32_t sync_event(int32_t DeviceId, void *EventPtr);
-
-  /// Get the elapsed time in milliseconds between two events.
-  int32_t get_event_elapsed_time(int32_t DeviceId, void *StartEventPtr,
-                                 void *EndEventPtr, float *ElapsedTime);
-
-  /// Remove the event from the plugin.
-  int32_t destroy_event(int32_t DeviceId, void *EventPtr);
-
   /// Remove the event from the plugin.
   void set_info_flag(uint32_t NewInfoLevel);
 
diff --git a/offload/plugins-nextgen/common/src/PluginInterface.cpp b/offload/plugins-nextgen/common/src/PluginInterface.cpp
index f8290acab83330..bd8ba6a6bdc64d 100644
--- a/offload/plugins-nextgen/common/src/PluginInterface.cpp
+++ b/offload/plugins-nextgen/common/src/PluginInterface.cpp
@@ -1372,79 +1372,6 @@ void GenericPluginTy::print_device_info(int32_t DeviceId) {
              << " info: " << toString(std::move(Err));
 }
 
-int32_t GenericPluginTy::create_event(int32_t DeviceId, void **EventPtr) {
-  auto Err = getDevice(DeviceId).createEvent(EventPtr);
-  if (Err) {
-    REPORT() << "Failure to create event: " << toString(std::move(Err));
-    return OFFLOAD_FAIL;
-  }
-
-  return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::record_event(int32_t DeviceId, void *EventPtr,
-                                      __tgt_async_info *AsyncInfoPtr) {
-  auto Err = getDevice(DeviceId).recordEvent(EventPtr, AsyncInfoPtr);
-  if (Err) {
-    REPORT() << "Failure to record event " << EventPtr << ": "
-             << toString(std::move(Err));
-    return OFFLOAD_FAIL;
-  }
-
-  return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::wait_event(int32_t DeviceId, void *EventPtr,
-                                    __tgt_async_info *AsyncInfoPtr) {
-  auto Err = getDevice(DeviceId).waitEvent(EventPtr, AsyncInfoPtr);
-  if (Err) {
-    REPORT() << "Failure to wait event " << EventPtr << ": "
-             << toString(std::move(Err));
-    return OFFLOAD_FAIL;
-  }
-
-  return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::sync_event(int32_t DeviceId, void *EventPtr) {
-  auto Err = getDevice(DeviceId).syncEvent(EventPtr);
-  if (Err) {
-    REPORT() << "Failure to synchronize event " << EventPtr << ": "
-             << toString(std::move(Err));
-    return OFFLOAD_FAIL;
-  }
-
-  return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::get_event_elapsed_time(int32_t DeviceId,
-                                                void *StartEventPtr,
-                                                void *EndEventPtr,
-                                                float *ElapsedTime) {
-  auto ElapsedTimeOrErr =
-      getDevice(DeviceId).getEventElapsedTime(StartEventPtr, EndEventPtr);
-  if (!ElapsedTimeOrErr) {
-    REPORT() << "Failure to get elapsed time between events " << StartEventPtr
-             << " and " << EndEventPtr << ": "
-             << toString(ElapsedTimeOrErr.takeError());
-    return OFFLOAD_FAIL;
-  }
-
-  *ElapsedTime = *ElapsedTimeOrErr;
-  return OFFLOAD_SUCCESS;
-}
-
-int32_t GenericPluginTy::destroy_event(int32_t DeviceId, void *EventPtr) {
-  auto Err = getDevice(DeviceId).destroyEvent(EventPtr);
-  if (Err) {
-    REPORT() << "Failure to destroy event " << EventPtr << ": "
-             << toString(std::move(Err));
-    return OFFLOAD_FAIL;
-  }
-
-  return OFFLOAD_SUCCESS;
-}
-
 void GenericPluginTy::set_info_flag(uint32_t NewInfoLevel) {
   std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal();
   InfoLevel.store(NewInfoLevel);



More information about the llvm-branch-commits mailing list