https://github.com/yxsamliu created https://github.com/llvm/llvm-project/pull/101350
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. >From 8819e99b64f3293a758f8a81258a25c91fab6ef6 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" <yaxun....@amd.com> Date: Wed, 31 Jul 2024 09:23:05 -0400 Subject: [PATCH] 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. --- clang/tools/amdgpu-arch/AMDGPUArch.cpp | 3 + clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp | 112 +++++++++++++++++++- 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/clang/tools/amdgpu-arch/AMDGPUArch.cpp b/clang/tools/amdgpu-arch/AMDGPUArch.cpp index 7ae57b7877e1f..fefd4f08d5ed2 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArch.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArch.cpp @@ -21,6 +21,9 @@ static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); // Mark all our options with this category. static cl::OptionCategory AMDGPUArchCategory("amdgpu-arch options"); +cl::opt<bool> Verbose("verbose", cl::desc("Enable verbose output"), + cl::init(false), cl::cat(AMDGPUArchCategory)); + static void PrintVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n'; } diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp index 7338872dbf32f..f9beb5046568c 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp @@ -11,9 +11,21 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/CommandLine.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <string> +#include <vector> + +#ifdef _WIN32 +#include <windows.h> +#endif using namespace llvm; @@ -31,16 +43,108 @@ typedef hipError_t (*hipGetDeviceCount_t)(int *); typedef hipError_t (*hipDeviceGet_t)(int *, int); typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int); -int printGPUsByHIP() { +extern cl::opt<bool> Verbose; + #ifdef _WIN32 - constexpr const char *DynamicHIPPath = "amdhip64.dll"; +std::vector<std::string> getSearchPaths() { + std::vector<std::string> Paths; + + // Get the directory of the current executable + if (auto MainExe = sys::fs::getMainExecutable(nullptr, nullptr); + !MainExe.empty()) + Paths.push_back(sys::path::parent_path(MainExe).str()); + + // Get the system directory + char SystemDirectory[MAX_PATH]; + if (GetSystemDirectoryA(SystemDirectory, MAX_PATH) > 0) { + Paths.push_back(SystemDirectory); + } + + // Get the Windows directory + char WindowsDirectory[MAX_PATH]; + if (GetWindowsDirectoryA(WindowsDirectory, MAX_PATH) > 0) { + Paths.push_back(WindowsDirectory); + } + + // Get the current working directory + SmallVector<char, 256> CWD; + if (sys::fs::current_path(CWD)) + Paths.push_back(std::string(CWD.begin(), CWD.end())); + + // Get the PATH environment variable + if (auto PathEnv = llvm::sys::Process::GetEnv("PATH")) { + SmallVector<StringRef, 16> PathList; + StringRef(*PathEnv).split(PathList, sys::EnvPathSeparator); + for (auto &Path : PathList) + Paths.push_back(Path.str()); + } + + return Paths; +} + +// Custom comparison function for dll name +bool compareVersions(const std::string &a, const std::string &b) { + // Extract version numbers + int versionA = std::stoi(a.substr(a.find_last_of('_') + 1)); + int versionB = std::stoi(b.substr(b.find_last_of('_') + 1)); + return versionA > versionB; +} + +#endif + +// On Windows, prefer amdhip64_n.dll where n is ROCm major version and greater +// value of n takes precedence. If amdhip64_n.dll is not found, fall back to +// amdhip64.dll. The reason is that a normal driver installation only has +// amdhip64_n.dll but we do not know what n is since this progrm may be used +// with a future version of HIP runtime. +// +// On Linux, always use default libamdhip64.so. +std::pair<std::string, bool> findNewestHIPDLL() { +#ifdef _WIN32 + const char *HipDLLPrefix = "amdhip64_"; + const char *HipDLLSuffix = ".dll"; + + std::vector<std::string> SearchPaths = getSearchPaths(); + std::vector<std::string> DLLNames; + + for (const auto &Dir : SearchPaths) { + std::error_code EC; + for (sys::fs::directory_iterator DirIt(Dir, EC), DirEnd; + DirIt != DirEnd && !EC; DirIt.increment(EC)) { + StringRef Filename = sys::path::filename(DirIt->path()); + if (Filename.starts_with(HipDLLPrefix) && + Filename.ends_with(HipDLLSuffix)) + DLLNames.push_back(sys::path::convert_to_slash(DirIt->path())); + } + if (!DLLNames.empty()) + break; + } + + if (DLLNames.empty()) + return {"amdhip64.dll", true}; + + std::sort(DLLNames.begin(), DLLNames.end(), compareVersions); + return {DLLNames[0], false}; #else - constexpr const char *DynamicHIPPath = "libamdhip64.so"; + // On Linux, fallback to default shared object + return {"libamdhip64.so", true}; #endif +} + +int printGPUsByHIP() { + auto [DynamicHIPPath, IsFallback] = findNewestHIPDLL(); + + if (Verbose) { + if (IsFallback) + outs() << "Using default HIP runtime: " << DynamicHIPPath << "\n"; + else + outs() << "Found HIP runtime: " << DynamicHIPPath << "\n"; + } std::string ErrMsg; auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>( - llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath, &ErrMsg)); + llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath.c_str(), + &ErrMsg)); if (!DynlibHandle->isValid()) { llvm::errs() << "Failed to load " << DynamicHIPPath << ": " << ErrMsg << '\n'; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits