1 //===- AMDGPUArch.cpp - list AMDGPU installed ----------*- C++ -*---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a tool for detecting name of AMDGPU installed in system
10 // using HIP runtime. This tool is used by AMDGPU OpenMP and HIP driver.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Support/DynamicLibrary.h"
15 #include "llvm/Support/Error.h"
16 #include "llvm/Support/raw_ostream.h"
17 
18 using namespace llvm;
19 
20 typedef struct {
21   char padding[396];
22   char gcnArchName[256];
23   char padding2[1024];
24 } hipDeviceProp_t;
25 
26 typedef enum {
27   hipSuccess = 0,
28 } hipError_t;
29 
30 typedef hipError_t (*hipGetDeviceCount_t)(int *);
31 typedef hipError_t (*hipDeviceGet_t)(int *, int);
32 typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int);
33 
34 int printGPUsByHIP() {
35 #ifdef _WIN32
36   constexpr const char *DynamicHIPPath = "amdhip64.dll";
37 #else
38   constexpr const char *DynamicHIPPath = "libamdhip64.so";
39 #endif
40 
41   std::string ErrMsg;
42   auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
43       llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHIPPath, &ErrMsg));
44   if (!DynlibHandle->isValid()) {
45     llvm::errs() << "Failed to load " << DynamicHIPPath << ": " << ErrMsg
46                  << '\n';
47     return 1;
48   }
49 
50 #define DYNAMIC_INIT_HIP(SYMBOL)                                               \
51   {                                                                            \
52     void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL);               \
53     if (!SymbolPtr) {                                                          \
54       llvm::errs() << "Failed to find symbol " << #SYMBOL << '\n';             \
55       return 1;                                                                \
56     }                                                                          \
57     SYMBOL = reinterpret_cast<decltype(SYMBOL)>(SymbolPtr);                    \
58   }
59 
60   hipGetDeviceCount_t hipGetDeviceCount;
61   hipDeviceGet_t hipDeviceGet;
62   hipGetDeviceProperties_t hipGetDeviceProperties;
63 
64   DYNAMIC_INIT_HIP(hipGetDeviceCount);
65   DYNAMIC_INIT_HIP(hipDeviceGet);
66   DYNAMIC_INIT_HIP(hipGetDeviceProperties);
67 
68 #undef DYNAMIC_INIT_HIP
69 
70   int deviceCount;
71   hipError_t err = hipGetDeviceCount(&deviceCount);
72   if (err != hipSuccess) {
73     llvm::errs() << "Failed to get device count\n";
74     return 1;
75   }
76 
77   for (int i = 0; i < deviceCount; ++i) {
78     int deviceId;
79     err = hipDeviceGet(&deviceId, i);
80     if (err != hipSuccess) {
81       llvm::errs() << "Failed to get device id for ordinal " << i << '\n';
82       return 1;
83     }
84 
85     hipDeviceProp_t prop;
86     err = hipGetDeviceProperties(&prop, deviceId);
87     if (err != hipSuccess) {
88       llvm::errs() << "Failed to get device properties for device " << deviceId
89                    << '\n';
90       return 1;
91     }
92     llvm::outs() << prop.gcnArchName << '\n';
93   }
94 
95   return 0;
96 }
97