yaxunl created this revision.
yaxunl added a reviewer: tra.
Herald added subscribers: kerbowa, tpr, dstuttard, jvesely, kzhuravl.
Herald added a project: All.
yaxunl requested review of this revision.
Herald added subscribers: jplehr, sstefan1, wdng.
Herald added a reviewer: jdoerfert.

Currently amdgpu-arch tool detects AMD GPU by dynamically
loading HSA runtime shared library and using HSA API's,
which is not available on Windows.

This patch makes it work on Windows by dynamically loading
HIP runtime dll and using HIP API's.


https://reviews.llvm.org/D153725

Files:
  clang/tools/amdgpu-arch/AMDGPUArch.cpp
  clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp
  clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp
  clang/tools/amdgpu-arch/CMakeLists.txt

Index: clang/tools/amdgpu-arch/CMakeLists.txt
===================================================================
--- clang/tools/amdgpu-arch/CMakeLists.txt
+++ clang/tools/amdgpu-arch/CMakeLists.txt
@@ -8,6 +8,6 @@
 
 set(LLVM_LINK_COMPONENTS Support)
 
-add_clang_tool(amdgpu-arch AMDGPUArch.cpp)
+add_clang_tool(amdgpu-arch AMDGPUArch.cpp AMDGPUArchByHSA.cpp AMDGPUArchByHIP.cpp)
 
 target_link_libraries(amdgpu-arch PRIVATE clangBasic)
