1//===- AMDGPUArchByHIP.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
18using namespace llvm;
19
20typedef struct {
21 char padding[396];
22 char gcnArchName[256];
23 char padding2[1024];
24} hipDeviceProp_t;
25
26typedef enum {
27 hipSuccess = 0,
28} hipError_t;
29
30typedef hipError_t (*hipGetDeviceCount_t)(int *);
31typedef hipError_t (*hipDeviceGet_t)(int *, int);
32typedef hipError_t (*hipGetDeviceProperties_t)(hipDeviceProp_t *, int);
33
34int 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 args: llvm::sys::DynamicLibrary::getPermanentLibrary(filename: DynamicHIPPath, errMsg: &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