[clang] cb9d4cd - [offload-arch] Report gfx1250-strict to match rocminfo (#224480)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 18 08:10:01 PDT 2026
Author: A. Cauble
Date: 2026-09-18T10:09:54-05:00
New Revision: cb9d4cdf5e415d17aaa54a094939249c15871d2d
URL: https://github.com/llvm/llvm-project/commit/cb9d4cdf5e415d17aaa54a094939249c15871d2d
DIFF: https://github.com/llvm/llvm-project/commit/cb9d4cdf5e415d17aaa54a094939249c15871d2d.diff
LOG: [offload-arch] Report gfx1250-strict to match rocminfo (#224480)
## Motivation
offload-arch would print gfx1250, but rocminfo reports gfx1250-strict on
revision 0s. We want to print the gfx1250-strict too.
Note: This is based off a [similar PR in
rocm-systems](https://github.com/ROCm/rocm-systems/pull/11639).
## Required Changes
* llvm already can parse the gfx1250 -strict target, so no changes
necessary there.
* offload-arch already printed gfx1250, so just needed to get the ASIC
Revision, which is in bits 25:22 in the capability property.
* If ASIC Revision is 0 and gfx_target_version is gfx1250, then report
"gfx1250-strict"
## Testing
* Tested this on a gfx1250-strict and offload-arch reports correctly.
* Added two unit tests to check for "gfx1250" v "gfx1250-strict"
depending on ASIC revision and guard against accidental parsing of
"capability2"
Added:
Modified:
clang/tools/offload-arch/AMDGPUArchByKFD.cpp
clang/unittests/offload-arch/OffloadArchTest.cpp
Removed:
################################################################################
diff --git a/clang/tools/offload-arch/AMDGPUArchByKFD.cpp b/clang/tools/offload-arch/AMDGPUArchByKFD.cpp
index 8e4284eb5f8de..5720c5a0958b4 100644
--- a/clang/tools/offload-arch/AMDGPUArchByKFD.cpp
+++ b/clang/tools/offload-arch/AMDGPUArchByKFD.cpp
@@ -19,11 +19,13 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
+#include <tuple>
using namespace llvm;
constexpr static const char *KFD_SYSFS_NODE_PATH =
"/sys/devices/virtual/kfd/kfd/topology/nodes";
+constexpr static long GFX1250_VERSION = 120500;
// See the ROCm implementation for how this is handled.
// https://github.com/ROCm/ROCT-Thunk-Interface/blob/master/src/libhsakmt.h#L126
@@ -31,9 +33,20 @@ constexpr static long getMajor(long Ver) { return (Ver / 10000) % 100; }
constexpr static long getMinor(long Ver) { return (Ver / 100) % 100; }
constexpr static long getStep(long Ver) { return Ver % 100; }
+// For A0, print gfx1250-strict to match rocminfo
+static StringRef getRevisionSuffix(long GFXVersion, long ASICRevision) {
+ return (GFXVersion == GFX1250_VERSION && ASICRevision == 0) ? "-strict" : "";
+}
+
// Exposed for testing
int printGPUsByKFD(StringRef NodePath) {
- SmallVector<std::pair<long, long>> Devices;
+ struct KFDNode {
+ long Node;
+ long GFXVersion;
+ long ASICRevision;
+ };
+
+ SmallVector<KFDNode> Devices;
std::error_code EC;
sys::fs::directory_iterator Begin(NodePath, EC), End;
@@ -58,6 +71,7 @@ int printGPUsByKFD(StringRef NodePath) {
return 1;
long GFXVersion = 0;
+ uint64_t Capability = 0;
for (line_iterator Lines(**BufferOrErr, false); !Lines.is_at_end();
++Lines) {
StringRef Line(*Lines);
@@ -65,21 +79,29 @@ int printGPUsByKFD(StringRef NodePath) {
if (Line.drop_while([](char C) { return std::isspace(C); })
.consumeInteger(10, GFXVersion))
return 1;
- break;
+ // Differentiate between capability and capability2
+ } else if (Line.consume_front("capability") && !Line.starts_with('2')) {
+ if (Line.drop_while([](char C) { return std::isspace(C); })
+ .consumeInteger(10, Capability))
+ return 1;
}
}
// If this is zero the node is a CPU.
if (GFXVersion == 0)
continue;
- Devices.emplace_back(Node, GFXVersion);
+ // ASIC revision is bits 25:22 in capability
+ long ASICRevision = (Capability >> 22) & 0xf;
+ Devices.push_back({Node, GFXVersion, ASICRevision});
}
// Sort the devices by their node to make sure it prints in order.
- llvm::sort(Devices, [](auto &L, auto &R) { return L.first < R.first; });
- for (const auto &[Node, GFXVersion] : Devices)
+ llvm::sort(Devices, [](auto &L, auto &R) { return L.Node < R.Node; });
+ for (const auto &[Node, GFXVersion, ASICRevision] : Devices) {
outs() << "gfx" << getMajor(GFXVersion) << getMinor(GFXVersion)
- << format_hex_no_prefix(getStep(GFXVersion), 1) << '\n';
+ << format_hex_no_prefix(getStep(GFXVersion), 1)
+ << getRevisionSuffix(GFXVersion, ASICRevision) << '\n';
+ }
return 0;
}
diff --git a/clang/unittests/offload-arch/OffloadArchTest.cpp b/clang/unittests/offload-arch/OffloadArchTest.cpp
index 5f5e49f5c72cc..8132a6ca10847 100644
--- a/clang/unittests/offload-arch/OffloadArchTest.cpp
+++ b/clang/unittests/offload-arch/OffloadArchTest.cpp
@@ -142,6 +142,19 @@ void addGPUNode(StringRef Dir, unsigned Node, StringRef GFXVersion) {
addNode(Dir, Node, ("gfx_target_version " + GFXVersion + "\n").str());
}
+// Write a node describing a GPU with the given gfx_target_version and
+// capabilities. Write capability2 before and after to catch accidental
+// reads of something other than "capability"
+void addGPUNodeWithCapability(StringRef Dir, unsigned Node,
+ StringRef GFXVersion, uint64_t Capability,
+ uint64_t Capability2) {
+ addNode(Dir, Node,
+ ("gfx_target_version " + GFXVersion + "\n" + "capability2 " +
+ Twine(Capability2) + "\n" + "capability " + Twine(Capability) +
+ "\n" + "capability2 " + Twine(Capability2) + "\n")
+ .str());
+}
+
// Run printGPUsByKFD, collecting what it writes to stdout.
int printGPUsByKFDCapturingStdout(StringRef NodePath, std::string &Output) {
testing::internal::CaptureStdout();
@@ -207,3 +220,25 @@ TEST(KFDTopology, MultipleGPUsArePrintedInNodeOrder) {
EXPECT_EQ(printGPUsByKFDCapturingStdout(Dir.path(), Output), 0);
EXPECT_EQ(Output, "gfx1101\ngfx90a\n");
}
+
+// Make sure that A0 of gfx1250 is printed as gfx1250-strict. Happens when
+// ASIC revision is 0. Also tests to make sure other properties that look like
+// capability (like capability2) are not read instead.
+TEST(KFDTopology, GFX1250A0IsPrintedAsStrict) {
+ unittest::TempDir Dir("kfd-topology", /*Unique=*/true);
+ addGPUNodeWithCapability(Dir.path(), 0, "120500", /*Capability=*/0xF837A280,
+ /*Capability2=*/0xFFFFFFFF);
+ std::string Output;
+ EXPECT_EQ(printGPUsByKFDCapturingStdout(Dir.path(), Output), 0);
+ EXPECT_EQ(Output, "gfx1250-strict\n");
+}
+
+// Make sure any other version of gfx1250 is printed as gfx1250.
+TEST(KFDTopology, GFX1250NonA0IsPrintedPlain) {
+ unittest::TempDir Dir("kfd-topology", /*Unique=*/true);
+ addGPUNodeWithCapability(Dir.path(), 0, "120500", /*Capability=*/0xF877A280,
+ /*Capability2=*/0x00000000);
+ std::string Output;
+ EXPECT_EQ(printGPUsByKFDCapturingStdout(Dir.path(), Output), 0);
+ EXPECT_EQ(Output, "gfx1250\n");
+}
More information about the cfe-commits
mailing list