[llvm] [offload][AMDGPU] Add HSA AMD extension version checks (PR #228569)
Robert Imschweiler via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 01:14:00 PDT 2026
https://github.com/ro-i updated https://github.com/llvm/llvm-project/pull/228569
>From 8673f8d8827cb895b0b39cb2c3dcb992591b3f7b Mon Sep 17 00:00:00 2001
From: Robert Imschweiler <robert.imschweiler at amd.com>
Date: Sat, 3 Oct 2026 02:47:31 -0500
Subject: [PATCH] [offload][AMDGPU] Add dynamic HSA version and symbol checks
---
.../amdgpu/dynamic_hsa/hsa.cpp | 41 ++++++++++++++++++-
.../plugins-nextgen/amdgpu/dynamic_hsa/hsa.h | 2 +
offload/plugins-nextgen/amdgpu/src/rtl.cpp | 15 +++++++
3 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp
index 13bd2fd064002b..724a5711a6be5e 100644
--- a/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp
+++ b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.cpp
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
#include "Shared/Debug.h"
@@ -19,6 +21,7 @@
#include "hsa.h"
#include "hsa_ext_amd.h"
#include <memory>
+#include <utility>
using namespace llvm::offload::debug;
@@ -96,14 +99,48 @@ DLWRAP_FINALIZE()
#define DEBUG_PREFIX "Target " GETNAME(TARGET_NAME) " RTL"
#endif
+/// Stand-in for an optional function that the HSA runtime does not provide.
+template <typename FuncTy> struct UnavailableTy;
+template <typename... ArgsTy>
+struct UnavailableTy<hsa_status_t (*)(ArgsTy...)> {
+ static hsa_status_t call(ArgsTy...) { return HSA_STATUS_ERROR; }
+};
+
+#define OPTIONAL_SYMBOL(SYMBOL) \
+ {#SYMBOL, reinterpret_cast<void *>(&UnavailableTy<decltype(&SYMBOL)>::call)}
+
+/// The functions that are newer than version 1.0 of the AMD extension. If the
+/// runtime lacks one, calls to it fail instead of preventing the plugin from
+/// loading.
+static const std::pair<llvm::StringRef, void *> OptionalSymbols[] = {
+ OPTIONAL_SYMBOL(hsa_amd_vmem_address_reserve),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_address_free),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_handle_create),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_handle_release),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_map),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_unmap),
+ OPTIONAL_SYMBOL(hsa_amd_vmem_set_access),
+};
+
+#undef OPTIONAL_SYMBOL
+
static bool resolveSymbols(llvm::sys::DynamicLibrary &Lib, const char *Name) {
for (size_t I = 0; I < dlwrap::size(); I++) {
const char *Sym = dlwrap::symbol(I);
void *P = Lib.getAddressOfSymbol(Sym);
if (P == nullptr) {
- ODBG(OLDT_Init) << "Unable to find '" << Sym << "' in '" << Name << "'!";
- return false;
+ const auto *It = llvm::find_if(
+ OptionalSymbols, [&](const auto &S) { return S.first == Sym; });
+ if (It == std::end(OptionalSymbols)) {
+ ODBG(OLDT_Init) << "Unable to find '" << Sym << "' in '" << Name
+ << "'!";
+ return false;
+ }
+ ODBG(OLDT_Init) << "Optional '" << Sym << "' is unavailable in '" << Name
+ << "'";
+ *dlwrap::pointer(I) = It->second;
+ continue;
}
ODBG(OLDT_Init) << "Implementing " << Sym << " with dlsym(" << Sym
<< ") -> " << P;
diff --git a/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h
index f66326a7f240e4..c303902ca3da7f 100644
--- a/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h
+++ b/offload/plugins-nextgen/amdgpu/dynamic_hsa/hsa.h
@@ -123,6 +123,8 @@ typedef enum {
HSA_SYSTEM_INFO_VERSION_MINOR = 1,
HSA_SYSTEM_INFO_TIMESTAMP = 2,
HSA_SYSTEM_INFO_TIMESTAMP_FREQUENCY = 3,
+ HSA_AMD_SYSTEM_INFO_EXT_VERSION_MAJOR = 0x207,
+ HSA_AMD_SYSTEM_INFO_EXT_VERSION_MINOR = 0x208,
} hsa_system_info_t;
typedef enum {
diff --git a/offload/plugins-nextgen/amdgpu/src/rtl.cpp b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
index de38c2a68e4ab4..5b52849af75da1 100644
--- a/offload/plugins-nextgen/amdgpu/src/rtl.cpp
+++ b/offload/plugins-nextgen/amdgpu/src/rtl.cpp
@@ -48,6 +48,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
@@ -232,6 +233,18 @@ static Error getTargetTripleAndFeatures(hsa_agent_t Agent,
});
return Err;
}
+
+/// Get the version of the AMD extension that the HSA runtime implements, if the
+/// runtime reports it.
+static std::optional<llvm::VersionTuple> getAMDExtensionVersion() {
+ uint16_t Major, Minor;
+ if (hsa_system_get_info(HSA_AMD_SYSTEM_INFO_EXT_VERSION_MAJOR, &Major) !=
+ HSA_STATUS_SUCCESS ||
+ hsa_system_get_info(HSA_AMD_SYSTEM_INFO_EXT_VERSION_MINOR, &Minor) !=
+ HSA_STATUS_SUCCESS)
+ return std::nullopt;
+ return llvm::VersionTuple(Major, Minor);
+}
} // namespace hsa_utils
/// Utility class representing generic resource references to AMDGPU resources.
@@ -3241,6 +3254,8 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy {
Info.add("HSA Runtime Version",
std::to_string(Major) + "." + std::to_string(Minor), "",
DeviceInfo::DRIVER_VERSION);
+ if (auto Version = hsa_utils::getAMDExtensionVersion())
+ Info.add("HSA AMD Extension Version", Version->getAsString());
Info.add("HSA OpenMP Device Number", DeviceId);
More information about the llvm-commits
mailing list