[llvm] [offload] Add floating-point support detection queries (PR #193233)

Ɓukasz Plewa via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 21 07:40:55 PDT 2026


https://github.com/lplewa updated https://github.com/llvm/llvm-project/pull/193233

>From f5a64d5429e8a1e772a45dcc8ceae7cc795d95f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Plewa?= <lukasz.plewa at intel.com>
Date: Mon, 20 Apr 2026 13:01:56 +0200
Subject: [PATCH] [offload] Add floating-point support detection queries

Add device info queries to detect support for half-, single-, and
double-precision floating-point formats.

For the AMDGPU, CUDA, and Host plugins, add the new queries alongside
the existing capability reporting without changing current behavior.

For the Level Zero plugin, implement floating-point support detection
and capability querying.
---
 offload/liboffload/API/Device.td              |  7 +-
 offload/liboffload/src/OffloadImpl.cpp        | 29 ++++----
 offload/plugins-nextgen/amdgpu/src/rtl.cpp    | 23 ++++++
 offload/plugins-nextgen/common/CMakeLists.txt |  1 +
 offload/plugins-nextgen/cuda/src/rtl.cpp      | 21 ++++++
 offload/plugins-nextgen/host/src/rtl.cpp      | 22 ++++++
 .../level_zero/dynamic_l0/L0DynWrapper.cpp    |  1 +
 .../level_zero/dynamic_l0/level_zero/ze_api.h | 51 ++++++++++++++
 .../level_zero/include/L0Device.h             | 23 ++++++
 .../level_zero/src/L0Device.cpp               | 70 +++++++++++++++++++
 .../deviceinfo/llvm-offload-device-info.cpp   |  8 +++
 .../OffloadAPI/device/olGetDeviceInfo.cpp     |  6 ++
 12 files changed, 245 insertions(+), 17 deletions(-)

diff --git a/offload/liboffload/API/Device.td b/offload/liboffload/API/Device.td
index 6ada191089674..86ccf446bdec8 100644
--- a/offload/liboffload/API/Device.td
+++ b/offload/liboffload/API/Device.td
@@ -47,7 +47,12 @@ def ol_device_info_t : Enum {
   ];
   list<TaggedEtor> fp_configs = !foreach(type, ["Single", "Double", "Half"], TaggedEtor<type # "_FP_CONFIG", "ol_device_fp_capability_flags_t", type # " precision floating point capability">);
   list<TaggedEtor> native_vec_widths = !foreach(type, ["char","short","int","long","float","double","half"], TaggedEtor<"NATIVE_VECTOR_WIDTH_" # type, "uint32_t", "Native vector width for " # type>);
-  let etors = !listconcat(basic_etors, fp_configs, native_vec_widths);
+  list<TaggedEtor> fp_support =
+      !foreach(type, ["Single", "Double", "Half"],
+               TaggedEtor<type#"_FP_SUPPORT", "bool",
+                          type#" precision floating point support">);
+  let etors =
+      !listconcat(basic_etors, fp_configs, native_vec_widths, fp_support);
 }
 
 def ol_device_fp_capability_flag_t : Enum {
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 314788794842d..71712c2bc6b45 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -429,22 +429,6 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
     else
       return Info.write<ol_device_type_t>(OL_DEVICE_TYPE_GPU);
 
-  case OL_DEVICE_INFO_SINGLE_FP_CONFIG:
-  case OL_DEVICE_INFO_DOUBLE_FP_CONFIG: {
-    ol_device_fp_capability_flags_t flags{0};
-    flags |= OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT |
-             OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST |
-             OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO |
-             OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF |
-             OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN |
-             OL_DEVICE_FP_CAPABILITY_FLAG_DENORM |
-             OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
-    return Info.write(flags);
-  }
-
-  case OL_DEVICE_INFO_HALF_FP_CONFIG:
-    return Info.write<ol_device_fp_capability_flags_t>(0);
-
   case OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR:
   case OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT:
   case OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT:
@@ -503,6 +487,9 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
   case OL_DEVICE_INFO_NUM_COMPUTE_UNITS:
   case OL_DEVICE_INFO_ADDRESS_BITS:
   case OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY:
+  case OL_DEVICE_INFO_SINGLE_FP_CONFIG:
+  case OL_DEVICE_INFO_DOUBLE_FP_CONFIG:
+  case OL_DEVICE_INFO_HALF_FP_CONFIG:
   case OL_DEVICE_INFO_MEMORY_CLOCK_RATE: {
     // Uint32 values
     if (!std::holds_alternative<uint64_t>(Entry->Value))
@@ -522,6 +509,16 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
     return Info.write(std::get<uint64_t>(Entry->Value));
   }
 
+  case OL_DEVICE_INFO_SINGLE_FP_SUPPORT:
+  case OL_DEVICE_INFO_DOUBLE_FP_SUPPORT:
+  case OL_DEVICE_INFO_HALF_FP_SUPPORT: {
+    // Boolean values
+    if (!std::holds_alternative<bool>(Entry->Value))
+      return makeError(ErrorCode::BACKEND_FAILURE,
+                       "plugin returned incorrect type");
+    return Info.write<bool>(std::get<bool>(Entry->Value));
+  }
+
   case OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION:
   case OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION: {
     // {x, y, z} triples
diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
index e608c5d6ce666..6817245572f17 100644
--- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp
+++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
@@ -31,6 +31,7 @@
 #include "Utils/ELF.h"
 
 #include "GlobalHandler.h"
+#include "OffloadAPI.h"
 #include "OpenMP/OMPT/Callback.h"
 #include "PluginInterface.h"
 #include "UtilitiesRTL.h"
@@ -3321,6 +3322,28 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy {
     if (Err)
       consumeError(std::move(Err));
 
+    ol_device_fp_capability_flags_t FPFlags =
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF |
+        OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN |
+        OL_DEVICE_FP_CAPABILITY_FLAG_DENORM | OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+
+    Info.add("Single FP Support", true, "", DeviceInfo::SINGLE_FP_SUPPORT);
+    Info.add("Single FP Capabilities", FPFlags, "",
+             DeviceInfo::SINGLE_FP_CONFIG);
+
+    Info.add("Double FP Support", true, "", DeviceInfo::DOUBLE_FP_SUPPORT);
+    Info.add("Double FP Capabilities", FPFlags, "",
+             DeviceInfo::DOUBLE_FP_CONFIG);
+
+    // TODO: Use HSA_AGENT_INFO_FAST_F16_OPERATION to detect FP16 support.
+    Info.add("Half FP Support", ol_bool_t(false), "",
+             DeviceInfo::HALF_FP_SUPPORT);
+    Info.add("Half FP Capabilities", ol_device_fp_capability_flags_t{0}, "",
+             DeviceInfo::HALF_FP_CONFIG);
+
     return Info;
   }
 
diff --git a/offload/plugins-nextgen/common/CMakeLists.txt b/offload/plugins-nextgen/common/CMakeLists.txt
index cd150d1bf9298..e7a9451df4cfc 100644
--- a/offload/plugins-nextgen/common/CMakeLists.txt
+++ b/offload/plugins-nextgen/common/CMakeLists.txt
@@ -53,6 +53,7 @@ target_link_options(PluginCommon PUBLIC ${offload_link_flags})
 target_include_directories(PluginCommon PUBLIC
   ${CMAKE_CURRENT_SOURCE_DIR}/include
   ${CMAKE_CURRENT_BINARY_DIR}/include
+  ${CMAKE_CURRENT_BINARY_DIR}/../../liboffload/API
   ${LIBOMPTARGET_LLVM_INCLUDE_DIRS}
   ${LIBOMPTARGET_BINARY_INCLUDE_DIR}
   ${LIBOMPTARGET_INCLUDE_DIR}
diff --git a/offload/plugins-nextgen/cuda/src/rtl.cpp b/offload/plugins-nextgen/cuda/src/rtl.cpp
index 8a7c8a4ffd42d..5d93ec589b1f8 100644
--- a/offload/plugins-nextgen/cuda/src/rtl.cpp
+++ b/offload/plugins-nextgen/cuda/src/rtl.cpp
@@ -21,6 +21,7 @@
 #include "Shared/Environment.h"
 
 #include "GlobalHandler.h"
+#include "OffloadAPI.h"
 #include "OpenMP/OMPT/Callback.h"
 #include "PluginInterface.h"
 #include "Utils/ELF.h"
@@ -1241,6 +1242,26 @@ struct CUDADeviceTy : public GenericDeviceTy {
 
     Info.add("Compute Capabilities", ComputeCapability.str());
 
+    ol_device_fp_capability_flags_t FPFlags =
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF |
+        OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN |
+        OL_DEVICE_FP_CAPABILITY_FLAG_DENORM | OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+
+    Info.add("Single FP Support", true, "", DeviceInfo::SINGLE_FP_SUPPORT);
+    Info.add("Single FP Capabilities", FPFlags, "",
+             DeviceInfo::SINGLE_FP_CONFIG);
+
+    Info.add("Double FP Support", true, "", DeviceInfo::DOUBLE_FP_SUPPORT);
+    Info.add("Double FP Capabilities", FPFlags, "",
+             DeviceInfo::DOUBLE_FP_CONFIG);
+
+    Info.add("Half FP Support", false, "", DeviceInfo::HALF_FP_SUPPORT);
+    Info.add("Half FP Capabilities", ol_device_fp_capability_flags_t{0}, "",
+             DeviceInfo::HALF_FP_CONFIG);
+
     return Info;
   }
 
diff --git a/offload/plugins-nextgen/host/src/rtl.cpp b/offload/plugins-nextgen/host/src/rtl.cpp
index bef49faf45383..3f2cc612e4df6 100644
--- a/offload/plugins-nextgen/host/src/rtl.cpp
+++ b/offload/plugins-nextgen/host/src/rtl.cpp
@@ -20,6 +20,7 @@
 #include "Utils/ELF.h"
 
 #include "GlobalHandler.h"
+#include "OffloadAPI.h"
 #include "OpenMP/OMPT/Callback.h"
 #include "PluginInterface.h"
 #include "omptarget.h"
@@ -403,6 +404,27 @@ struct GenELF64DeviceTy : public GenericDeviceTy {
     MaxSize.add("x", uint32_max);
     MaxSize.add("y", uint32_max);
     MaxSize.add("z", uint32_max);
+
+    ol_device_fp_capability_flags_t FPFlags =
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO |
+        OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF |
+        OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN |
+        OL_DEVICE_FP_CAPABILITY_FLAG_DENORM | OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+
+    Info.add("Single FP Support", true, "", DeviceInfo::SINGLE_FP_SUPPORT);
+    Info.add("Single FP Capabilities", FPFlags, "",
+             DeviceInfo::SINGLE_FP_CONFIG);
+
+    Info.add("Double FP Support", true, "", DeviceInfo::DOUBLE_FP_SUPPORT);
+    Info.add("Double FP Capabilities", FPFlags, "",
+             DeviceInfo::DOUBLE_FP_CONFIG);
+
+    Info.add("Half FP Support", false, "", DeviceInfo::HALF_FP_SUPPORT);
+    Info.add("Half FP Capabilities", ol_device_fp_capability_flags_t{0}, "",
+             DeviceInfo::HALF_FP_CONFIG);
+
     return Info;
   }
 
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
index e68bddd0047a1..8643897facacd 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
@@ -50,6 +50,7 @@ DLWRAP(zeDeviceCanAccessPeer, 3)
 DLWRAP(zeDeviceGetProperties, 2)
 DLWRAP(zeDeviceGetCommandQueueGroupProperties, 3)
 DLWRAP(zeDeviceGetComputeProperties, 2)
+DLWRAP(zeDeviceGetModuleProperties, 2)
 DLWRAP(zeDeviceGetMemoryProperties, 3)
 DLWRAP(zeDeviceGetCacheProperties, 3)
 DLWRAP(zeDeviceGetGlobalTimestamps, 3)
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
index 6049bd2c83ad1..81a4c00269160 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
@@ -148,6 +148,7 @@ typedef enum _ze_structure_type_t {
   ZE_STRUCTURE_TYPE_DRIVER_PROPERTIES = 0x1,
   ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES = 0x3,
   ZE_STRUCTURE_TYPE_DEVICE_COMPUTE_PROPERTIES = 0x4,
+  ZE_STRUCTURE_TYPE_DEVICE_MODULE_PROPERTIES = 0x5,
   ZE_STRUCTURE_TYPE_COMMAND_QUEUE_GROUP_PROPERTIES = 0x6,
   ZE_STRUCTURE_TYPE_DEVICE_MEMORY_PROPERTIES = 0x7,
   ZE_STRUCTURE_TYPE_DEVICE_CACHE_PROPERTIES = 0x9,
@@ -399,6 +400,53 @@ typedef struct _ze_device_cache_properties_t {
   size_t cacheSize;
 } ze_device_cache_properties_t;
 
+/* Native kernel UUID */
+#ifndef ZE_MAX_NATIVE_KERNEL_UUID_SIZE
+#define ZE_MAX_NATIVE_KERNEL_UUID_SIZE 16
+#endif
+
+typedef struct _ze_native_kernel_uuid_t {
+  uint8_t id[ZE_MAX_NATIVE_KERNEL_UUID_SIZE];
+} ze_native_kernel_uuid_t;
+
+/* Device module flags */
+typedef uint32_t ze_device_module_flags_t;
+typedef enum _ze_device_module_flag_t {
+  ZE_DEVICE_MODULE_FLAG_FP16 = ZE_BIT(0),
+  ZE_DEVICE_MODULE_FLAG_FP64 = ZE_BIT(1),
+  ZE_DEVICE_MODULE_FLAG_INT64_ATOMICS = ZE_BIT(2),
+  ZE_DEVICE_MODULE_FLAG_DP4A = ZE_BIT(3),
+  ZE_DEVICE_MODULE_FLAG_FORCE_UINT32 = 0x7fffffff
+} ze_device_module_flag_t;
+
+/* Floating-point capability flags */
+typedef uint32_t ze_device_fp_flags_t;
+typedef enum _ze_device_fp_flag_t {
+  ZE_DEVICE_FP_FLAG_DENORM = ZE_BIT(0),
+  ZE_DEVICE_FP_FLAG_INF_NAN = ZE_BIT(1),
+  ZE_DEVICE_FP_FLAG_ROUND_TO_NEAREST = ZE_BIT(2),
+  ZE_DEVICE_FP_FLAG_ROUND_TO_ZERO = ZE_BIT(3),
+  ZE_DEVICE_FP_FLAG_ROUND_TO_INF = ZE_BIT(4),
+  ZE_DEVICE_FP_FLAG_FMA = ZE_BIT(5),
+  ZE_DEVICE_FP_FLAG_ROUNDED_DIVIDE_SQRT = ZE_BIT(6),
+  ZE_DEVICE_FP_FLAG_SOFT_FLOAT = ZE_BIT(7),
+  ZE_DEVICE_FP_FLAG_FORCE_UINT32 = 0x7fffffff
+} ze_device_fp_flag_t;
+
+/* Device module properties */
+typedef struct _ze_device_module_properties_t {
+  ze_structure_type_t stype;
+  void *pNext;
+  uint32_t spirvVersionSupported;
+  ze_device_module_flags_t flags;
+  ze_device_fp_flags_t fp16flags;
+  ze_device_fp_flags_t fp32flags;
+  ze_device_fp_flags_t fp64flags;
+  uint32_t maxArgumentsSize;
+  uint32_t printfBufferSize;
+  ze_native_kernel_uuid_t nativeKernelSupported;
+} ze_device_module_properties_t;
+
 /* Device IP version (extension) */
 typedef struct _ze_device_ip_version_ext_t {
   ze_structure_type_t stype;
@@ -612,6 +660,9 @@ ZE_APIEXPORT ze_result_t ZE_APICALL zeDeviceGetComputeProperties(
     ze_device_handle_t hDevice,
     ze_device_compute_properties_t *pComputeProperties);
 ZE_APIEXPORT ze_result_t ZE_APICALL
+zeDeviceGetModuleProperties(ze_device_handle_t hDevice,
+                            ze_device_module_properties_t *pModuleProperties);
+ZE_APIEXPORT ze_result_t ZE_APICALL
 zeDeviceGetMemoryProperties(ze_device_handle_t hDevice, uint32_t *pCount,
                             ze_device_memory_properties_t *pMemProperties);
 ZE_APIEXPORT ze_result_t ZE_APICALL
diff --git a/offload/plugins-nextgen/level_zero/include/L0Device.h b/offload/plugins-nextgen/level_zero/include/L0Device.h
index 8c83d14f8d1b0..1ca62145f536e 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Device.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Device.h
@@ -188,6 +188,7 @@ class L0DeviceTy final : public GenericDeviceTy {
   ze_device_compute_properties_t ComputeProperties{};
   ze_device_memory_properties_t MemoryProperties{};
   ze_device_cache_properties_t CacheProperties{};
+  ze_device_module_properties_t ModuleProperties{};
 
   /// Devices' default target allocation kind for internal allocation.
   int32_t AllocKind = TARGET_ALLOC_DEVICE;
@@ -257,6 +258,8 @@ class L0DeviceTy final : public GenericDeviceTy {
     MemoryProperties.pNext = nullptr;
     CacheProperties.stype = ZE_STRUCTURE_TYPE_DEVICE_CACHE_PROPERTIES;
     CacheProperties.pNext = nullptr;
+    ModuleProperties.stype = ZE_STRUCTURE_TYPE_DEVICE_MODULE_PROPERTIES;
+    ModuleProperties.pNext = nullptr;
   }
 
   static L0DeviceTy &makeL0Device(GenericDeviceTy &Device) {
@@ -385,6 +388,26 @@ class L0DeviceTy final : public GenericDeviceTy {
     return DeviceProperties.maxMemAllocSize;
   }
 
+  bool supportsFP64() const {
+    return ModuleProperties.flags & ZE_DEVICE_MODULE_FLAG_FP64;
+  }
+
+  bool supportsFP16() const {
+    return ModuleProperties.flags & ZE_DEVICE_MODULE_FLAG_FP16;
+  }
+
+  ze_device_fp_flags_t getFP64Flags() const {
+    return ModuleProperties.fp64flags;
+  }
+
+  ze_device_fp_flags_t getFP16Flags() const {
+    return ModuleProperties.fp16flags;
+  }
+
+  ze_device_fp_flags_t getFP32Flags() const {
+    return ModuleProperties.fp32flags;
+  }
+
   int32_t getAllocKind() const { return AllocKind; }
   DeviceArchTy getDeviceArch() const { return DeviceArch; }
   bool isDeviceArch(DeviceArchTy Arch) const { return DeviceArch == Arch; }
diff --git a/offload/plugins-nextgen/level_zero/src/L0Device.cpp b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
index 461f12407680f..3a7334ec45066 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Device.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
@@ -18,6 +18,7 @@
 #include "L0Trace.h"
 
 #include "GlobalHandler.h"
+#include "OffloadAPI.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/Object/ELF.h"
 
@@ -195,6 +196,7 @@ Error L0DeviceTy::initImpl(GenericPluginTy &Plugin) {
                     &MemoryProperties);
   CALL_ZE_RET_ERROR(zeDeviceGetCacheProperties, zeDevice, &Count,
                     &CacheProperties);
+  CALL_ZE_RET_ERROR(zeDeviceGetModuleProperties, zeDevice, &ModuleProperties);
 
   DeviceName = std::string(DeviceProperties.name);
 
@@ -639,6 +641,74 @@ Expected<InfoTreeNode> L0DeviceTy::obtainInfoImpl() {
            DeviceInfo::MEMORY_CLOCK_RATE);
   Info.add("Memory Address Size", uint64_t{64u}, "bits",
            DeviceInfo::ADDRESS_BITS);
+
+  // FP64 (Double precision).
+  Info.add("Double FP Support", supportsFP64(), "",
+           DeviceInfo::DOUBLE_FP_SUPPORT);
+  ol_device_fp_capability_flags_t DoubleFPCapabilities = 0;
+  ze_device_fp_flags_t ZeDoubleFPFlags = getFP64Flags();
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_DENORM)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_DENORM;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_INF_NAN)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_NEAREST)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_ZERO)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_INF)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_FMA)
+    DoubleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+  if (ZeDoubleFPFlags & ZE_DEVICE_FP_FLAG_ROUNDED_DIVIDE_SQRT)
+    DoubleFPCapabilities |=
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT;
+  Info.add("Double FP Capabilities", DoubleFPCapabilities, "",
+           DeviceInfo::DOUBLE_FP_CONFIG);
+
+  // FP16 (Half precision).
+  Info.add("Half FP Support", supportsFP16(), "", DeviceInfo::HALF_FP_SUPPORT);
+  ol_device_fp_capability_flags_t HalfFPCapabilities = 0;
+  ze_device_fp_flags_t ZeHalfFPFlags = getFP16Flags();
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_DENORM)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_DENORM;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_INF_NAN)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_NEAREST)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_ZERO)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_INF)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_FMA)
+    HalfFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+  if (ZeHalfFPFlags & ZE_DEVICE_FP_FLAG_ROUNDED_DIVIDE_SQRT)
+    HalfFPCapabilities |=
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT;
+  Info.add("Half FP Capabilities", HalfFPCapabilities, "",
+           DeviceInfo::HALF_FP_CONFIG);
+
+  // FP32 (Single FP).
+  Info.add("Single FP Support", true, "", DeviceInfo::SINGLE_FP_SUPPORT);
+  ol_device_fp_capability_flags_t SingleFPCapabilities = 0;
+  ze_device_fp_flags_t ZeSingleFPFlags = getFP32Flags();
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_DENORM)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_DENORM;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_INF_NAN)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_INF_NAN;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_NEAREST)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_NEAREST;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_ZERO)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_ZERO;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_ROUND_TO_INF)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_ROUND_TO_INF;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_FMA)
+    SingleFPCapabilities |= OL_DEVICE_FP_CAPABILITY_FLAG_FMA;
+  if (ZeSingleFPFlags & ZE_DEVICE_FP_FLAG_ROUNDED_DIVIDE_SQRT)
+    SingleFPCapabilities |=
+        OL_DEVICE_FP_CAPABILITY_FLAG_CORRECTLY_ROUNDED_DIVIDE_SQRT;
+  Info.add("Single FP Capabilities", SingleFPCapabilities, "",
+           DeviceInfo::SINGLE_FP_CONFIG);
+
   return Info;
 }
 
