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"); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
