[llvm] [Offload] Add type information to device info nodes (PR #144535)
Ross Brunton via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 20 06:41:31 PDT 2025
https://github.com/RossBrunton updated https://github.com/llvm/llvm-project/pull/144535
>From b8cb3802aac2dac1bb269373dd94ff72f927310b Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Tue, 17 Jun 2025 15:37:12 +0100
Subject: [PATCH 1/2] [Offload] Add type information to device info nodes
Rather than being "stringly typed", store values as a std::variant that
can hold various types. This means that liboffload doesn't have to do
any string parsing for integer/bool device info keys.
---
offload/liboffload/src/OffloadImpl.cpp | 18 ++++----
.../common/include/PluginInterface.h | 42 +++++++++++++------
2 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index f02497c0a6331..59c84abca8ac9 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -245,23 +245,23 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
ReturnHelper ReturnValue(PropSize, PropValue, PropSizeRet);
// Find the info if it exists under any of the given names
- auto GetInfo = [&](std::vector<std::string> Names) {
+ auto GetInfoString = [&](std::vector<std::string> Names) {
if (Device == OffloadContext::get().HostDevice())
- return std::string("Host");
+ return "Host";
if (!Device->Device)
- return std::string("");
+ return "";
auto Info = Device->Device->obtainInfoImpl();
if (auto Err = Info.takeError())
- return std::string("");
+ return "";
for (auto Name : Names) {
if (auto Entry = Info->get(Name))
- return (*Entry)->Value;
+ return std::get<std::string>((*Entry)->Value).c_str();
}
- return std::string("");
+ return "";
};
switch (PropName) {
@@ -272,12 +272,12 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
? ReturnValue(OL_DEVICE_TYPE_HOST)
: ReturnValue(OL_DEVICE_TYPE_GPU);
case OL_DEVICE_INFO_NAME:
- return ReturnValue(GetInfo({"Device Name"}).c_str());
+ return ReturnValue(GetInfoString({"Device Name"}));
case OL_DEVICE_INFO_VENDOR:
- return ReturnValue(GetInfo({"Vendor Name"}).c_str());
+ return ReturnValue(GetInfoString({"Vendor Name"}));
case OL_DEVICE_INFO_DRIVER_VERSION:
return ReturnValue(
- GetInfo({"CUDA Driver Version", "HSA Runtime Version"}).c_str());
+ GetInfoString({"CUDA Driver Version", "HSA Runtime Version"}));
default:
return createOffloadError(ErrorCode::INVALID_ENUMERATION,
"getDeviceInfo enum '%i' is invalid", PropName);
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index f5d995532b7a5..d76c415ce4cdd 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -17,6 +17,7 @@
#include <list>
#include <map>
#include <shared_mutex>
+#include <variant>
#include <vector>
#include "ExclusiveAccess.h"
@@ -122,7 +123,9 @@ struct InfoTreeNode {
static constexpr uint64_t IndentSize = 4;
std::string Key;
- std::string Value;
+ struct None {};
+ using VariantType = std::variant<uint64_t, std::string, bool, None>;
+ VariantType Value;
std::string Units;
// Need to specify a default value number of elements here as `InfoTreeNode`'s
// size is unknown. This is a vector (rather than a Key->Value map) since:
@@ -131,15 +134,15 @@ struct InfoTreeNode {
// * The same key can appear multiple times
std::unique_ptr<llvm::SmallVector<InfoTreeNode, 8>> Children;
- InfoTreeNode() : InfoTreeNode("", "", "") {}
- InfoTreeNode(std::string Key, std::string Value, std::string Units)
+ InfoTreeNode() : InfoTreeNode("", None{}, "") {}
+ InfoTreeNode(std::string Key, VariantType Value, std::string Units)
: Key(Key), Value(Value), Units(Units) {}
/// Add a new info entry as a child of this node. The entry requires at least
/// a key string in \p Key. The value in \p Value is optional and can be any
/// type that is representable as a string. The units in \p Units is optional
/// and must be a string.
- template <typename T = std::string>
+ template <typename T = None>
InfoTreeNode *add(std::string Key, T Value = T(),
const std::string &Units = std::string()) {
assert(!Key.empty() && "Invalid info key");
@@ -147,15 +150,15 @@ struct InfoTreeNode {
if (!Children)
Children = std::make_unique<llvm::SmallVector<InfoTreeNode, 8>>();
- std::string ValueStr;
- if constexpr (std::is_same_v<T, bool>)
- ValueStr = Value ? "Yes" : "No";
+ VariantType ValueVariant;
+ if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, None>)
+ ValueVariant = Value;
else if constexpr (std::is_arithmetic_v<T>)
- ValueStr = std::to_string(Value);
+ ValueVariant = static_cast<uint64_t>(Value);
else
- ValueStr = Value;
+ ValueVariant = std::string{Value};
- return &Children->emplace_back(Key, ValueStr, Units);
+ return &Children->emplace_back(Key, ValueVariant, Units);
}
std::optional<InfoTreeNode *> get(StringRef Key) {
@@ -184,8 +187,23 @@ struct InfoTreeNode {
MaxKeySize - (Key.size() + KeyIndentSize) + IndentSize;
llvm::outs() << std::string(KeyIndentSize, ' ') << Key
- << std::string(ValIndentSize, ' ') << Value
- << (Units.empty() ? "" : " ") << Units << "\n";
+ << std::string(ValIndentSize, ' ');
+ std::visit(
+ [](auto &&V) {
+ using T = std::decay_t<decltype(V)>;
+ if constexpr (std::is_same_v<T, std::string>)
+ llvm::outs() << V;
+ else if constexpr (std::is_same_v<T, bool>)
+ llvm::outs() << (V ? "Yes" : "No");
+ else if constexpr (std::is_same_v<T, uint64_t>)
+ llvm::outs() << V;
+ else if constexpr (std::is_same_v<T, None>) {
+ // Do nothing
+ } else
+ static_assert(false, "doPrint visit not exhaustive");
+ },
+ Value);
+ llvm::outs() << (Units.empty() ? "" : " ") << Units << "\n";
}
// Print children
>From 7f43a2889cb4abcc7bfa029f6cf4ff3250fe93d5 Mon Sep 17 00:00:00 2001
From: Ross Brunton <ross at codeplay.com>
Date: Fri, 20 Jun 2025 14:39:49 +0100
Subject: [PATCH 2/2] Use std::monostate
---
.../plugins-nextgen/common/include/PluginInterface.h | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index d76c415ce4cdd..91df800304378 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -123,8 +123,7 @@ struct InfoTreeNode {
static constexpr uint64_t IndentSize = 4;
std::string Key;
- struct None {};
- using VariantType = std::variant<uint64_t, std::string, bool, None>;
+ using VariantType = std::variant<uint64_t, std::string, bool, std::monostate>;
VariantType Value;
std::string Units;
// Need to specify a default value number of elements here as `InfoTreeNode`'s
@@ -134,7 +133,7 @@ struct InfoTreeNode {
// * The same key can appear multiple times
std::unique_ptr<llvm::SmallVector<InfoTreeNode, 8>> Children;
- InfoTreeNode() : InfoTreeNode("", None{}, "") {}
+ InfoTreeNode() : InfoTreeNode("", std::monostate{}, "") {}
InfoTreeNode(std::string Key, VariantType Value, std::string Units)
: Key(Key), Value(Value), Units(Units) {}
@@ -142,7 +141,7 @@ struct InfoTreeNode {
/// a key string in \p Key. The value in \p Value is optional and can be any
/// type that is representable as a string. The units in \p Units is optional
/// and must be a string.
- template <typename T = None>
+ template <typename T = std::monostate>
InfoTreeNode *add(std::string Key, T Value = T(),
const std::string &Units = std::string()) {
assert(!Key.empty() && "Invalid info key");
@@ -151,7 +150,7 @@ struct InfoTreeNode {
Children = std::make_unique<llvm::SmallVector<InfoTreeNode, 8>>();
VariantType ValueVariant;
- if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, None>)
+ if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, std::monostate>)
ValueVariant = Value;
else if constexpr (std::is_arithmetic_v<T>)
ValueVariant = static_cast<uint64_t>(Value);
@@ -197,7 +196,7 @@ struct InfoTreeNode {
llvm::outs() << (V ? "Yes" : "No");
else if constexpr (std::is_same_v<T, uint64_t>)
llvm::outs() << V;
- else if constexpr (std::is_same_v<T, None>) {
+ else if constexpr (std::is_same_v<T, std::monostate>) {
// Do nothing
} else
static_assert(false, "doPrint visit not exhaustive");
More information about the llvm-commits
mailing list