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
1830using namespace llvm ;
1931
@@ -31,16 +43,108 @@ typedef hipError_t (*hipGetDeviceCount_t)(int *);
3143typedef hipError_t (*hipDeviceGet_t)(int *, int );
3244typedef 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