Index: clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp
===================================================================
--- /dev/null
+++ clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp
@@ -0,0 +1,121 @@
+//===- AMDGPUArchLinux.cpp - list AMDGPU installed ------*- C++ -*---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a tool for detecting name of AMDGPU installed in system
+// using HSA on Linux. This tool is used by AMDGPU OpenMP and HIP driver.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Version.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+typedef enum {
+  HSA_STATUS_SUCCESS = 0x0,
+} hsa_status_t;
+
+typedef enum {
+  HSA_DEVICE_TYPE_CPU = 0,
+  HSA_DEVICE_TYPE_GPU = 1,
+} hsa_device_type_t;
+
+typedef enum {
+  HSA_AGENT_INFO_NAME = 0,
+  HSA_AGENT_INFO_DEVICE = 17,
+} hsa_agent_info_t;
+
+typedef struct hsa_agent_s {
+  uint64_t handle;
+} hsa_agent_t;
+
+hsa_status_t (*hsa_init)();
+hsa_status_t (*hsa_shut_down)();
+hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *);
+hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*)(hsa_agent_t, void *),
+                                   void *);
+
+constexpr const char *DynamicHSAPath = "libhsa-runtime64.so";
+
+llvm::Error loadHSA() {
+  std::string ErrMsg;
+  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
+      llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg));
+  if (!DynlibHandle->isValid()) {
+    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                   "Failed to 'dlopen' %s", DynamicHSAPath);
+  }
+#define DYNAMIC_INIT(SYMBOL)                                                   \
+  {                                                                            \
+    void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
+    if (!SymbolPtr)                                                            \
+      return llvm::createStringError(llvm::inconvertibleErrorCode(),           \
+                                     "Failed to 'dlsym' " #SYMBOL);            \
+    SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
+  }
+  DYNAMIC_INIT(hsa_init);
+  DYNAMIC_INIT(hsa_shut_down);
+  DYNAMIC_INIT(hsa_agent_get_info);
+  DYNAMIC_INIT(hsa_iterate_agents);
+#undef DYNAMIC_INIT
+  return llvm::Error::success();
+}
+
+static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) {
+  hsa_device_type_t DeviceType;
+  hsa_status_t Status =
+      hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DeviceType);
+
+  // continue only if device type if GPU
+  if (Status != HSA_STATUS_SUCCESS || DeviceType != HSA_DEVICE_TYPE_GPU) {
+    return Status;
+  }
+
+  std::vector<std::string> *GPUs =
+      static_cast<std::vector<std::string> *>(Data);
+  char GPUName[64];
+  Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, GPUName);
+  if (Status != HSA_STATUS_SUCCESS) {
+    return Status;
+  }
+  GPUs->push_back(GPUName);
+  return HSA_STATUS_SUCCESS;
+}
+
+int printGPUsByHSA() {
+  // Attempt to load the HSA runtime.
+  if (llvm::Error Err = loadHSA()) {
+    logAllUnhandledErrors(std::move(Err), llvm::errs());
+    return 1;
+  }
+
+  hsa_status_t Status = hsa_init();
+  if (Status != HSA_STATUS_SUCCESS) {
+    return 1;
+  }
+
+  std::vector<std::string> GPUs;
+  Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs);
+  if (Status != HSA_STATUS_SUCCESS) {
+    return 1;
+  }
+
+  for (const auto &GPU : GPUs)
+    printf("%s\n", GPU.c_str());
+
+  if (GPUs.size() < 1)
+    return 1;
+
+  hsa_shut_down();
+  return 0;
+}
Index: clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp
===================================================================
--- /dev/null
+++ clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp
@@ -0,0 +1,95 @@
+//===- AMDGPUArch.cpp - list AMDGPU installed ----------*- C++ -*---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a tool for detecting name of AMDGPU installed in system
+// using HIP runtime. This tool is used by AMDGPU OpenMP and HIP driver.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+
+typedef struct {
+  char padding[396];
+  char gcnArchName[256];
+  char padding2[1024];
+} hipDeviceProp_t;
+
+typedef enum {
+  hipSuccess = 0,
+} hipError_t;
+
+typedef hipError_t (*hipGetDeviceCount_t)(int *);
+typedef hipError_t (*hipDeviceGet_t)(int *, int);
+typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int);
+
+int printGPUsByHIP() {
+#ifdef _WIN32
+  constexpr const char *DynamicHIPPath = "amdhip64.dll";
+#else
+  constexpr const char *DynamicHIPPath = "libamdhip64.so";
+#endif
+
+  std::string ErrMsg;
+  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
+      llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath, &ErrMsg));
+  if (!DynlibHandle->isValid()) {
+    llvm::errs() << "Failed to load " << DynamicHIPPath << ": " << ErrMsg
+                 << "\n";
+    return 1;
+  }
+
+#define DYNAMIC_INIT_HIP(SYMBOL)                                               \
+  {                                                                            \
+    void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
+    if (!SymbolPtr) {                                                          \
+      llvm::errs() << "Failed to find symbol " << #SYMBOL << "\n";             \
+      return 1;                                                                \
+    }                                                                          \
+    SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
+  }
+
+  hipGetDeviceCount_t hipGetDeviceCount;
+  hipDeviceGet_t hipDeviceGet;
+  hipGetDeviceProperties_t hipGetDeviceProperties;
+
+  DYNAMIC_INIT_HIP(hipGetDeviceCount);
+  DYNAMIC_INIT_HIP(hipDeviceGet);
+  DYNAMIC_INIT_HIP(hipGetDeviceProperties);
+
+#undef DYNAMIC_INIT_HIP
+
+  int deviceCount;
+  hipError_t err = hipGetDeviceCount(&deviceCount);
+  if (err != hipSuccess) {
+    llvm::errs() << "Failed to get device count\n";
+    return 1;
+  }
+
+  for (int i = 0; i < deviceCount; ++i) {
+    int deviceId;
+    err = hipDeviceGet(&deviceId, i);
+    if (err != hipSuccess) {
+      llvm::errs() << "Failed to get device id for ordinal " << i << "\n";
+      return 1;
+    }
+
+    hipDeviceProp_t prop;
+    err = hipGetDeviceProperties(&prop, deviceId);
+    if (err != hipSuccess) {
+      llvm::errs() << "Failed to get device properties for device " << deviceId
+                   << "\n";
+      return 1;
+    }
+    printf("%s\n", prop.gcnArchName);
+  }
+
+  return 0;
+}
Index: clang/tools/amdgpu-arch/AMDGPUArch.cpp
===================================================================
--- clang/tools/amdgpu-arch/AMDGPUArch.cpp
+++ clang/tools/amdgpu-arch/AMDGPUArch.cpp
@@ -6,18 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements a tool for detecting name of AMDGPU installed in system
-// using HSA. This tool is used by AMDGPU OpenMP driver.
+// This file implements a tool for detecting name of AMDGPU installed in system.
+// This tool is used by AMDGPU OpenMP and HIP driver.
 //
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Version.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <string>
-#include <vector>
 
 using namespace llvm;
 
