[llvm] [OFFLOAD] Add support for host offloading device (PR #171010)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 21 09:17:57 PST 2026


https://github.com/fineg74 updated https://github.com/llvm/llvm-project/pull/171010

>From 8fb7fb823baa1f07b59fdd35256248eeafb19196 Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Fri, 21 Nov 2025 18:35:24 -0800
Subject: [PATCH 1/6] Add support for host offloading device

---
 offload/liboffload/API/Device.td       |  9 +++++++++
 offload/liboffload/src/OffloadImpl.cpp | 10 ++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/offload/liboffload/API/Device.td b/offload/liboffload/API/Device.td
index 6ada191089674..79ad077b945e2 100644
--- a/offload/liboffload/API/Device.td
+++ b/offload/liboffload/API/Device.td
@@ -131,3 +131,12 @@ def olGetDeviceInfoSize : Function {
     Return<"OL_ERRC_INVALID_DEVICE">
   ];
 }
+
+def olGetHostDevice : Function {
+  let desc = "Returns the host device.";
+  let details = [];
+  let params = [
+    Param<"ol_device_handle_t*", "Device", "handle of the device instance", PARAM_OUT>,
+  ];
+  let returns = [];
+}
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index eab9627217ca8..0765949280b04 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -263,6 +263,8 @@ constexpr ol_platform_backend_t pluginNameToBackend(StringRef Name) {
     return OL_PLATFORM_BACKEND_AMDGPU;
   } else if (Name == "cuda") {
     return OL_PLATFORM_BACKEND_CUDA;
+  } else if (Name == "host") {
+    return OL_PLATFORM_BACKEND_HOST;
   } else {
     return OL_PLATFORM_BACKEND_UNKNOWN;
   }
