[llvm-branch-commits] [llvm] [offload][omp] Initialize devices through liboffload (PR #221276)

Alex Duran via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Sep 4 09:19:53 PDT 2026


https://github.com/adurang created https://github.com/llvm/llvm-project/pull/221276

None

>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 1/3] [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 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 2/3] [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 3/3] [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,



More information about the llvm-branch-commits mailing list