1 //===--- ROCm.h - ROCm installation detector --------------------*- 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 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 10 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 11 12 #include "clang/Basic/Cuda.h" 13 #include "clang/Basic/LLVM.h" 14 #include "clang/Driver/Driver.h" 15 #include "clang/Driver/Options.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/StringMap.h" 18 #include "llvm/Option/ArgList.h" 19 #include "llvm/Support/VersionTuple.h" 20 #include "llvm/TargetParser/Triple.h" 21 22 namespace clang { 23 namespace driver { 24 25 /// ABI version of device library. 26 struct DeviceLibABIVersion { 27 unsigned ABIVersion = 0; 28 DeviceLibABIVersion(unsigned V) : ABIVersion(V) {} 29 static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) { 30 if (CodeObjectVersion < 4) 31 CodeObjectVersion = 4; 32 return DeviceLibABIVersion(CodeObjectVersion * 100); 33 } 34 /// Whether ABI version bc file is requested. 35 /// ABIVersion is code object version multiplied by 100. Code object v4 36 /// and below works with ROCm 5.0 and below which does not have 37 /// abi_version_*.bc. Code object v5 requires abi_version_500.bc. 38 bool requiresLibrary() { return ABIVersion >= 500; } 39 std::string toString() { 40 assert(ABIVersion % 100 == 0 && "Not supported"); 41 return Twine(ABIVersion / 100).str(); 42 } 43 }; 44 45 /// A class to find a viable ROCM installation 46 /// TODO: Generalize to handle libclc. 47 class RocmInstallationDetector { 48 private: 49 struct ConditionalLibrary { 50 SmallString<0> On; 51 SmallString<0> Off; 52 53 bool isValid() const { return !On.empty() && !Off.empty(); } 54 55 StringRef get(bool Enabled) const { 56 assert(isValid()); 57 return Enabled ? On : Off; 58 } 59 }; 60 61 // Installation path candidate. 62 struct Candidate { 63 llvm::SmallString<0> Path; 64 bool StrictChecking; 65 // Release string for ROCm packages built with SPACK if not empty. The 66 // installation directories of ROCm packages built with SPACK follow the 67 // convention <package_name>-<rocm_release_string>-<hash>. 68 std::string SPACKReleaseStr; 69 70 bool isSPACK() const { return !SPACKReleaseStr.empty(); } 71 Candidate(std::string Path, bool StrictChecking = false, 72 StringRef SPACKReleaseStr = {}) 73 : Path(Path), StrictChecking(StrictChecking), 74 SPACKReleaseStr(SPACKReleaseStr.str()) {} 75 }; 76 77 const Driver &D; 78 bool HasHIPRuntime = false; 79 bool HasDeviceLibrary = false; 80 bool HasHIPStdParLibrary = false; 81 bool HasRocThrustLibrary = false; 82 bool HasRocPrimLibrary = false; 83 84 // Default version if not detected or specified. 85 const unsigned DefaultVersionMajor = 3; 86 const unsigned DefaultVersionMinor = 5; 87 const char *DefaultVersionPatch = "0"; 88 89 // The version string in Major.Minor.Patch format. 90 std::string DetectedVersion; 91 // Version containing major and minor. 92 llvm::VersionTuple VersionMajorMinor; 93 // Version containing patch. 94 std::string VersionPatch; 95 96 // ROCm path specified by --rocm-path. 97 StringRef RocmPathArg; 98 // ROCm device library paths specified by --rocm-device-lib-path. 99 std::vector<std::string> RocmDeviceLibPathArg; 100 // HIP runtime path specified by --hip-path. 101 StringRef HIPPathArg; 102 // HIP Standard Parallel Algorithm acceleration library specified by 103 // --hipstdpar-path 104 StringRef HIPStdParPathArg; 105 // rocThrust algorithm library specified by --hipstdpar-thrust-path 106 StringRef HIPRocThrustPathArg; 107 // rocPrim algorithm library specified by --hipstdpar-prim-path 108 StringRef HIPRocPrimPathArg; 109 // HIP version specified by --hip-version. 110 StringRef HIPVersionArg; 111 // Wheter -nogpulib is specified. 112 bool NoBuiltinLibs = false; 113 114 // Paths 115 SmallString<0> InstallPath; 116 SmallString<0> BinPath; 117 SmallString<0> LibPath; 118 SmallString<0> LibDevicePath; 119 SmallString<0> IncludePath; 120 SmallString<0> SharePath; 121 llvm::StringMap<std::string> LibDeviceMap; 122 123 // Libraries that are always linked. 124 SmallString<0> OCML; 125 SmallString<0> OCKL; 126 127 // Libraries that are always linked depending on the language 128 SmallString<0> OpenCL; 129 SmallString<0> HIP; 130 131 // Asan runtime library 132 SmallString<0> AsanRTL; 133 134 // Libraries swapped based on compile flags. 135 ConditionalLibrary WavefrontSize64; 136 ConditionalLibrary FiniteOnly; 137 ConditionalLibrary UnsafeMath; 138 ConditionalLibrary DenormalsAreZero; 139 ConditionalLibrary CorrectlyRoundedSqrt; 140 141 // Maps ABI version to library path. The version number is in the format of 142 // three digits as used in the ABI version library name. 143 std::map<unsigned, std::string> ABIVersionMap; 144 145 // Cache ROCm installation search paths. 146 SmallVector<Candidate, 4> ROCmSearchDirs; 147 bool PrintROCmSearchDirs; 148 bool Verbose; 149 150 bool allGenericLibsValid() const { 151 return !OCML.empty() && !OCKL.empty() && !OpenCL.empty() && !HIP.empty() && 152 WavefrontSize64.isValid() && FiniteOnly.isValid() && 153 UnsafeMath.isValid() && DenormalsAreZero.isValid() && 154 CorrectlyRoundedSqrt.isValid(); 155 } 156 157 void scanLibDevicePath(llvm::StringRef Path); 158 bool parseHIPVersionFile(llvm::StringRef V); 159 const SmallVectorImpl<Candidate> &getInstallationPathCandidates(); 160 161 /// Find the path to a SPACK package under the ROCm candidate installation 162 /// directory if the candidate is a SPACK ROCm candidate. \returns empty 163 /// string if the candidate is not SPACK ROCm candidate or the requested 164 /// package is not found. 165 llvm::SmallString<0> findSPACKPackage(const Candidate &Cand, 166 StringRef PackageName); 167 168 public: 169 RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, 170 const llvm::opt::ArgList &Args, 171 bool DetectHIPRuntime = true, 172 bool DetectDeviceLib = false); 173 174 /// Get file paths of default bitcode libraries common to AMDGPU based 175 /// toolchains. 176 llvm::SmallVector<std::string, 12> 177 getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, 178 StringRef LibDeviceFile, bool Wave64, bool DAZ, 179 bool FiniteOnly, bool UnsafeMathOpt, 180 bool FastRelaxedMath, bool CorrectSqrt, 181 DeviceLibABIVersion ABIVer, bool isOpenMP) const; 182 /// Check file paths of default bitcode libraries common to AMDGPU based 183 /// toolchains. \returns false if there are invalid or missing files. 184 bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, 185 DeviceLibABIVersion ABIVer) const; 186 187 /// Check whether we detected a valid HIP runtime. 188 bool hasHIPRuntime() const { return HasHIPRuntime; } 189 190 /// Check whether we detected a valid ROCm device library. 191 bool hasDeviceLibrary() const { return HasDeviceLibrary; } 192 193 /// Check whether we detected a valid HIP STDPAR Acceleration library. 194 bool hasHIPStdParLibrary() const { return HasHIPStdParLibrary; } 195 196 /// Print information about the detected ROCm installation. 197 void print(raw_ostream &OS) const; 198 199 /// Get the detected Rocm install's version. 200 // RocmVersion version() const { return Version; } 201 202 /// Get the detected Rocm installation path. 203 StringRef getInstallPath() const { return InstallPath; } 204 205 /// Get the detected path to Rocm's bin directory. 206 // StringRef getBinPath() const { return BinPath; } 207 208 /// Get the detected Rocm Include path. 209 StringRef getIncludePath() const { return IncludePath; } 210 211 /// Get the detected Rocm library path. 212 StringRef getLibPath() const { return LibPath; } 213 214 /// Get the detected Rocm device library path. 215 StringRef getLibDevicePath() const { return LibDevicePath; } 216 217 StringRef getOCMLPath() const { 218 assert(!OCML.empty()); 219 return OCML; 220 } 221 222 StringRef getOCKLPath() const { 223 assert(!OCKL.empty()); 224 return OCKL; 225 } 226 227 StringRef getOpenCLPath() const { 228 assert(!OpenCL.empty()); 229 return OpenCL; 230 } 231 232 StringRef getHIPPath() const { 233 assert(!HIP.empty()); 234 return HIP; 235 } 236 237 /// Returns empty string of Asan runtime library is not available. 238 StringRef getAsanRTLPath() const { return AsanRTL; } 239 240 StringRef getWavefrontSize64Path(bool Enabled) const { 241 return WavefrontSize64.get(Enabled); 242 } 243 244 StringRef getFiniteOnlyPath(bool Enabled) const { 245 return FiniteOnly.get(Enabled); 246 } 247 248 StringRef getUnsafeMathPath(bool Enabled) const { 249 return UnsafeMath.get(Enabled); 250 } 251 252 StringRef getDenormalsAreZeroPath(bool Enabled) const { 253 return DenormalsAreZero.get(Enabled); 254 } 255 256 StringRef getCorrectlyRoundedSqrtPath(bool Enabled) const { 257 return CorrectlyRoundedSqrt.get(Enabled); 258 } 259 260 StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const { 261 auto Loc = ABIVersionMap.find(ABIVer.ABIVersion); 262 if (Loc == ABIVersionMap.end()) 263 return StringRef(); 264 return Loc->second; 265 } 266 267 /// Get libdevice file for given architecture 268 StringRef getLibDeviceFile(StringRef Gpu) const { 269 auto Loc = LibDeviceMap.find(Gpu); 270 if (Loc == LibDeviceMap.end()) 271 return ""; 272 return Loc->second; 273 } 274 275 void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, 276 llvm::opt::ArgStringList &CC1Args) const; 277 278 void detectDeviceLibrary(); 279 void detectHIPRuntime(); 280 281 /// Get the values for --rocm-device-lib-path arguments 282 ArrayRef<std::string> getRocmDeviceLibPathArg() const { 283 return RocmDeviceLibPathArg; 284 } 285 286 /// Get the value for --rocm-path argument 287 StringRef getRocmPathArg() const { return RocmPathArg; } 288 289 /// Get the value for --hip-version argument 290 StringRef getHIPVersionArg() const { return HIPVersionArg; } 291 292 StringRef getHIPVersion() const { return DetectedVersion; } 293 }; 294 295 } // end namespace driver 296 } // end namespace clang 297 298 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H 299