15ffd83dbSDimitry Andric //===--- ROCm.h - ROCm installation detector --------------------*- C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 105ffd83dbSDimitry Andric #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 115ffd83dbSDimitry Andric 125ffd83dbSDimitry Andric #include "clang/Basic/Cuda.h" 135ffd83dbSDimitry Andric #include "clang/Basic/LLVM.h" 145ffd83dbSDimitry Andric #include "clang/Driver/Driver.h" 155ffd83dbSDimitry Andric #include "clang/Driver/Options.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/SmallString.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/StringMap.h" 185ffd83dbSDimitry Andric #include "llvm/Option/ArgList.h" 195ffd83dbSDimitry Andric #include "llvm/Support/VersionTuple.h" 2006c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 215ffd83dbSDimitry Andric 225ffd83dbSDimitry Andric namespace clang { 235ffd83dbSDimitry Andric namespace driver { 245ffd83dbSDimitry Andric 2581ad6265SDimitry Andric /// ABI version of device library. 2681ad6265SDimitry Andric struct DeviceLibABIVersion { 2781ad6265SDimitry Andric unsigned ABIVersion = 0; 2881ad6265SDimitry Andric DeviceLibABIVersion(unsigned V) : ABIVersion(V) {} 2981ad6265SDimitry Andric static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) { 3081ad6265SDimitry Andric if (CodeObjectVersion < 4) 3181ad6265SDimitry Andric CodeObjectVersion = 4; 3281ad6265SDimitry Andric return DeviceLibABIVersion(CodeObjectVersion * 100); 3381ad6265SDimitry Andric } 3481ad6265SDimitry Andric /// Whether ABI version bc file is requested. 3581ad6265SDimitry Andric /// ABIVersion is code object version multiplied by 100. Code object v4 3681ad6265SDimitry Andric /// and below works with ROCm 5.0 and below which does not have 3781ad6265SDimitry Andric /// abi_version_*.bc. Code object v5 requires abi_version_500.bc. 3881ad6265SDimitry Andric bool requiresLibrary() { return ABIVersion >= 500; } 3981ad6265SDimitry Andric std::string toString() { 4081ad6265SDimitry Andric assert(ABIVersion % 100 == 0 && "Not supported"); 4181ad6265SDimitry Andric return Twine(ABIVersion / 100).str(); 4281ad6265SDimitry Andric } 4381ad6265SDimitry Andric }; 4481ad6265SDimitry Andric 455ffd83dbSDimitry Andric /// A class to find a viable ROCM installation 465ffd83dbSDimitry Andric /// TODO: Generalize to handle libclc. 475ffd83dbSDimitry Andric class RocmInstallationDetector { 485ffd83dbSDimitry Andric private: 495ffd83dbSDimitry Andric struct ConditionalLibrary { 505ffd83dbSDimitry Andric SmallString<0> On; 515ffd83dbSDimitry Andric SmallString<0> Off; 525ffd83dbSDimitry Andric 535ffd83dbSDimitry Andric bool isValid() const { return !On.empty() && !Off.empty(); } 545ffd83dbSDimitry Andric 555ffd83dbSDimitry Andric StringRef get(bool Enabled) const { 565ffd83dbSDimitry Andric assert(isValid()); 575ffd83dbSDimitry Andric return Enabled ? On : Off; 585ffd83dbSDimitry Andric } 595ffd83dbSDimitry Andric }; 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric // Installation path candidate. 625ffd83dbSDimitry Andric struct Candidate { 635ffd83dbSDimitry Andric llvm::SmallString<0> Path; 645ffd83dbSDimitry Andric bool StrictChecking; 65fe6060f1SDimitry Andric // Release string for ROCm packages built with SPACK if not empty. The 66fe6060f1SDimitry Andric // installation directories of ROCm packages built with SPACK follow the 67fe6060f1SDimitry Andric // convention <package_name>-<rocm_release_string>-<hash>. 68fe6060f1SDimitry Andric std::string SPACKReleaseStr; 695ffd83dbSDimitry Andric 70fe6060f1SDimitry Andric bool isSPACK() const { return !SPACKReleaseStr.empty(); } 71fe6060f1SDimitry Andric Candidate(std::string Path, bool StrictChecking = false, 72fe6060f1SDimitry Andric StringRef SPACKReleaseStr = {}) 73fe6060f1SDimitry Andric : Path(Path), StrictChecking(StrictChecking), 74fe6060f1SDimitry Andric SPACKReleaseStr(SPACKReleaseStr.str()) {} 755ffd83dbSDimitry Andric }; 765ffd83dbSDimitry Andric 775ffd83dbSDimitry Andric const Driver &D; 785ffd83dbSDimitry Andric bool HasHIPRuntime = false; 795ffd83dbSDimitry Andric bool HasDeviceLibrary = false; 80*5f757f3fSDimitry Andric bool HasHIPStdParLibrary = false; 81*5f757f3fSDimitry Andric bool HasRocThrustLibrary = false; 82*5f757f3fSDimitry Andric bool HasRocPrimLibrary = false; 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric // Default version if not detected or specified. 855ffd83dbSDimitry Andric const unsigned DefaultVersionMajor = 3; 865ffd83dbSDimitry Andric const unsigned DefaultVersionMinor = 5; 875ffd83dbSDimitry Andric const char *DefaultVersionPatch = "0"; 885ffd83dbSDimitry Andric 895ffd83dbSDimitry Andric // The version string in Major.Minor.Patch format. 905ffd83dbSDimitry Andric std::string DetectedVersion; 915ffd83dbSDimitry Andric // Version containing major and minor. 925ffd83dbSDimitry Andric llvm::VersionTuple VersionMajorMinor; 935ffd83dbSDimitry Andric // Version containing patch. 945ffd83dbSDimitry Andric std::string VersionPatch; 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric // ROCm path specified by --rocm-path. 975ffd83dbSDimitry Andric StringRef RocmPathArg; 985ffd83dbSDimitry Andric // ROCm device library paths specified by --rocm-device-lib-path. 995ffd83dbSDimitry Andric std::vector<std::string> RocmDeviceLibPathArg; 100fe6060f1SDimitry Andric // HIP runtime path specified by --hip-path. 101fe6060f1SDimitry Andric StringRef HIPPathArg; 102*5f757f3fSDimitry Andric // HIP Standard Parallel Algorithm acceleration library specified by 103*5f757f3fSDimitry Andric // --hipstdpar-path 104*5f757f3fSDimitry Andric StringRef HIPStdParPathArg; 105*5f757f3fSDimitry Andric // rocThrust algorithm library specified by --hipstdpar-thrust-path 106*5f757f3fSDimitry Andric StringRef HIPRocThrustPathArg; 107*5f757f3fSDimitry Andric // rocPrim algorithm library specified by --hipstdpar-prim-path 108*5f757f3fSDimitry Andric StringRef HIPRocPrimPathArg; 1095ffd83dbSDimitry Andric // HIP version specified by --hip-version. 1105ffd83dbSDimitry Andric StringRef HIPVersionArg; 1115ffd83dbSDimitry Andric // Wheter -nogpulib is specified. 1125ffd83dbSDimitry Andric bool NoBuiltinLibs = false; 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric // Paths 1155ffd83dbSDimitry Andric SmallString<0> InstallPath; 1165ffd83dbSDimitry Andric SmallString<0> BinPath; 1175ffd83dbSDimitry Andric SmallString<0> LibPath; 1185ffd83dbSDimitry Andric SmallString<0> LibDevicePath; 1195ffd83dbSDimitry Andric SmallString<0> IncludePath; 120bdd1243dSDimitry Andric SmallString<0> SharePath; 1215ffd83dbSDimitry Andric llvm::StringMap<std::string> LibDeviceMap; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric // Libraries that are always linked. 1245ffd83dbSDimitry Andric SmallString<0> OCML; 1255ffd83dbSDimitry Andric SmallString<0> OCKL; 1265ffd83dbSDimitry Andric 1275ffd83dbSDimitry Andric // Libraries that are always linked depending on the language 1285ffd83dbSDimitry Andric SmallString<0> OpenCL; 1295ffd83dbSDimitry Andric SmallString<0> HIP; 1305ffd83dbSDimitry Andric 131fe6060f1SDimitry Andric // Asan runtime library 132fe6060f1SDimitry Andric SmallString<0> AsanRTL; 133fe6060f1SDimitry Andric 1345ffd83dbSDimitry Andric // Libraries swapped based on compile flags. 1355ffd83dbSDimitry Andric ConditionalLibrary WavefrontSize64; 1365ffd83dbSDimitry Andric ConditionalLibrary FiniteOnly; 1375ffd83dbSDimitry Andric ConditionalLibrary UnsafeMath; 1385ffd83dbSDimitry Andric ConditionalLibrary DenormalsAreZero; 1395ffd83dbSDimitry Andric ConditionalLibrary CorrectlyRoundedSqrt; 1405ffd83dbSDimitry Andric 14181ad6265SDimitry Andric // Maps ABI version to library path. The version number is in the format of 14281ad6265SDimitry Andric // three digits as used in the ABI version library name. 14381ad6265SDimitry Andric std::map<unsigned, std::string> ABIVersionMap; 14481ad6265SDimitry Andric 145fe6060f1SDimitry Andric // Cache ROCm installation search paths. 146fe6060f1SDimitry Andric SmallVector<Candidate, 4> ROCmSearchDirs; 147fe6060f1SDimitry Andric bool PrintROCmSearchDirs; 148fe6060f1SDimitry Andric bool Verbose; 149fe6060f1SDimitry Andric 1505ffd83dbSDimitry Andric bool allGenericLibsValid() const { 1515ffd83dbSDimitry Andric return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() && 1525ffd83dbSDimitry Andric WavefrontSize64.isValid() && FiniteOnly.isValid() && 1535ffd83dbSDimitry Andric UnsafeMath.isValid() && DenormalsAreZero.isValid() && 1545ffd83dbSDimitry Andric CorrectlyRoundedSqrt.isValid(); 1555ffd83dbSDimitry Andric } 1565ffd83dbSDimitry Andric 1575ffd83dbSDimitry Andric void scanLibDevicePath(llvm::StringRef Path); 158e8d8bef9SDimitry Andric bool parseHIPVersionFile(llvm::StringRef V); 159fe6060f1SDimitry Andric const SmallVectorImpl<Candidate> &getInstallationPathCandidates(); 160fe6060f1SDimitry Andric 161fe6060f1SDimitry Andric /// Find the path to a SPACK package under the ROCm candidate installation 162fe6060f1SDimitry Andric /// directory if the candidate is a SPACK ROCm candidate. \returns empty 163fe6060f1SDimitry Andric /// string if the candidate is not SPACK ROCm candidate or the requested 164fe6060f1SDimitry Andric /// package is not found. 165fe6060f1SDimitry Andric llvm::SmallString<0> findSPACKPackage(const Candidate &Cand, 166fe6060f1SDimitry Andric StringRef PackageName); 1675ffd83dbSDimitry Andric 1685ffd83dbSDimitry Andric public: 1695ffd83dbSDimitry Andric RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, 1705ffd83dbSDimitry Andric const llvm::opt::ArgList &Args, 1715ffd83dbSDimitry Andric bool DetectHIPRuntime = true, 1725ffd83dbSDimitry Andric bool DetectDeviceLib = false); 1735ffd83dbSDimitry Andric 174fe6060f1SDimitry Andric /// Get file paths of default bitcode libraries common to AMDGPU based 175fe6060f1SDimitry Andric /// toolchains. 176fe6060f1SDimitry Andric llvm::SmallVector<std::string, 12> 177fe6060f1SDimitry Andric getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, 178fe6060f1SDimitry Andric StringRef LibDeviceFile, bool Wave64, bool DAZ, 179fe6060f1SDimitry Andric bool FiniteOnly, bool UnsafeMathOpt, 18081ad6265SDimitry Andric bool FastRelaxedMath, bool CorrectSqrt, 18181ad6265SDimitry Andric DeviceLibABIVersion ABIVer, bool isOpenMP) const; 18281ad6265SDimitry Andric /// Check file paths of default bitcode libraries common to AMDGPU based 18381ad6265SDimitry Andric /// toolchains. \returns false if there are invalid or missing files. 18481ad6265SDimitry Andric bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, 18581ad6265SDimitry Andric DeviceLibABIVersion ABIVer) const; 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric /// Check whether we detected a valid HIP runtime. 1885ffd83dbSDimitry Andric bool hasHIPRuntime() const { return HasHIPRuntime; } 1895ffd83dbSDimitry Andric 1905ffd83dbSDimitry Andric /// Check whether we detected a valid ROCm device library. 1915ffd83dbSDimitry Andric bool hasDeviceLibrary() const { return HasDeviceLibrary; } 1925ffd83dbSDimitry Andric 193*5f757f3fSDimitry Andric /// Check whether we detected a valid HIP STDPAR Acceleration library. 194*5f757f3fSDimitry Andric bool hasHIPStdParLibrary() const { return HasHIPStdParLibrary; } 195*5f757f3fSDimitry Andric 1965ffd83dbSDimitry Andric /// Print information about the detected ROCm installation. 1975ffd83dbSDimitry Andric void print(raw_ostream &OS) const; 1985ffd83dbSDimitry Andric 1995ffd83dbSDimitry Andric /// Get the detected Rocm install's version. 2005ffd83dbSDimitry Andric // RocmVersion version() const { return Version; } 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric /// Get the detected Rocm installation path. 2035ffd83dbSDimitry Andric StringRef getInstallPath() const { return InstallPath; } 2045ffd83dbSDimitry Andric 2055ffd83dbSDimitry Andric /// Get the detected path to Rocm's bin directory. 2065ffd83dbSDimitry Andric // StringRef getBinPath() const { return BinPath; } 2075ffd83dbSDimitry Andric 2085ffd83dbSDimitry Andric /// Get the detected Rocm Include path. 2095ffd83dbSDimitry Andric StringRef getIncludePath() const { return IncludePath; } 2105ffd83dbSDimitry Andric 2115ffd83dbSDimitry Andric /// Get the detected Rocm library path. 2125ffd83dbSDimitry Andric StringRef getLibPath() const { return LibPath; } 2135ffd83dbSDimitry Andric 2145ffd83dbSDimitry Andric /// Get the detected Rocm device library path. 2155ffd83dbSDimitry Andric StringRef getLibDevicePath() const { return LibDevicePath; } 2165ffd83dbSDimitry Andric 2175ffd83dbSDimitry Andric StringRef getOCMLPath() const { 2185ffd83dbSDimitry Andric assert(!OCML.empty()); 2195ffd83dbSDimitry Andric return OCML; 2205ffd83dbSDimitry Andric } 2215ffd83dbSDimitry Andric 2225ffd83dbSDimitry Andric StringRef getOCKLPath() const { 2235ffd83dbSDimitry Andric assert(!OCKL.empty()); 2245ffd83dbSDimitry Andric return OCKL; 2255ffd83dbSDimitry Andric } 2265ffd83dbSDimitry Andric 2275ffd83dbSDimitry Andric StringRef getOpenCLPath() const { 2285ffd83dbSDimitry Andric assert(!OpenCL.empty()); 2295ffd83dbSDimitry Andric return OpenCL; 2305ffd83dbSDimitry Andric } 2315ffd83dbSDimitry Andric 2325ffd83dbSDimitry Andric StringRef getHIPPath() const { 2335ffd83dbSDimitry Andric assert(!HIP.empty()); 2345ffd83dbSDimitry Andric return HIP; 2355ffd83dbSDimitry Andric } 2365ffd83dbSDimitry Andric 237fe6060f1SDimitry Andric /// Returns empty string of Asan runtime library is not available. 238fe6060f1SDimitry Andric StringRef getAsanRTLPath() const { return AsanRTL; } 239fe6060f1SDimitry Andric 2405ffd83dbSDimitry Andric StringRef getWavefrontSize64Path(bool Enabled) const { 2415ffd83dbSDimitry Andric return WavefrontSize64.get(Enabled); 2425ffd83dbSDimitry Andric } 2435ffd83dbSDimitry Andric 2445ffd83dbSDimitry Andric StringRef getFiniteOnlyPath(bool Enabled) const { 2455ffd83dbSDimitry Andric return FiniteOnly.get(Enabled); 2465ffd83dbSDimitry Andric } 2475ffd83dbSDimitry Andric 2485ffd83dbSDimitry Andric StringRef getUnsafeMathPath(bool Enabled) const { 2495ffd83dbSDimitry Andric return UnsafeMath.get(Enabled); 2505ffd83dbSDimitry Andric } 2515ffd83dbSDimitry Andric 2525ffd83dbSDimitry Andric StringRef getDenormalsAreZeroPath(bool Enabled) const { 2535ffd83dbSDimitry Andric return DenormalsAreZero.get(Enabled); 2545ffd83dbSDimitry Andric } 2555ffd83dbSDimitry Andric 2565ffd83dbSDimitry Andric StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const { 2575ffd83dbSDimitry Andric return CorrectlyRoundedSqrt.get(Enabled); 2585ffd83dbSDimitry Andric } 2595ffd83dbSDimitry Andric 26081ad6265SDimitry Andric StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const { 26181ad6265SDimitry Andric auto Loc = ABIVersionMap.find(ABIVer.ABIVersion); 26281ad6265SDimitry Andric if (Loc == ABIVersionMap.end()) 26381ad6265SDimitry Andric return StringRef(); 26481ad6265SDimitry Andric return Loc->second; 26581ad6265SDimitry Andric } 26681ad6265SDimitry Andric 2675ffd83dbSDimitry Andric /// Get libdevice file for given architecture 268bdd1243dSDimitry Andric StringRef getLibDeviceFile(StringRef Gpu) const { 269bdd1243dSDimitry Andric auto Loc = LibDeviceMap.find(Gpu); 270bdd1243dSDimitry Andric if (Loc == LibDeviceMap.end()) 271bdd1243dSDimitry Andric return ""; 272bdd1243dSDimitry Andric return Loc->second; 2735ffd83dbSDimitry Andric } 2745ffd83dbSDimitry Andric 2755ffd83dbSDimitry Andric void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, 2765ffd83dbSDimitry Andric llvm::opt::ArgStringList &CC1Args) const; 2775ffd83dbSDimitry Andric 2785ffd83dbSDimitry Andric void detectDeviceLibrary(); 2795ffd83dbSDimitry Andric void detectHIPRuntime(); 2805ffd83dbSDimitry Andric 2815ffd83dbSDimitry Andric /// Get the values for --rocm-device-lib-path arguments 282bdd1243dSDimitry Andric ArrayRef<std::string> getRocmDeviceLibPathArg() const { 2835ffd83dbSDimitry Andric return RocmDeviceLibPathArg; 2845ffd83dbSDimitry Andric } 2855ffd83dbSDimitry Andric 2865ffd83dbSDimitry Andric /// Get the value for --rocm-path argument 2875ffd83dbSDimitry Andric StringRef getRocmPathArg() const { return RocmPathArg; } 2885ffd83dbSDimitry Andric 2895ffd83dbSDimitry Andric /// Get the value for --hip-version argument 2905ffd83dbSDimitry Andric StringRef getHIPVersionArg() const { return HIPVersionArg; } 2915ffd83dbSDimitry Andric 292bdd1243dSDimitry Andric StringRef getHIPVersion() const { return DetectedVersion; } 2935ffd83dbSDimitry Andric }; 2945ffd83dbSDimitry Andric 2955ffd83dbSDimitry Andric } // end namespace driver 2965ffd83dbSDimitry Andric } // end namespace clang 2975ffd83dbSDimitry Andric 2985ffd83dbSDimitry Andric #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 299