yaxunl created this revision.
yaxunl added reviewers: tra, arsenm.
Herald added subscribers: kerbowa, nhaehnle, wdng, jvesely.

Do not detect device library by default in rocm detector. Only detect device 
library in HIP toolchain.

Detect rocm path by version file in host toolchains.

Also added detecting rocm version and printing rocm installation path and 
version with -v.

Fixed include path and device library detection for ROCm 3.5.


https://reviews.llvm.org/D82930

Files:
  clang/lib/Driver/ToolChains/AMDGPU.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/lib/Driver/ToolChains/ROCm.h
  clang/test/Driver/Inputs/rocm/bin/.hipVersion

Index: clang/test/Driver/Inputs/rocm/bin/.hipVersion
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/rocm/bin/.hipVersion
@@ -0,0 +1,4 @@
+# Auto-generated by cmake
+HIP_VERSION_MAJOR=3
+HIP_VERSION_MINOR=6
+HIP_VERSION_PATCH=20214-a2917cd
Index: clang/lib/Driver/ToolChains/ROCm.h
===================================================================
--- clang/lib/Driver/ToolChains/ROCm.h
+++ clang/lib/Driver/ToolChains/ROCm.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Support/VersionTuple.h"
 
 namespace clang {
 namespace driver {
@@ -38,11 +39,17 @@
     }
   };
 
+
   const Driver &D;
   bool IsValid = false;
-  // RocmVersion Version = RocmVersion::UNKNOWN;
+  // The version string in Major.Minor.Path format.
+  std::string DetectedVersion;
+  // Version containing major and minor.
+  llvm::VersionTuple VersionMajorMinor;
+  // Version containing patch.
+  std::string VersionPatch;
   SmallString<0> InstallPath;
-  // SmallString<0> BinPath;
+  SmallString<0> BinPath;
   SmallString<0> LibPath;
   SmallString<0> LibDevicePath;
   SmallString<0> IncludePath;
@@ -75,6 +82,7 @@
   mutable llvm::SmallSet<CudaArch, 4> ArchsWithBadVersion;
 
   void scanLibDevicePath();
+  void ParseHIPVersionFile(llvm::StringRef V);
 
 public:
   RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
@@ -163,6 +171,8 @@
 
   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                          llvm::opt::ArgStringList &CC1Args) const;
+
+  void detectDeviceLibrary(const llvm::opt::ArgList &Args);
 };
 
 } // end namespace driver
Index: clang/lib/Driver/ToolChains/MSVC.cpp
===================================================================
--- clang/lib/Driver/ToolChains/MSVC.cpp
+++ clang/lib/Driver/ToolChains/MSVC.cpp
@@ -805,6 +805,7 @@
 
 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
   CudaInstallation.print(OS);
+  RocmInstallation.print(OS);
 }
 
 // Windows SDKs and VC Toolchains group their contents into subdirectories based
Index: clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2656,6 +2656,7 @@
   // Print the information about how we detected the GCC installation.
   GCCInstallation.print(OS);
   CudaInstallation.print(OS);
+  RocmInstallation.print(OS);
 }
 
 bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const {
Index: clang/lib/Driver/ToolChains/AMDGPU.cpp
===================================================================
--- clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -89,6 +89,25 @@
   }
 }
 
+void RocmInstallationDetector::ParseHIPVersionFile(llvm::StringRef V) {
+  SmallVector<StringRef, 4> VersionParts;
+  V.split(VersionParts, '\n');
+  unsigned Major;
+  unsigned Minor;
+  for (auto Part : VersionParts) {
+    auto Splits = Part.split('=');
+    if (Splits.first == "HIP_VERSION_MAJOR")
+      Splits.second.getAsInteger(0, Major);
+    else if (Splits.first == "HIP_VERSION_MINOR")
+      Splits.second.getAsInteger(0, Minor);
+    else if (Splits.first == "HIP_VERSION_PATCH")
+      VersionPatch = Splits.second.str();
+  }
+  VersionMajorMinor = llvm::VersionTuple(Major, Minor);
+  DetectedVersion =
+      (Twine(Major) + "." + Twine(Minor) + "." + VersionPatch).str();
+}
+
 RocmInstallationDetector::RocmInstallationDetector(
     const Driver &D, const llvm::Triple &HostTriple,
     const llvm::opt::ArgList &Args)
@@ -133,6 +152,33 @@
     Candidates.emplace_back(D.SysRoot + "/opt/rocm");
   }
 
