pdhaliwal updated this revision to Diff 335761.
pdhaliwal marked 10 inline comments as done.
pdhaliwal added a comment.

Addressed review comments.

RE test: Since the tool is contingent on the results of HSA API call, adding a 
test
which would always PASS on all the systems with different AMD GPUs as well as 
always ignored on systems
with non AMDGPUs would not work. I welcome suggestions on how to resolve this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99949/new/

https://reviews.llvm.org/D99949

Files:
  clang/lib/Driver/ToolChains/AMDGPU.cpp
  clang/lib/Driver/ToolChains/AMDGPU.h
  clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
  clang/tools/CMakeLists.txt
  clang/tools/amdgpu-arch/AMDGPUArch.cpp
  clang/tools/amdgpu-arch/CMakeLists.txt

Index: clang/tools/amdgpu-arch/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang/tools/amdgpu-arch/CMakeLists.txt
@@ -0,0 +1,17 @@
+# //===----------------------------------------------------------------------===//
+# //
+# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# // See https://llvm.org/LICENSE.txt for details.
+# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# //
+# //===----------------------------------------------------------------------===//
+
+find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm)
+if (NOT ${hsa-runtime64_FOUND})
+  message(STATUS "Not building amdgpu-arch: hsa-runtime64 not found")
+  return()
+endif()
+
+add_clang_tool(amdgpu-arch AMDGPUArch.cpp)
+
+clang_target_link_libraries(amdgpu-arch PRIVATE hsa-runtime64::hsa-runtime64)
Index: clang/tools/amdgpu-arch/AMDGPUArch.cpp
===================================================================
--- /dev/null
+++ clang/tools/amdgpu-arch/AMDGPUArch.cpp
@@ -0,0 +1,59 @@
+//===- 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 HSA. This tool is used by AMDGPU OpenMP driver.
+//
+//===----------------------------------------------------------------------===//
+
+#include <hsa.h>
+#include <string>
+#include <vector>
+
+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 main() {
+  hsa_status_t Status = hsa_init();
+  if (Status != HSA_STATUS_SUCCESS) {
+    fprintf(stderr, "Unable to initialize HSA\n");
+  }
+
+  std::vector<std::string> GPUs;
+  Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs);
+  if (Status != HSA_STATUS_SUCCESS) {
+    return 1;
+  }
+
+  for (unsigned I = 0; I < GPUs.size(); I++) {
+    printf("%s\n", GPUs[I].c_str());
+  }
+  if (GPUs.size() < 1)
+    return 1;
+
+  hsa_shut_down();
+  return 0;
+}
Index: clang/tools/CMakeLists.txt
===================================================================
--- clang/tools/CMakeLists.txt
+++ clang/tools/CMakeLists.txt
@@ -43,3 +43,5 @@
 
 # libclang may require clang-tidy in clang-tools-extra.
 add_clang_subdirectory(libclang)
+
+add_clang_subdirectory(amdgpu-arch)
Index: clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
===================================================================
--- clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -145,10 +145,16 @@
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
+  const ToolChain &TC = getToolChain();
   assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target");
 
+  const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC =
+      static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC);
   StringRef GPUArch = Args.getLastArgValue(options::OPT_march_EQ);
-  assert(GPUArch.startswith("gfx") && "Unsupported sub arch");
+  if (GPUArch.empty()) {
+    GPUArch = AMDGPUOpenMPTC.getSystemGPUArch();
+  }
+  assert(!GPUArch.empty() && "Must have an explicit GPU arch.");
 
   // Prefix for temporary file name.
   std::string Prefix;
@@ -187,6 +193,11 @@
   HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
 
   StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
+  if (GpuArch.empty()) {
+    // in case no GPU arch is passed via -march, then try to detect
+    // the system gpu
+    GpuArch = getSystemGPUArch();
+  }
   assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
   assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
          "Only OpenMP offloading kinds are supported.");
Index: clang/lib/Driver/ToolChains/AMDGPU.h
===================================================================
--- clang/lib/Driver/ToolChains/AMDGPU.h
+++ clang/lib/Driver/ToolChains/AMDGPU.h
@@ -100,12 +100,18 @@
   /// Should skip argument.
   bool shouldSkipArgument(const llvm::opt::Arg *Arg) const;
 
+  /// Uses HSA to get arch of the system GPU. Returns empty string
+  /// if unable to find one.
+  SmallString<8> getSystemGPUArch() const;
+
 protected:
   /// Check and diagnose invalid target ID specified by -mcpu.
   void checkTargetID(const llvm::opt::ArgList &DriverArgs) const;
 
   /// Get GPU arch from -mcpu without checking.
   StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;
+
+  SmallVector<SmallString<8>, 1> detectSystemGPUs() const;
 };
 
 class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
Index: clang/lib/Driver/ToolChains/AMDGPU.cpp
===================================================================
--- clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -13,9 +13,13 @@
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/LineIterator.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
+#define AMDGPU_ARCH_PROGRAM_NAME "amdgpu-arch"
+
 using namespace clang::driver;
 using namespace clang::driver::tools;
 using namespace clang::driver::toolchains;
@@ -715,6 +719,52 @@
   }
 }
 
+llvm::SmallVector<SmallString<8>, 1> AMDGPUToolChain::detectSystemGPUs() const {
+  std::string Program = GetProgramPath(AMDGPU_ARCH_PROGRAM_NAME);
+  llvm::SmallString<64> OutputFile;
+  llvm::sys::fs::createTemporaryFile("print-system-gpus", "" /* No Suffix */,
+                                     OutputFile);
+  llvm::FileRemover OutputRemover(OutputFile.c_str());
+  llvm::Optional<llvm::StringRef> Redirects[] = {
+      {""},
+      StringRef(OutputFile),
+      {""},
+  };
+
+  if (llvm::sys::ExecuteAndWait(Program.c_str(), {}, {}, Redirects)) {
+    return {};
+  }
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
+      llvm::MemoryBuffer::getFile(OutputFile.c_str());
+  if (!OutputBuf)
+    return {};
+
+  llvm::SmallVector<SmallString<8>, 1> GPUArchs;
+  for (llvm::line_iterator LineIt(**OutputBuf); !LineIt.is_at_end(); ++LineIt) {
+    GPUArchs.push_back(*LineIt);
+  }
+  return GPUArchs;
+}
+
+SmallString<8> AMDGPUToolChain::getSystemGPUArch() const {
+  // detect the AMDGPU installed in system
+  auto GPUArchs = detectSystemGPUs();
+  if (GPUArchs.empty()) {
+    return SmallString<8>("");
+  }
+  if (GPUArchs.size() > 1) {
+    bool AllSame = std::all_of(
+        GPUArchs.begin(), GPUArchs.end(),
+        [&](const StringRef &GPUArch) { return GPUArch == GPUArchs.front(); });
+    if (AllSame)
+      return GPUArchs.front();
+
+    return SmallString<8>("");
+  }
+  return GPUArchs.front();
+}
+
 void ROCMToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
     Action::OffloadKind DeviceOffloadingKind) const {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to