diff --git a/offload/tools/deviceinfo/llvm-offload-device-info.cpp b/offload/tools/deviceinfo/llvm-offload-device-info.cpp
index 936d082695b47..ab2b3c5706f4b 100644
--- a/offload/tools/deviceinfo/llvm-offload-device-info.cpp
+++ b/offload/tools/deviceinfo/llvm-offload-device-info.cpp
@@ -211,14 +211,22 @@ ol_result_t printDevice(std::ostream &S, ol_device_handle_t D) {
   OFFLOAD_ERR(
       printDeviceValue<uint64_t>(S, D, OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE,
                                  "Work Group Shared Mem Size", "B"));
+  OFFLOAD_ERR(
+      printDeviceValue<bool>(S, D, OL_DEVICE_INFO_SINGLE_FP_SUPPORT,
+                             "Single Precision Floating Point Support"));
   OFFLOAD_ERR(
       (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(
           S, D, OL_DEVICE_INFO_SINGLE_FP_CONFIG,
           "Single Precision Floating Point Capability")));
+  OFFLOAD_ERR(
+      printDeviceValue<bool>(S, D, OL_DEVICE_INFO_DOUBLE_FP_SUPPORT,
+                             "Double Precision Floating Point Support"));
   OFFLOAD_ERR(
       (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(
           S, D, OL_DEVICE_INFO_DOUBLE_FP_CONFIG,
           "Double Precision Floating Point Capability")));
+  OFFLOAD_ERR(printDeviceValue<bool>(S, D, OL_DEVICE_INFO_HALF_FP_SUPPORT,
+                                     "Half Precision Floating Point Support"));
   OFFLOAD_ERR(
       (printDeviceValue<ol_device_fp_capability_flags_t, PrintKind::FP_FLAGS>(
           S, D, OL_DEVICE_INFO_HALF_FP_CONFIG,
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
index ba29fb153682d..f2ea60cffdf12 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
@@ -201,6 +201,12 @@ OL_DEVICE_INFO_TEST_VALUE_GT(NativeVectorWidthFloat, uint32_t,
                              OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT, 0);
 OL_DEVICE_INFO_TEST_VALUE_GT(NativeVectorWidthDouble, uint32_t,
                              OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE, 0);
+OL_DEVICE_INFO_TEST_SUCCESS(SingleFPSupport, bool,
+                            OL_DEVICE_INFO_SINGLE_FP_SUPPORT);
+OL_DEVICE_INFO_TEST_SUCCESS(DoubleFPSupport, bool,
+                            OL_DEVICE_INFO_DOUBLE_FP_SUPPORT);
+OL_DEVICE_INFO_TEST_SUCCESS(HalfFPSupport, bool,
+                            OL_DEVICE_INFO_HALF_FP_SUPPORT);
 OL_DEVICE_INFO_TEST_SUCCESS(NativeVectorWidthHalf, uint32_t,
                             OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF);
 OL_DEVICE_INFO_TEST_VALUE_GT(MaxClockFrequency, uint32_t,



More information about the llvm-commits mailing list