+  auto &FS = D.getVFS();
+
+  for (const auto &Candidate : Candidates) {
+    InstallPath = Candidate.Path;
+    if (InstallPath.empty() || !FS.exists(InstallPath))
+      continue;
+
+    llvm::sys::path::append(BinPath, InstallPath, "bin");
+    llvm::sys::path::append(IncludePath, InstallPath, "include");
+    llvm::sys::path::append(LibPath, InstallPath, "lib");
+
+    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
+        FS.getBufferForFile(BinPath + "/.hipVersion");
+    if (!VersionFile)
+      continue;
+
+    ParseHIPVersionFile((*VersionFile)->getBuffer());
+    IsValid = true;
+    return;
+  }
+  IsValid = false;
+}
+
+void RocmInstallationDetector::detectDeviceLibrary(
+    const llvm::opt::ArgList &Args) {
+  if (!IsValid)
+    return;
   bool NoBuiltinLibs = Args.hasArg(options::OPT_nogpulib);
 
   assert(LibDevicePath.empty());
@@ -157,56 +203,52 @@
     return;
   }
 
-  for (const auto &Candidate : Candidates) {
-    InstallPath = Candidate.Path;
-    if (InstallPath.empty() || !FS.exists(InstallPath))
-      continue;
-
-    // The install path situation in old versions of ROCm is a real mess, and
-    // use a different install layout. Multiple copies of the device libraries
-    // exist for each frontend project, and differ depending on which build
-    // system produced the packages. Standalone OpenCL builds also have a
-    // different directory structure from the ROCm OpenCL package.
-    //
-    // The desired structure is (${ROCM_ROOT} or
-    // ${OPENCL_ROOT})/amdgcn/bitcode/*, so try to detect this layout.
-
-    // BinPath = InstallPath + "/bin";
-    llvm::sys::path::append(IncludePath, InstallPath, "include");
-    llvm::sys::path::append(LibDevicePath, InstallPath, "amdgcn", "bitcode");
-
-    // We don't need the include path for OpenCL, since clang already ships with
-    // the default header.
-
-    bool CheckLibDevice = (!NoBuiltinLibs || Candidate.StrictChecking);
+  // The install path situation in old versions of ROCm is a real mess, and
+  // use a different install layout. Multiple copies of the device libraries
+  // exist for each frontend project, and differ depending on which build
+  // system produced the packages. Standalone OpenCL builds also have a
+  // different directory structure from the ROCm OpenCL package.
+  //
+  // The desired structure is ${ROCM_ROOT})/amdgcn/bitcode/* or
+  // ${ROCM_ROOT}/lib/* so try to detect this layout.
+
+  auto CheckDeviceLib = [&]() {
+    bool CheckLibDevice = !NoBuiltinLibs;
     if (CheckLibDevice && !FS.exists(LibDevicePath))
-      continue;
+      return false;
 
     scanLibDevicePath();
 
     if (!NoBuiltinLibs) {
       // Check that the required non-target libraries are all available.
       if (!allGenericLibsValid())
-        continue;
+        return false;
 
       // Check that we have found at least one libdevice that we can link in if
       // -nobuiltinlib hasn't been specified.
       if (LibDeviceMap.empty())
-        continue;
+        return false;
     }
-
-    IsValid = true;
-    break;
-  }
+    return true;
+  };
+  llvm::sys::path::append(LibDevicePath, InstallPath, "amdgcn", "bitcode");
+  IsValid = CheckDeviceLib();
+  if (IsValid)
+    return;
+  llvm::sys::path::append(LibDevicePath, InstallPath, "lib");
+  IsValid = CheckDeviceLib();
 }
 
 void RocmInstallationDetector::print(raw_ostream &OS) const {
   if (isValid())
-    OS << "Found ROCm installation: " << InstallPath << '\n';
+    OS << "Found ROCm installation: " << InstallPath << ", version "
+       << DetectedVersion << '\n';
 }
 
 void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
                                                  ArgStringList &CC1Args) const {
+  if (VersionMajorMinor <= llvm::VersionTuple(3, 5))
+    return;
   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
     // HIP header includes standard library wrapper headers under clang
     // cuda_wrappers directory. Since these wrapper headers include_next
@@ -385,8 +427,9 @@
 /// ROCM Toolchain
 ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args)
-  : AMDGPUToolChain(D, Triple, Args),
-    RocmInstallation(D, Triple, Args) { }
+    : AMDGPUToolChain(D, Triple, Args), RocmInstallation(D, Triple, Args) {
+  RocmInstallation.detectDeviceLibrary(Args);
+}
 
 void AMDGPUToolChain::addClangTargetOptions(
     const llvm::opt::ArgList &DriverArgs,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to