11#include "clang/Config/config.h"
18#include "llvm/ADT/SmallSet.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Support/Error.h"
22#include "llvm/Support/LineIterator.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/Process.h"
25#include "llvm/Support/VirtualFileSystem.h"
26#include "llvm/TargetParser/AMDGPUTargetParser.h"
27#include "llvm/TargetParser/Host.h"
29#include <system_error>
37RocmInstallationDetector::CommonBitcodeLibsPreferences::
38 CommonBitcodeLibsPreferences(
const Driver &D,
39 const llvm::opt::ArgList &DriverArgs,
42 const bool NeedsASanRT)
45 const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
46 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
50 const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
52 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
53 options::OPT_mno_wavefrontsize64,
false);
60 const bool DefaultDAZ =
61 (Kind == llvm::AMDGPU::GK_NONE)
63 : !((ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_FMA_F32) &&
64 (ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_DENORMAL_F32));
67 DAZ = IsKnownOffloading
68 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
69 options::OPT_fno_gpu_flush_denormals_to_zero,
71 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
73 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
74 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
75 options::OPT_fno_finite_math_only,
false);
78 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
79 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
80 options::OPT_fno_unsafe_math_optimizations,
false);
82 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
83 DriverArgs.hasFlag(options::OPT_ffast_math,
84 options::OPT_fno_fast_math,
false);
88 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
89 options::OPT_fno_gpu_sanitize,
true) &&
93void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
94 assert(!Path.empty());
96 const StringRef Suffix(
".bc");
97 const StringRef Suffix2(
".amdgcn.bc");
100 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
101 !EC && LI != LE; LI = LI.increment(EC)) {
102 StringRef FilePath = LI->path();
103 StringRef
FileName = llvm::sys::path::filename(FilePath);
109 BaseName =
FileName.drop_back(Suffix2.size());
110 else if (
FileName.ends_with(Suffix))
111 BaseName =
FileName.drop_back(Suffix.size());
113 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
114 if (BaseName ==
"ocml") {
116 }
else if (BaseName ==
"ockl") {
118 }
else if (BaseName ==
"opencl") {
120 }
else if (BaseName ==
"asanrtl") {
122 }
else if (BaseName ==
"oclc_finite_only_off") {
123 FiniteOnly.Off = FilePath;
124 }
else if (BaseName ==
"oclc_finite_only_on") {
125 FiniteOnly.On = FilePath;
126 }
else if (BaseName ==
"oclc_unsafe_math_on") {
127 UnsafeMath.On = FilePath;
128 }
else if (BaseName ==
"oclc_unsafe_math_off") {
129 UnsafeMath.Off = FilePath;
130 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
131 WavefrontSize64.On = FilePath;
132 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
133 WavefrontSize64.Off = FilePath;
134 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
135 unsigned ABIVersionNumber;
136 if (BaseName.drop_front(ABIVersionPrefix.size())
137 .getAsInteger(0, ABIVersionNumber))
139 ABIVersionMap[ABIVersionNumber] = FilePath.str();
143 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
144 if (!BaseName.starts_with(DeviceLibPrefix))
147 StringRef IsaVersionNumber =
148 BaseName.drop_front(DeviceLibPrefix.size());
150 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
152 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
159bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
160 SmallVector<StringRef, 4> VersionParts;
161 V.split(VersionParts,
'\n');
162 unsigned Major = ~0U;
163 unsigned Minor = ~0U;
164 for (
auto Part : VersionParts) {
165 auto Splits = Part.rtrim().split(
'=');
166 if (Splits.first ==
"HIP_VERSION_MAJOR") {
167 if (Splits.second.getAsInteger(0, Major))
169 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
170 if (Splits.second.getAsInteger(0, Minor))
172 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
173 VersionPatch = Splits.second.str();
175 if (Major == ~0U || Minor == ~0U)
177 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
179 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
185const SmallVectorImpl<RocmInstallationDetector::Candidate> &
186RocmInstallationDetector::getInstallationPathCandidates() {
189 if (!ROCmSearchDirs.empty())
190 return ROCmSearchDirs;
192 auto DoPrintROCmSearchDirs = [&]() {
193 if (PrintROCmSearchDirs)
194 for (
auto Cand : ROCmSearchDirs) {
195 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
201 if (!RocmPathArg.empty()) {
202 ROCmSearchDirs.emplace_back(RocmPathArg.str());
203 DoPrintROCmSearchDirs();
204 return ROCmSearchDirs;
205 }
else if (std::optional<std::string> RocmPathEnv =
206 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
207 if (!RocmPathEnv->empty()) {
208 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
209 DoPrintROCmSearchDirs();
210 return ROCmSearchDirs;
215 StringRef InstallDir = D.Dir;
220 auto DeduceROCmPath = [](StringRef ClangPath) {
222 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
223 StringRef ParentName = llvm::sys::path::filename(ParentDir);
226 if (ParentName ==
"bin") {
227 ParentDir = llvm::sys::path::parent_path(ParentDir);
228 ParentName = llvm::sys::path::filename(ParentDir);
233 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
234 ParentDir = llvm::sys::path::parent_path(ParentDir);
235 ParentName = llvm::sys::path::filename(ParentDir);
239 if (ParentName ==
"lib")
240 ParentDir = llvm::sys::path::parent_path(ParentDir);
243 return Candidate(ParentDir.str(),
true);
248 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
252 llvm::SmallString<256> RealClangPath;
253 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
254 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
255 if (ParentPath != InstallDir)
256 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
259 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
260 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
261 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
262 if (RealClangRoot != ClangRoot)
263 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
264 ROCmSearchDirs.emplace_back(D.ResourceDir,
267 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
272 std::string LatestROCm;
273 llvm::VersionTuple LatestVer;
275 auto GetROCmVersion = [](StringRef DirName) {
276 llvm::VersionTuple
V;
277 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
280 llvm::replace(VerStr,
'-',
'.');
284 for (llvm::vfs::directory_iterator
285 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
287 File != FileEnd && !EC;
File.increment(EC)) {
288 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
291 if (LatestROCm.empty()) {
293 LatestVer = GetROCmVersion(LatestROCm);
296 auto Ver = GetROCmVersion(
FileName);
297 if (LatestVer < Ver) {
302 if (!LatestROCm.empty())
303 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
306 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
308 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
311 DoPrintROCmSearchDirs();
312 return ROCmSearchDirs;
316 const Driver &D,
const llvm::Triple &HostTriple,
317 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
319 Verbose = Args.hasArg(options::OPT_v);
320 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
321 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
322 RocmDeviceLibPathArg =
323 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
324 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
325 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
326 HasHIPStdParLibrary =
327 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
328 "/hipstdpar_lib.hpp");
329 HIPRocThrustPathArg =
330 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
331 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
332 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
333 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
334 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
335 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
337 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
338 HIPVersionArg = A->getValue();
339 unsigned Major = ~0U;
340 unsigned Minor = ~0U;
341 SmallVector<StringRef, 3> Parts;
342 HIPVersionArg.split(Parts,
'.');
344 Parts[0].getAsInteger(0, Major);
345 if (Parts.size() > 1)
346 Parts[1].getAsInteger(0, Minor);
347 if (Parts.size() > 2)
348 VersionPatch = Parts[2].str();
349 if (VersionPatch.empty())
351 if (Major != ~0U && Minor == ~0U)
353 if (Major == ~0U || Minor == ~0U)
354 D.Diag(diag::err_drv_invalid_value)
355 << A->getAsString(Args) << HIPVersionArg;
357 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
359 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
361 VersionPatch = DefaultVersionPatch;
363 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
364 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
365 Twine(DefaultVersionMinor) +
"." + VersionPatch)
369 if (DetectHIPRuntime)
374 assert(LibDevicePath.empty());
376 if (!RocmDeviceLibPathArg.empty())
377 LibDevicePath = RocmDeviceLibPathArg.back();
378 else if (std::optional<std::string> LibPathEnv =
379 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
380 LibDevicePath = std::move(*LibPathEnv);
382 auto &FS = D.getVFS();
383 if (!LibDevicePath.empty()) {
387 if (!FS.exists(LibDevicePath))
390 scanLibDevicePath(LibDevicePath);
391 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
396 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
397 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
398 if (CheckLibDevice && !FS.exists(Path))
401 scanLibDevicePath(Path);
403 if (!NoBuiltinLibs) {
405 if (!allGenericLibsValid())
410 if (LibDeviceMap.empty())
417 LibDevicePath = D.ResourceDir;
418 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
419 "amdgcn",
"bitcode");
420 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
421 if (HasDeviceLibrary)
426 auto &ROCmDirs = getInstallationPathCandidates();
427 for (
const auto &Candidate : ROCmDirs) {
428 LibDevicePath = Candidate.Path;
429 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
430 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
431 if (HasDeviceLibrary)
438 if (!HIPPathArg.empty())
439 HIPSearchDirs.emplace_back(HIPPathArg.str());
440 else if (std::optional<std::string> HIPPathEnv =
441 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
442 if (!HIPPathEnv->empty())
443 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
445 if (HIPSearchDirs.empty())
446 HIPSearchDirs.append(getInstallationPathCandidates());
447 auto &FS = D.getVFS();
449 for (
const auto &Candidate : HIPSearchDirs) {
450 InstallPath = Candidate.Path;
451 if (InstallPath.empty() || !FS.exists(InstallPath))
454 BinPath = InstallPath;
455 llvm::sys::path::append(BinPath,
"bin");
456 IncludePath = InstallPath;
457 llvm::sys::path::append(IncludePath,
"include");
458 LibPath = InstallPath;
459 llvm::sys::path::append(LibPath,
"lib");
460 SharePath = InstallPath;
461 llvm::sys::path::append(SharePath,
"share");
464 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
465 llvm::sys::path::append(ParentSharePath,
"share");
468 const Twine &c =
"",
const Twine &d =
"") {
470 llvm::sys::path::append(newpath, a, b, c, d);
474 std::vector<SmallString<0>> VersionFilePaths = {
475 Append(SharePath,
"hip",
"version"),
476 InstallPath != D.SysRoot +
"/usr/local"
477 ?
Append(ParentSharePath,
"hip",
"version")
479 Append(BinPath,
".hipVersion")};
481 for (
const auto &VersionFilePath : VersionFilePaths) {
482 if (VersionFilePath.empty())
484 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
485 FS.getBufferForFile(VersionFilePath);
488 if (HIPVersionArg.empty() && VersionFile)
489 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
492 HasHIPRuntime =
true;
497 if (!Candidate.StrictChecking) {
498 HasHIPRuntime =
true;
502 HasHIPRuntime =
false;
507 OS <<
"Found HIP installation: " << InstallPath <<
", version "
508 << DetectedVersion <<
'\n';
512 ArgStringList &CC1Args)
const {
513 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
514 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
515 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
517 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
532 if (UsesRuntimeWrapper)
533 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
534 CC1Args.push_back(
"-internal-isystem");
535 CC1Args.push_back(DriverArgs.MakeArgString(P));
538 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
540 auto &FS = D.getVFS();
543 if (!HIPStdParPathArg.empty() ||
544 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
545 D.Diag(diag::err_drv_no_hipstdpar_lib);
548 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
549 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
552 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
553 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
556 const char *ThrustPath;
557 if (HasRocThrustLibrary)
558 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
560 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
562 const char *HIPStdParPath;
564 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
566 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
567 "/system/hip/hipstdpar");
569 const char *PrimPath;
570 if (HasRocPrimLibrary)
571 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
573 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
575 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
576 "-idirafter", HIPStdParPath,
"-include",
577 "hipstdpar_lib.hpp"});
580 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
589 D.Diag(diag::err_drv_no_hip_runtime);
593 CC1Args.push_back(
"-idirafter");
595 if (UsesRuntimeWrapper)
596 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
605 const char *LinkingOutput)
const {
607 ArgStringList CmdArgs;
608 if (!Args.hasArg(options::OPT_r)) {
609 CmdArgs.push_back(
"--no-undefined");
610 CmdArgs.push_back(
"-shared");
613 if (Args.hasArg(options::OPT_hipstdpar))
614 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
619 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
620 CmdArgs.push_back(Args.MakeArgString(
621 "-plugin-opt=mcpu=" +
623 Args.getLastArgValue(options::OPT_mcpu_EQ))));
627 Args.AddAllArgs(CmdArgs, options::OPT_L);
631 std::vector<StringRef> Features;
634 if (!Features.empty()) {
636 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
642 if (Args.hasArg(options::OPT_stdlib))
643 CmdArgs.append({
"-lc",
"-lm"});
644 if (Args.hasArg(options::OPT_startfiles)) {
645 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
647 IncludePath =
"/lib";
649 llvm::sys::path::append(P,
"crt1.o");
650 CmdArgs.push_back(Args.MakeArgString(P));
653 CmdArgs.push_back(
"-o");
655 C.addCommand(std::make_unique<Command>(
657 CmdArgs, Inputs, Output));
661 const llvm::Triple &Triple,
662 const llvm::opt::ArgList &Args,
663 std::vector<StringRef> &Features) {
664 if (Args.hasFlag(options::OPT_mwavefrontsize64,
665 options::OPT_mno_wavefrontsize64,
false))
666 Features.push_back(
"+wavefrontsize64");
668 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
669 options::OPT_mno_amdgpu_precise_memory_op,
false))
670 Features.push_back(
"+precise-memory");
673 options::OPT_m_amdgpu_Features_Group);
681 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}) {
682 loadMultilibsFromYAML(Args, D);
700 DAL =
new DerivedArgList(Args.getBaseArgs());
709 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
710 DAL->eraseArg(options::OPT_march_EQ);
711 if (!DAL->hasArg(options::OPT_mcpu_EQ))
712 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
718 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
719 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
720 DAL->eraseArg(options::OPT_mcpu_EQ);
724 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
726 auto &GPUs = *GPUsOrErr;
727 if (!llvm::all_equal(GPUs))
729 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
730 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
731 Args.MakeArgString(GPUs.front()));
736 DAL->eraseArg(options::OPT_mcpu_EQ);
737 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
747 auto XnackIt = FeatureMap.find(
"xnack");
748 if (XnackIt != FeatureMap.end()) {
749 DAL->AddFlagArg(
nullptr,
750 Opts.getOption(XnackIt->second ? options::OPT_mxnack
751 : options::OPT_mno_xnack));
754 auto SrameccIt = FeatureMap.find(
"sramecc");
755 if (SrameccIt != FeatureMap.end()) {
756 DAL->AddFlagArg(
nullptr, Opts.getOption(SrameccIt->second
757 ? options::OPT_msramecc
758 : options::OPT_mno_sramecc));
762 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
766 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
769 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
771 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
779 llvm::AMDGPU::GPUKind Kind) {
782 if (Kind == llvm::AMDGPU::GK_NONE)
785 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
789 const bool BothDenormAndFMAFast =
790 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
791 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
792 return !BothDenormAndFMAFast;
796 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
797 const llvm::fltSemantics *FPType)
const {
799 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
800 return llvm::DenormalMode::getIEEE();
807 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
808 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
809 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
810 options::OPT_fno_gpu_flush_denormals_to_zero,
812 return llvm::DenormalMode::getPreserveSign();
814 return llvm::DenormalMode::getIEEE();
817 const StringRef GpuArch =
getGPUArch(DriverArgs);
818 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
822 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
827 return DAZ ? llvm::DenormalMode::getPreserveSign() :
828 llvm::DenormalMode::getIEEE();
832 llvm::AMDGPU::GPUKind Kind) {
833 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
834 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
836 return !HasWave32 || DriverArgs.hasFlag(
837 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
845 if (Triple.getEnvironment() != llvm::Triple::LLVM)
852 DerivedArgList *DAL =
856 for (Arg *A : Args) {
858 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
860 bool IsExplicitDevice =
861 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
863 ? diag::err_drv_unsupported_option_for_target
864 : diag::warn_drv_unsupported_option_for_target)
865 << A->getAsString(Args) <<
getTriple().str();
873 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
878 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
879 options::OPT_fvisibility_ms_compat) &&
881 CC1Args.push_back(
"-fvisibility=hidden");
882 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
896 !DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
897 CC1Args.push_back(
"-disable-llvm-optzns");
899 if (DriverArgs.hasArg(options::OPT_hipstdpar))
900 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
909 CC1Args.push_back(
"-Werror=atomic-alignment");
913 ArgStringList &CC1Args)
const {
914 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
915 DriverArgs.hasArg(options::OPT_nostdlibinc))
924 llvm::sys::path::append(Dir, M.includeSuffix());
937 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
942 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
943 if (TargetID.empty())
946 llvm::StringMap<bool> FeatureMap;
948 if (!OptionalGpuArch)
949 return {TargetID.str(), std::nullopt, std::nullopt};
951 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
957 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
959 << *PTID.OptionalTargetID;
968 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
969 Program = A->getValue();
975 return StdoutOrErr.takeError();
978 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
980 GPUArchs.push_back(
Arch.str());
982 if (GPUArchs.empty())
983 return llvm::createStringError(std::error_code(),
984 "No AMD GPU detected in the system");
986 return std::move(GPUArchs);
990 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
993 DeviceOffloadingKind);
998 DriverArgs.hasArg(options::OPT_nostdlib))
1001 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1013 if (TT.getEnvironment() == llvm::Triple::LLVM)
1019 StringRef TargetID =
1020 BA ? BA.
ArchName : DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1027 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1036 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
1040 for (
auto [BCFile, Internalize] : BCLibs) {
1042 CC1Args.push_back(
"-mlink-builtin-bitcode");
1044 CC1Args.push_back(
"-mlink-bitcode-file");
1045 CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
1050 StringRef GPUArch, StringRef LibDeviceFile,
1053 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1056 if (LibDeviceFile.empty()) {
1057 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1064 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1066 D.Diag(diag::err_drv_no_rocm_device_lib)
1067 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1075 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1077 const bool NeedsASanRT)
const {
1080 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1081 DeviceOffloadingKind, NeedsASanRT};
1084 bool Internalize =
true) {
1085 if (!BCLib.
Path.empty()) {
1087 BCLibs.emplace_back(BCLib);
1090 auto AddSanBCLibs = [&]() {
1099 else if (Pref.GPUSan && Pref.IsOpenMP)
1104 AddBCLib(LibDeviceFile);
1106 if (!ABIVerPath.empty())
1107 AddBCLib(ABIVerPath);
1114 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1116 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1117 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1127 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1135 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1136 : llvm::AMDGPU::parseArchR600(Processor);
1137 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1138 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1141 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1142 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1147 llvm::StringMap<bool> FeatureMap;
1148 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1149 if (!OptionalGpuArch)
1151 auto Loc = FeatureMap.find(
"xnack");
1152 return (Loc != FeatureMap.end() && Loc->second);
1163 SupportedMask |= SanitizerKind::Address;
1165 return SupportedMask;
1171 if ((Kinds & SanitizerKind::Address) && BA &&
static StringRef getTriple(const Command &Job)
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)
BoundArch getOffloadingArch() const
OffloadKind getOffloadingDeviceKind() const
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > executeProgram(llvm::ArrayRef< llvm::StringRef > Args) const
DiagnosticBuilder Diag(unsigned DiagID) const
const llvm::opt::OptTable & getOpts() const
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
StringRef getIncludePath() const
Get the detected path to Rocm's bin directory.
StringRef getUnsafeMathPath(bool Enabled) const
StringRef getOCMLPath() const
StringRef getAsanRTLPath() const
Returns empty string of Asan runtime library is not available.
RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args, bool DetectHIPRuntime=true)
StringRef getOCKLPath() const
StringRef getFiniteOnlyPath(bool Enabled) const
bool hasDeviceLibrary() const
Check whether we detected a valid ROCm device library.
bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, DeviceLibABIVersion ABIVer) const
Check file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPStdParLibrary() const
Check whether we detected a valid HIP STDPAR Acceleration library.
StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const
llvm::SmallVector< ToolChain::BitCodeLibraryInfo, 12 > getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, StringRef GPUArch, const Action::OffloadKind DeviceOffloadingKind, const bool NeedsASanRT) const
Get file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPRuntime() const
Check whether we detected a valid HIP runtime.
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
void detectDeviceLibrary()
StringRef getWavefrontSize64Path(bool Enabled) const
void print(raw_ostream &OS) const
Print information about the detected ROCm installation.
SmallVector< InputInfo, 4 > InputInfoList
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
std::optional< llvm::StringRef > parseTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch, llvm::StringMap< bool > *FeatureMap)
Parse a target ID to get processor and feature map.
llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch)
Get processor name from target ID.
Diagnostic wrappers for TextAPI types for error reporting.
Represents a bound architecture for offload / multiple architecture compilation.
ABI version of device library.
unsigned getAsCodeObjectVersion() const
static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion)
bool requiresLibrary()
Whether ABI version bc file is requested.
static constexpr ResponseFileSupport AtFileCurCP()