@@ -276,7 +278,6 @@ Error initPlugins(OffloadContext &Context) {
   // Attempt to create an instance of each supported plugin.
 #define PLUGIN_TARGET(Name)                                                    \
   do {                                                                         \
-    if (StringRef(#Name) != "host")                                            \
       Context.Platforms.emplace_back(std::make_unique<ol_platform_impl_t>(     \
           std::unique_ptr<GenericPluginTy>(createPlugin_##Name()),             \
           pluginNameToBackend(#Name)));                                        \
@@ -349,7 +350,7 @@ Error olGetPlatformInfoImplDetail(ol_platform_handle_t Platform,
                                   ol_platform_info_t PropName, size_t PropSize,
                                   void *PropValue, size_t *PropSizeRet) {
   InfoWriter Info(PropSize, PropValue, PropSizeRet);
-  bool IsHost = Platform->BackendType == OL_PLATFORM_BACKEND_HOST;
+  bool IsHost = Platform->Plugin == nullptr;
 
   // Note that the plugin is potentially uninitialized here. It will need to be
   // initialized once info is added that requires it to be initialized.
@@ -1214,5 +1215,10 @@ Error olLaunchHostFunction_impl(ol_queue_handle_t Queue,
                                                 Queue->AsyncInfo);
 }
 
+Error olGetHostDevice_impl(ol_device_handle_t *Device) {
+  *Device = OffloadContext::get().HostDevice;
+  return Error::success();
+}
+
 } // namespace offload
 } // namespace llvm

>From dc8f4748025bfd68c5bc7886f772b80e60c69a7d Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Wed, 10 Dec 2025 13:50:55 -0800
Subject: [PATCH 2/6] Fix formatting issues

---
 offload/liboffload/src/OffloadImpl.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 0765949280b04..0766b235e1451 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -278,9 +278,9 @@ Error initPlugins(OffloadContext &Context) {
   // Attempt to create an instance of each supported plugin.
 #define PLUGIN_TARGET(Name)                                                    \
   do {                                                                         \
-      Context.Platforms.emplace_back(std::make_unique<ol_platform_impl_t>(     \
-          std::unique_ptr<GenericPluginTy>(createPlugin_##Name()),             \
-          pluginNameToBackend(#Name)));                                        \
+    Context.Platforms.emplace_back(std::make_unique<ol_platform_impl_t>(       \
+        std::unique_ptr<GenericPluginTy>(createPlugin_##Name()),               \
+        pluginNameToBackend(#Name)));                                          \
   } while (false);
 #include "Shared/Targets.def"
 

>From 554af110573c9cef8e7e2ca692822ecea4f46ed6 Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Wed, 10 Dec 2025 14:16:37 -0800
Subject: [PATCH 3/6] Address PR comments

---
 offload/liboffload/src/OffloadImpl.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 0766b235e1451..5d75ff047ee5b 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -299,6 +299,9 @@ Error initPlugins(OffloadContext &Context) {
                            .emplace_back(std::make_unique<ol_device_impl_t>(
                                -1, nullptr, *HostPlatform, InfoTreeNode{}))
                            .get();
+  if (!Context.HostDevice)
+    return createOffloadError(ErrorCode::INVALID_NULL_HANDLE,
+                              "Host Device is invalid");
 
   Context.TracingEnabled = std::getenv("OFFLOAD_TRACE");
   Context.ValidationEnabled = !std::getenv("OFFLOAD_DISABLE_VALIDATION");

>From 68953e0ae6e4e788d8cd01beb5920514a1336d6e Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Mon, 19 Jan 2026 13:47:14 -0800
Subject: [PATCH 4/6] Fix some unittest failures

---
 offload/plugins-nextgen/host/src/rtl.cpp      | 27 ++++++++++++++-----
 .../OffloadAPI/common/Environment.cpp         | 22 +++------------
 2 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index 81fbb671aa88f..8f662b616993b 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -299,10 +299,8 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
   Error dataExchangeImpl(const void *SrcPtr, GenericDeviceTy &DstGenericDevice,
                          void *DstPtr, int64_t Size,
                          AsyncInfoWrapperTy &AsyncInfoWrapper) override {
-    // This function should never be called because the function
-    // GenELF64PluginTy::isDataExchangable() returns false.
-    return Plugin::error(ErrorCode::UNSUPPORTED,
-                         "dataExchangeImpl not supported");
+    std::memcpy(DstPtr, SrcPtr, Size);
+    return Plugin::success();
   }
 
   /// Insert a data fence between previous data operations and the following
@@ -342,8 +340,7 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
 
   /// This plugin does not support interoperability
   Error initAsyncInfoImpl(AsyncInfoWrapperTy &AsyncInfoWrapper) override {
-    return Plugin::error(ErrorCode::UNSUPPORTED,
-                         "initAsyncInfoImpl not supported");
+    return Plugin::success();
   }
 
   Error enqueueHostCallImpl(void (*Callback)(void *), void *UserData,
@@ -379,6 +376,22 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
   Expected<InfoTreeNode> obtainInfoImpl() override {
     InfoTreeNode Info;
     Info.add("Device Type", "Generic-elf-64bit");
+    Info.add("Product Name", "Host", "", DeviceInfo::PRODUCT_NAME);
+    Info.add("Device Name", " Host Device", "", DeviceInfo::NAME);
+    Info.add("Max Group size", 1, "", DeviceInfo::MAX_WORK_GROUP_SIZE);
+    auto &MaxGroupSize =
+      *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
+                DeviceInfo::MAX_WORK_GROUP_SIZE_PER_DIMENSION);
+    MaxGroupSize.add("x", 1);
+    MaxGroupSize.add("y", 1);
+    MaxGroupSize.add("z", 1);
+    Info.add("Maximum Grid Dimensions", 1,
+           "", DeviceInfo::MAX_WORK_SIZE);
+    auto &MaxSize = *Info.add("Grid Size per Dimension", std::monostate{}, "",
+                            DeviceInfo::MAX_WORK_SIZE_PER_DIMENSION);
+    MaxSize.add("x", 1);
+    MaxSize.add("y", 1);
+    MaxSize.add("z", 1);
     return Info;
   }
 
@@ -472,7 +485,7 @@ struct GenELF64PluginTy final : public GenericPluginTy {
 
   /// This plugin does not support exchanging data between two devices.
   bool isDataExchangable(int32_t SrcDeviceId, int32_t DstDeviceId) override {
-    return false;
+    return true;
   }
 
   /// All images (ELF-compatible) should be compatible with this plugin.
diff --git a/offload/unittests/OffloadAPI/common/Environment.cpp b/offload/unittests/OffloadAPI/common/Environment.cpp
index f8dcef6215bd9..cf43020348252 100644
--- a/offload/unittests/OffloadAPI/common/Environment.cpp
+++ b/offload/unittests/OffloadAPI/common/Environment.cpp
@@ -116,7 +116,9 @@ const std::vector<TestEnvironment::Device> &TestEnvironment::getDevices() {
             ol_platform_backend_t Backend;
             olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,
                               sizeof(Backend), &Backend);
-            if (Backend != OL_PLATFORM_BACKEND_HOST) {
+            ol_device_handle_t Host;
+            olGetHostDevice(&Host);
+            if (D != Host) {
               auto *OutDevices = static_cast<decltype(Devices) *>(Data);
               std::string Name;
               raw_string_ostream NameStr(Name);
@@ -139,23 +141,7 @@ ol_device_handle_t TestEnvironment::getHostDevice() {
   static ol_device_handle_t HostDevice = nullptr;
 
   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) {
-            *(static_cast<ol_device_handle_t *>(Data)) = D;
-            return false;
-          }
-
-          return true;
-        },
-        &HostDevice);
+    olGetHostDevice(&HostDevice);
   }
 
   return HostDevice;

>From 92f703e4c7dcd00e856036b16c5e85e7d0ffde41 Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Tue, 20 Jan 2026 18:07:39 -0800
Subject: [PATCH 5/6] Fix more unit tests

---
 offload/plugins-nextgen/host/src/rtl.cpp | 27 +++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index 8f662b616993b..5fe51172f13c4 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -374,10 +374,22 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
 
   /// Print information about the device.
   Expected<InfoTreeNode> obtainInfoImpl() override {
+    constexpr auto uint32_max = std::numeric_limits<uint32_t>::max();
     InfoTreeNode Info;
     Info.add("Device Type", "Generic-elf-64bit");
     Info.add("Product Name", "Host", "", DeviceInfo::PRODUCT_NAME);
-    Info.add("Device Name", " Host Device", "", DeviceInfo::NAME);
+    Info.add("Vendor", "Unknown", "", DeviceInfo::VENDOR);
+    Info.add("Vendor ID", 1, "", DeviceInfo::VENDOR_ID);
+    Info.add("Device Name", " Host Offload Device", "", DeviceInfo::NAME);
+    Info.add("Driver Version", "Unknown", "", DeviceInfo::DRIVER_VERSION);
+    Info.add("Number of total EUs", 1, "", DeviceInfo::NUM_COMPUTE_UNITS);
+    Info.add("Max memory clock frequency (MHz)", 1, "", DeviceInfo::MEMORY_CLOCK_RATE);
+    Info.add("Max clock frequency (MHz)", 1, "", DeviceInfo::MAX_CLOCK_FREQUENCY);
+    Info.add("Memory Address Size", uint64_t{64u}, "bits",
+           DeviceInfo::ADDRESS_BITS);
+    Info.add("Local memory size (bytes)", 1, "", DeviceInfo::WORK_GROUP_LOCAL_MEM_SIZE);
+    Info.add("Global memory size (bytes)", 1, "", DeviceInfo::GLOBAL_MEM_SIZE);
+    Info.add("Max Memory Allocation Size (bytes)", 1, "", DeviceInfo::MAX_MEM_ALLOC_SIZE);
     Info.add("Max Group size", 1, "", DeviceInfo::MAX_WORK_GROUP_SIZE);
     auto &MaxGroupSize =
       *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
@@ -385,16 +397,21 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
     MaxGroupSize.add("x", 1);
     MaxGroupSize.add("y", 1);
     MaxGroupSize.add("z", 1);
-    Info.add("Maximum Grid Dimensions", 1,
+    Info.add("Maximum Grid Dimensions", uint32_max,
            "", DeviceInfo::MAX_WORK_SIZE);
     auto &MaxSize = *Info.add("Grid Size per Dimension", std::monostate{}, "",
                             DeviceInfo::MAX_WORK_SIZE_PER_DIMENSION);
-    MaxSize.add("x", 1);
-    MaxSize.add("y", 1);
-    MaxSize.add("z", 1);
+    MaxSize.add("x", uint32_max);
+    MaxSize.add("y", uint32_max);
+    MaxSize.add("z", uint32_max);
     return Info;
   }
 
+  Error getDeviceMemorySize(uint64_t &DSize) override {
+    DSize = 1;
+    return Plugin::success();
+  }
+
   /// Getters and setters for stack size and heap size not relevant.
   Error getDeviceStackSize(uint64_t &Value) override {
     Value = 0;

>From 6071c88c396c755b128242d7a800921ef2a4ce99 Mon Sep 17 00:00:00 2001
From: "Fine, Gregory" <gregory.fine at intel.com>
Date: Wed, 21 Jan 2026 09:17:43 -0800
Subject: [PATCH 6/6] Fix formatting

---
 offload/plugins-nextgen/host/src/rtl.cpp | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index 5fe51172f13c4..aacb0e33c2430 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -383,24 +383,28 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
     Info.add("Device Name", " Host Offload Device", "", DeviceInfo::NAME);
     Info.add("Driver Version", "Unknown", "", DeviceInfo::DRIVER_VERSION);
     Info.add("Number of total EUs", 1, "", DeviceInfo::NUM_COMPUTE_UNITS);
-    Info.add("Max memory clock frequency (MHz)", 1, "", DeviceInfo::MEMORY_CLOCK_RATE);
-    Info.add("Max clock frequency (MHz)", 1, "", DeviceInfo::MAX_CLOCK_FREQUENCY);
+    Info.add("Max memory clock frequency (MHz)", 1, "",
+             DeviceInfo::MEMORY_CLOCK_RATE);
+    Info.add("Max clock frequency (MHz)", 1, "",
+             DeviceInfo::MAX_CLOCK_FREQUENCY);
     Info.add("Memory Address Size", uint64_t{64u}, "bits",
-           DeviceInfo::ADDRESS_BITS);
-    Info.add("Local memory size (bytes)", 1, "", DeviceInfo::WORK_GROUP_LOCAL_MEM_SIZE);
+             DeviceInfo::ADDRESS_BITS);
+    Info.add("Local memory size (bytes)", 1, "",
+             DeviceInfo::WORK_GROUP_LOCAL_MEM_SIZE);
     Info.add("Global memory size (bytes)", 1, "", DeviceInfo::GLOBAL_MEM_SIZE);
-    Info.add("Max Memory Allocation Size (bytes)", 1, "", DeviceInfo::MAX_MEM_ALLOC_SIZE);
+    Info.add("Max Memory Allocation Size (bytes)", 1, "",
+             DeviceInfo::MAX_MEM_ALLOC_SIZE);
     Info.add("Max Group size", 1, "", DeviceInfo::MAX_WORK_GROUP_SIZE);
     auto &MaxGroupSize =
-      *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
-                DeviceInfo::MAX_WORK_GROUP_SIZE_PER_DIMENSION);
+        *Info.add("Workgroup Max Size per Dimension", std::monostate{}, "",
+                  DeviceInfo::MAX_WORK_GROUP_SIZE_PER_DIMENSION);
     MaxGroupSize.add("x", 1);
     MaxGroupSize.add("y", 1);
     MaxGroupSize.add("z", 1);
-    Info.add("Maximum Grid Dimensions", uint32_max,
-           "", DeviceInfo::MAX_WORK_SIZE);
+    Info.add("Maximum Grid Dimensions", uint32_max, "",
+             DeviceInfo::MAX_WORK_SIZE);
     auto &MaxSize = *Info.add("Grid Size per Dimension", std::monostate{}, "",
-                            DeviceInfo::MAX_WORK_SIZE_PER_DIMENSION);
+                              DeviceInfo::MAX_WORK_SIZE_PER_DIMENSION);
     MaxSize.add("x", uint32_max);
     MaxSize.add("y", uint32_max);
     MaxSize.add("z", uint32_max);



More information about the llvm-commits mailing list