@@ -30,76 +25,8 @@
   OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n';
 }
 
-typedef enum {
-  HSA_STATUS_SUCCESS = 0x0,
-} hsa_status_t;
-
-typedef enum {
-  HSA_DEVICE_TYPE_CPU = 0,
-  HSA_DEVICE_TYPE_GPU = 1,
-} hsa_device_type_t;
-
-typedef enum {
-  HSA_AGENT_INFO_NAME = 0,
-  HSA_AGENT_INFO_DEVICE = 17,
-} hsa_agent_info_t;
-
-typedef struct hsa_agent_s {
-  uint64_t handle;
-} hsa_agent_t;
-
-hsa_status_t (*hsa_init)();
-hsa_status_t (*hsa_shut_down)();
-hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *);
-hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*)(hsa_agent_t, void *),
-                                   void *);
-
-constexpr const char *DynamicHSAPath = "libhsa-runtime64.so";
-
-llvm::Error loadHSA() {
-  std::string ErrMsg;
-  auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
-      llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg));
-  if (!DynlibHandle->isValid()) {
-    return llvm::createStringError(llvm::inconvertibleErrorCode(),
-                                   "Failed to 'dlopen' %s", DynamicHSAPath);
-  }
-#define DYNAMIC_INIT(SYMBOL)                                                   \
-  {                                                                            \
-    void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
-    if (!SymbolPtr)                                                            \
-      return llvm::createStringError(llvm::inconvertibleErrorCode(),           \
-                                     "Failed to 'dlsym' " #SYMBOL);            \
-    SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
-  }
-  DYNAMIC_INIT(hsa_init);
-  DYNAMIC_INIT(hsa_shut_down);
-  DYNAMIC_INIT(hsa_agent_get_info);
-  DYNAMIC_INIT(hsa_iterate_agents);
-#undef DYNAMIC_INIT
-  return llvm::Error::success();
-}
-
-static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) {
-  hsa_device_type_t DeviceType;
-  hsa_status_t Status =
-      hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DeviceType);
-
-  // continue only if device type if GPU
-  if (Status != HSA_STATUS_SUCCESS || DeviceType != HSA_DEVICE_TYPE_GPU) {
-    return Status;
-  }
-
-  std::vector<std::string> *GPUs =
-      static_cast<std::vector<std::string> *>(Data);
-  char GPUName[64];
-  Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, GPUName);
-  if (Status != HSA_STATUS_SUCCESS) {
-    return Status;
-  }
-  GPUs->push_back(GPUName);
-  return HSA_STATUS_SUCCESS;
-}
+int printGPUsByHSA();
+int printGPUsByHIP();
 
 int main(int argc, char *argv[]) {
   cl::HideUnrelatedOptions(AMDGPUArchCategory);
@@ -117,29 +44,9 @@
     return 0;
   }
 
-  // Attempt to load the HSA runtime.
-  if (llvm::Error Err = loadHSA()) {
-    logAllUnhandledErrors(std::move(Err), llvm::errs());
-    return 1;
-  }
-
-  hsa_status_t Status = hsa_init();
-  if (Status != HSA_STATUS_SUCCESS) {
-    return 1;
-  }
-
-  std::vector<std::string> GPUs;
-  Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs);
-  if (Status != HSA_STATUS_SUCCESS) {
-    return 1;
-  }
-
-  for (const auto &GPU : GPUs)
-    printf("%s\n", GPU.c_str());
-
-  if (GPUs.size() < 1)
-    return 1;
-
-  hsa_shut_down();
-  return 0;
+#ifdef _WIN32
+  return printGPUsByHIP();
+#else
+  return printGPUsByHSA();
+#endif
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to