Files
clang-p2996/clang/tools/amdgpu-arch/AMDGPUArchByHIP.cpp
Yaxun (Sam) Liu 661d91a0fd [clang] Make amdgpu-arch tool work on Windows
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.

Reviewed by: Matt Arsenault, Joseph Huber, Johannes Doerfert

Differential Revision: https://reviews.llvm.org/D153725
2023-07-08 00:01:02 -04:00

97 lines
3.1 KiB
C++

//===- 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"
#include "llvm/Support/raw_ostream.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;
}
llvm::outs() << prop.gcnArchName << '\n';
}
return 0;
}