Skip to content

Commit 8819e99

Browse files
committed
Fix amdgpu-arch for dll name on Windows
Recently HIP runtime changed dll name to amdhip64_n.dll on Windows, where n is ROCm major version number. Fix amdgpu-arch to search for amdhip64_n.dll on Windows.
1 parent b5a7d3b commit 8819e99

File tree

2 files changed

+111
-4
lines changed

2 files changed

+111
-4
lines changed

clang/tools/amdgpu-arch/AMDGPUArch.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
2121
// Mark all our options with this category.
2222
static cl::OptionCategory AMDGPUArchCategory("amdgpu-arch options");
2323

24+
cl::opt<bool> Verbose("verbose", cl::desc("Enable verbose output"),
25+
cl::init(false), cl::cat(AMDGPUArchCategory));
26+
2427
static void PrintVersion(raw_ostream &OS) {
2528
OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n';
2629
}

clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,21 @@
1111
//
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "llvm/Support/CommandLine.h"
1415
#include "llvm/Support/DynamicLibrary.h"
1516
#include "llvm/Support/Error.h"
17+
#include "llvm/Support/FileSystem.h"
18+
#include "llvm/Support/Path.h"
19+
#include "llvm/Support/Process.h"
20+
#include "llvm/Support/Program.h"
1621
#include "llvm/Support/raw_ostream.h"
22+
#include <algorithm>
23+
#include <string>
24+
#include <vector>
25+
26+
#ifdef _WIN32
27+
#include <windows.h>
28+
#endif
1729

1830
using namespace llvm;
1931

@@ -31,16 +43,108 @@ typedef hipError_t (*hipGetDeviceCount_t)(int *);
3143
typedef hipError_t (*hipDeviceGet_t)(int *, int);
3244
typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int);
3345

34-
int printGPUsByHIP() {
46+
extern cl::opt<bool> Verbose;
47+
3548
#ifdef _WIN32
36-
constexpr const char *DynamicHIPPath = "amdhip64.dll";
49+
std::vector<std::string> getSearchPaths() {
50+
std::vector<std::string> Paths;
51+
52+
// Get the directory of the current executable
53+
if (auto MainExe = sys::fs::getMainExecutable(nullptr, nullptr);
54+
!MainExe.empty())
55+
Paths.push_back(sys::path::parent_path(MainExe).str());
56+
57+
// Get the system directory
58+
char SystemDirectory[MAX_PATH];
59+
if (GetSystemDirectoryA(SystemDirectory, MAX_PATH) > 0) {
60+
Paths.push_back(SystemDirectory);
61+
}
62+
63+
// Get the Windows directory
64+
char WindowsDirectory[MAX_PATH];
65+
if (GetWindowsDirectoryA(WindowsDirectory, MAX_PATH) > 0) {
66+
Paths.push_back(WindowsDirectory);
67+
}
68+
69+
// Get the current working directory
70+
SmallVector<char, 256> CWD;
71+
if (sys::fs::current_path(CWD))
72+
Paths.push_back(std::string(CWD.begin(), CWD.end()));
73+
74+
// Get the PATH environment variable
75+
if (auto PathEnv = llvm::sys::Process::GetEnv("PATH")) {
76+
SmallVector<StringRef, 16> PathList;
77+
StringRef(*PathEnv).split(PathList, sys::EnvPathSeparator);
78+
for (auto &Path : PathList)
79+
Paths.push_back(Path.str());
80+
}
81+
82+
return Paths;
83+
}
84+
85+
// Custom comparison function for dll name
86+
bool compareVersions(const std::string &a, const std::string &b) {
87+
// Extract version numbers
88+
int versionA = std::stoi(a.substr(a.find_last_of('_') + 1));
89+
int versionB = std::stoi(b.substr(b.find_last_of('_') + 1));
90+
return versionA > versionB;
91+
}
92+
93+
#endif
94+
95+
// On Windows, prefer amdhip64_n.dll where n is ROCm major version and greater
96+
// value of n takes precedence. If amdhip64_n.dll is not found, fall back to
97+
// amdhip64.dll. The reason is that a normal driver installation only has
98+
// amdhip64_n.dll but we do not know what n is since this progrm may be used
99+
// with a future version of HIP runtime.
100+
//
101+
// On Linux, always use default libamdhip64.so.
102+
std::pair<std::string, bool> findNewestHIPDLL() {
103+
#ifdef _WIN32
104+
const char *HipDLLPrefix = "amdhip64_";
105+
const char *HipDLLSuffix = ".dll";
106+
107+
std::vector<std::string> SearchPaths = getSearchPaths();
108+
std::vector<std::string> DLLNames;
109+
110+
for (const auto &Dir : SearchPaths) {
111+
std::error_code EC;
112+
for (sys::fs::directory_iterator DirIt(Dir, EC), DirEnd;
113+
DirIt != DirEnd && !EC; DirIt.increment(EC)) {
114+
StringRef Filename = sys::path::filename(DirIt->path());
115+
if (Filename.starts_with(HipDLLPrefix) &&
116+
Filename.ends_with(HipDLLSuffix))
117+
DLLNames.push_back(sys::path::convert_to_slash(DirIt->path()));
118+
}
119+
if (!DLLNames.empty())
120+
break;
121+
}
122+
123+
if (DLLNames.empty())
124+
return {"amdhip64.dll", true};
125+
126+
std::sort(DLLNames.begin(), DLLNames.end(), compareVersions);
127+
return {DLLNames[0], false};
37128
#else
38-
constexpr const char *DynamicHIPPath = "libamdhip64.so";
129+
// On Linux, fallback to default shared object
130+
return {"libamdhip64.so", true};
39131
#endif
132+
}
133+
134+
int printGPUsByHIP() {
135+
auto [DynamicHIPPath, IsFallback] = findNewestHIPDLL();
136+
137+
if (Verbose) {
138+
if (IsFallback)
139+
outs() << "Using default HIP runtime: " << DynamicHIPPath << "\n";
140+
else
141+
outs() << "Found HIP runtime: " << DynamicHIPPath << "\n";
142+
}
40143

41144
std::string ErrMsg;
42145
auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
43-
llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath, &ErrMsg));
146+
llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath.c_str(),
147+
&ErrMsg));
44148
if (!DynlibHandle->isValid()) {
45149
llvm::errs() << "Failed to load " << DynamicHIPPath << ": " << ErrMsg
46150
<< '\n';

0 commit comments

Comments
 (0)