12#include "clang/Config/config.h"
19#include "llvm/ADT/SmallSet.h"
20#include "llvm/ADT/StringExtras.h"
21#include "llvm/Option/ArgList.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/LineIterator.h"
24#include "llvm/Support/Path.h"
25#include "llvm/Support/Process.h"
26#include "llvm/Support/VirtualFileSystem.h"
27#include "llvm/TargetParser/AMDGPUTargetParser.h"
28#include "llvm/TargetParser/Host.h"
30#include <system_error>
38RocmInstallationDetector::CommonBitcodeLibsPreferences::
39 CommonBitcodeLibsPreferences(
const Driver &D,
40 const llvm::opt::ArgList &DriverArgs,
43 const bool NeedsASanRT)
46 const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
47 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
51 const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
53 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
54 options::OPT_mno_wavefrontsize64,
false);
61 const bool DefaultDAZ =
62 (Kind == llvm::AMDGPU::GK_NONE)
64 : !((ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_FMA_F32) &&
65 (ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_DENORMAL_F32));
68 DAZ = IsKnownOffloading
69 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
70 options::OPT_fno_gpu_flush_denormals_to_zero,
72 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
74 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
75 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
76 options::OPT_fno_finite_math_only,
false);
79 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
80 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
81 options::OPT_fno_unsafe_math_optimizations,
false);
83 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
84 DriverArgs.hasFlag(options::OPT_ffast_math,
85 options::OPT_fno_fast_math,
false);
89 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
90 options::OPT_fno_gpu_sanitize,
true) &&
94void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
95 assert(!Path.empty());
97 const StringRef Suffix(
".bc");
98 const StringRef Suffix2(
".amdgcn.bc");
101 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
102 !EC && LI != LE; LI = LI.increment(EC)) {
103 StringRef FilePath = LI->path();
104 StringRef
FileName = llvm::sys::path::filename(FilePath);
110 BaseName =
FileName.drop_back(Suffix2.size());
111 else if (
FileName.ends_with(Suffix))
112 BaseName =
FileName.drop_back(Suffix.size());
114 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
115 if (BaseName ==
"ocml") {
117 }
else if (BaseName ==
"ockl") {
119 }
else if (BaseName ==
"opencl") {
121 }
else if (BaseName ==
"asanrtl") {
123 }
else if (BaseName ==
"oclc_finite_only_off") {
124 FiniteOnly.Off = FilePath;
125 }
else if (BaseName ==
"oclc_finite_only_on") {
126 FiniteOnly.On = FilePath;
127 }
else if (BaseName ==
"oclc_unsafe_math_on") {
128 UnsafeMath.On = FilePath;
129 }
else if (BaseName ==
"oclc_unsafe_math_off") {
130 UnsafeMath.Off = FilePath;
131 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
132 WavefrontSize64.On = FilePath;
133 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
134 WavefrontSize64.Off = FilePath;
135 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
136 unsigned ABIVersionNumber;
137 if (BaseName.drop_front(ABIVersionPrefix.size())
138 .getAsInteger(0, ABIVersionNumber))
140 ABIVersionMap[ABIVersionNumber] = FilePath.str();
144 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
145 if (!BaseName.starts_with(DeviceLibPrefix))
148 StringRef IsaVersionNumber =
149 BaseName.drop_front(DeviceLibPrefix.size());
151 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
153 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
160bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
161 SmallVector<StringRef, 4> VersionParts;
162 V.split(VersionParts,
'\n');
163 unsigned Major = ~0U;
164 unsigned Minor = ~0U;
165 for (
auto Part : VersionParts) {
166 auto Splits = Part.rtrim().split(
'=');
167 if (Splits.first ==
"HIP_VERSION_MAJOR") {
168 if (Splits.second.getAsInteger(0, Major))
170 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
171 if (Splits.second.getAsInteger(0, Minor))
173 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
174 VersionPatch = Splits.second.str();
176 if (Major == ~0U || Minor == ~0U)
178 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
180 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
186const SmallVectorImpl<RocmInstallationDetector::Candidate> &
187RocmInstallationDetector::getInstallationPathCandidates() {
190 if (!ROCmSearchDirs.empty())
191 return ROCmSearchDirs;
193 auto DoPrintROCmSearchDirs = [&]() {
194 if (PrintROCmSearchDirs)
195 for (
auto Cand : ROCmSearchDirs) {
196 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
202 if (!RocmPathArg.empty()) {
203 ROCmSearchDirs.emplace_back(RocmPathArg.str());
204 DoPrintROCmSearchDirs();
205 return ROCmSearchDirs;
206 }
else if (std::optional<std::string> RocmPathEnv =
207 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
208 if (!RocmPathEnv->empty()) {
209 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
210 DoPrintROCmSearchDirs();
211 return ROCmSearchDirs;
216 StringRef InstallDir = D.Dir;
221 auto DeduceROCmPath = [](StringRef ClangPath) {
223 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
224 StringRef ParentName = llvm::sys::path::filename(ParentDir);
227 if (ParentName ==
"bin") {
228 ParentDir = llvm::sys::path::parent_path(ParentDir);
229 ParentName = llvm::sys::path::filename(ParentDir);
234 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
235 ParentDir = llvm::sys::path::parent_path(ParentDir);
236 ParentName = llvm::sys::path::filename(ParentDir);
240 if (ParentName ==
"lib")
241 ParentDir = llvm::sys::path::parent_path(ParentDir);
244 return Candidate(ParentDir.str(),
true);
249 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
253 llvm::SmallString<256> RealClangPath;
254 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
255 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
256 if (ParentPath != InstallDir)
257 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
260 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
261 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
262 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
263 if (RealClangRoot != ClangRoot)
264 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
265 ROCmSearchDirs.emplace_back(D.ResourceDir,
268 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
273 std::string LatestROCm;
274 llvm::VersionTuple LatestVer;
276 auto GetROCmVersion = [](StringRef DirName) {
277 llvm::VersionTuple
V;
278 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
281 llvm::replace(VerStr,
'-',
'.');
285 for (llvm::vfs::directory_iterator
286 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
288 File != FileEnd && !EC;
File.increment(EC)) {
289 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
292 if (LatestROCm.empty()) {
294 LatestVer = GetROCmVersion(LatestROCm);
297 auto Ver = GetROCmVersion(
FileName);
298 if (LatestVer < Ver) {
303 if (!LatestROCm.empty())
304 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
307 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
309 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
312 DoPrintROCmSearchDirs();
313 return ROCmSearchDirs;
317 const Driver &D,
const llvm::Triple &HostTriple,
318 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
320 Verbose = Args.hasArg(options::OPT_v);
321 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
322 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
323 RocmDeviceLibPathArg =
324 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
325 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
326 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
327 HasHIPStdParLibrary =
328 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
329 "/hipstdpar_lib.hpp");
330 HIPRocThrustPathArg =
331 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
332 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
333 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
334 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
335 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
336 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
338 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
339 HIPVersionArg = A->getValue();
340 unsigned Major = ~0U;
341 unsigned Minor = ~0U;
342 SmallVector<StringRef, 3> Parts;
343 HIPVersionArg.split(Parts,
'.');
345 Parts[0].getAsInteger(0, Major);
346 if (Parts.size() > 1)
347 Parts[1].getAsInteger(0, Minor);
348 if (Parts.size() > 2)
349 VersionPatch = Parts[2].str();
350 if (VersionPatch.empty())
352 if (Major != ~0U && Minor == ~0U)
354 if (Major == ~0U || Minor == ~0U)
355 D.Diag(diag::err_drv_invalid_value)
356 << A->getAsString(Args) << HIPVersionArg;
358 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
360 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
362 VersionPatch = DefaultVersionPatch;
364 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
365 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
366 Twine(DefaultVersionMinor) +
"." + VersionPatch)
370 if (DetectHIPRuntime)
375 assert(LibDevicePath.empty());
377 if (!RocmDeviceLibPathArg.empty())
378 LibDevicePath = RocmDeviceLibPathArg.back();
379 else if (std::optional<std::string> LibPathEnv =
380 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
381 LibDevicePath = std::move(*LibPathEnv);
383 auto &FS = D.getVFS();
384 if (!LibDevicePath.empty()) {
388 if (!FS.exists(LibDevicePath))
391 scanLibDevicePath(LibDevicePath);
392 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
397 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
398 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
399 if (CheckLibDevice && !FS.exists(Path))
402 scanLibDevicePath(Path);
404 if (!NoBuiltinLibs) {
406 if (!allGenericLibsValid())
411 if (LibDeviceMap.empty())
418 LibDevicePath = D.ResourceDir;
419 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
420 "amdgcn",
"bitcode");
421 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
422 if (HasDeviceLibrary)
427 auto &ROCmDirs = getInstallationPathCandidates();
428 for (
const auto &Candidate : ROCmDirs) {
429 LibDevicePath = Candidate.Path;
430 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
431 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
432 if (HasDeviceLibrary)
439 if (!HIPPathArg.empty())
440 HIPSearchDirs.emplace_back(HIPPathArg.str());
441 else if (std::optional<std::string> HIPPathEnv =
442 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
443 if (!HIPPathEnv->empty())
444 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
446 if (HIPSearchDirs.empty())
447 HIPSearchDirs.append(getInstallationPathCandidates());
448 auto &FS = D.getVFS();
450 for (
const auto &Candidate : HIPSearchDirs) {
451 InstallPath = Candidate.Path;
452 if (InstallPath.empty() || !FS.exists(InstallPath))
455 BinPath = InstallPath;
456 llvm::sys::path::append(BinPath,
"bin");
457 IncludePath = InstallPath;
458 llvm::sys::path::append(IncludePath,
"include");
459 LibPath = InstallPath;
460 llvm::sys::path::append(LibPath,
"lib");
461 SharePath = InstallPath;
462 llvm::sys::path::append(SharePath,
"share");
465 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
466 llvm::sys::path::append(ParentSharePath,
"share");
469 const Twine &c =
"",
const Twine &d =
"") {
471 llvm::sys::path::append(newpath, a, b, c, d);
475 std::vector<SmallString<0>> VersionFilePaths = {
476 Append(SharePath,
"hip",
"version"),
477 InstallPath != D.SysRoot +
"/usr/local"
478 ?
Append(ParentSharePath,
"hip",
"version")
480 Append(BinPath,
".hipVersion")};
482 for (
const auto &VersionFilePath : VersionFilePaths) {
483 if (VersionFilePath.empty())
485 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
486 FS.getBufferForFile(VersionFilePath);
489 if (HIPVersionArg.empty() && VersionFile)
490 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
493 HasHIPRuntime =
true;
498 if (!Candidate.StrictChecking) {
499 HasHIPRuntime =
true;
503 HasHIPRuntime =
false;
508 OS <<
"Found HIP installation: " << InstallPath <<
", version "
509 << DetectedVersion <<
'\n';
513 ArgStringList &CC1Args)
const {
514 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
515 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
516 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
518 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
533 if (UsesRuntimeWrapper)
534 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
535 CC1Args.push_back(
"-internal-isystem");
536 CC1Args.push_back(DriverArgs.MakeArgString(P));
539 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
541 auto &FS = D.getVFS();
544 if (!HIPStdParPathArg.empty() ||
545 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
546 D.Diag(diag::err_drv_no_hipstdpar_lib);
549 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
550 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
553 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
554 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
557 const char *ThrustPath;
558 if (HasRocThrustLibrary)
559 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
561 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
563 const char *HIPStdParPath;
565 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
567 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
568 "/system/hip/hipstdpar");
570 const char *PrimPath;
571 if (HasRocPrimLibrary)
572 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
574 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
576 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
577 "-idirafter", HIPStdParPath,
"-include",
578 "hipstdpar_lib.hpp"});
581 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
590 D.Diag(diag::err_drv_no_hip_runtime);
594 CC1Args.push_back(
"-idirafter");
596 if (UsesRuntimeWrapper)
597 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
606 const char *LinkingOutput)
const {
608 ArgStringList CmdArgs;
609 if (!Args.hasArg(options::OPT_r)) {
610 CmdArgs.push_back(
"--no-undefined");
611 CmdArgs.push_back(
"-shared");
614 if (Args.hasArg(options::OPT_hipstdpar))
615 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
620 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
621 CmdArgs.push_back(Args.MakeArgString(
622 "-plugin-opt=mcpu=" +
624 Args.getLastArgValue(options::OPT_mcpu_EQ))));
628 Args.AddAllArgs(CmdArgs, options::OPT_L);
632 std::vector<StringRef> Features;
635 if (!Features.empty()) {
637 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
643 if (Args.hasArg(options::OPT_stdlib))
644 CmdArgs.append({
"-lc",
"-lm"});
645 if (Args.hasArg(options::OPT_startfiles)) {
646 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
648 IncludePath =
"/lib";
650 llvm::sys::path::append(P,
"crt1.o");
651 CmdArgs.push_back(Args.MakeArgString(P));
654 CmdArgs.push_back(
"-o");
656 C.addCommand(std::make_unique<Command>(
658 CmdArgs, Inputs, Output));
662 const llvm::Triple &Triple,
663 const llvm::opt::ArgList &Args,
664 std::vector<StringRef> &Features) {
665 if (Args.hasFlag(options::OPT_mwavefrontsize64,
666 options::OPT_mno_wavefrontsize64,
false))
667 Features.push_back(
"+wavefrontsize64");
669 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
670 options::OPT_mno_amdgpu_precise_memory_op,
false))
671 Features.push_back(
"+precise-memory");
674 options::OPT_m_amdgpu_Features_Group);
679 const ArgList &Args,
const ToolChain *HostTC_,
684 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
686 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
687 loadMultilibsFromYAML(Args, D);
695 if (Triple.getOS() == llvm::Triple::AMDHSA &&
696 Triple.getEnvironment() != llvm::Triple::LLVM)
697 RocmInstallation->detectDeviceLibrary();
700 getProgramPaths().push_back(getDriver().Dir);
715 DAL =
new DerivedArgList(Args.getBaseArgs());
724 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
725 DAL->eraseArg(options::OPT_march_EQ);
726 if (!DAL->hasArg(options::OPT_mcpu_EQ))
727 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
733 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
734 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
735 DAL->eraseArg(options::OPT_mcpu_EQ);
739 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
741 auto &GPUs = *GPUsOrErr;
742 if (!llvm::all_equal(GPUs))
744 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
745 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
746 Args.MakeArgString(GPUs.front()));
751 DAL->eraseArg(options::OPT_mcpu_EQ);
752 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
763 auto XnackIt = FeatureMap.find(
"xnack");
764 if (XnackIt != FeatureMap.end()) {
765 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
766 ? options::OPT_mxnack
767 : options::OPT_mno_xnack));
770 auto SrameccIt = FeatureMap.find(
"sramecc");
771 if (SrameccIt != FeatureMap.end()) {
772 DAL->AddFlagArg(
nullptr,
773 Opts.getOption(SrameccIt->second
774 ? options::OPT_msramecc
775 : options::OPT_mno_sramecc));
781 for (Arg *A : Args) {
783 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
785 bool IsExplicitDevice =
786 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
788 ? diag::err_drv_unsupported_option_for_target
789 : diag::warn_drv_unsupported_option_for_target)
790 << A->getAsString(Args) <<
getTriple().str();
794 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
798 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
801 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
803 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
811 llvm::AMDGPU::GPUKind Kind) {
814 if (Kind == llvm::AMDGPU::GK_NONE)
817 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
821 const bool BothDenormAndFMAFast =
822 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
823 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
824 return !BothDenormAndFMAFast;
828 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
829 const llvm::fltSemantics *FPType)
const {
831 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
832 return llvm::DenormalMode::getIEEE();
839 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
840 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
841 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
842 options::OPT_fno_gpu_flush_denormals_to_zero,
844 return llvm::DenormalMode::getPreserveSign();
846 return llvm::DenormalMode::getIEEE();
849 const StringRef GpuArch =
getGPUArch(DriverArgs);
850 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
854 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
859 return DAZ ? llvm::DenormalMode::getPreserveSign() :
860 llvm::DenormalMode::getIEEE();
864 llvm::AMDGPU::GPUKind Kind) {
865 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
866 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
868 return !HasWave32 || DriverArgs.hasFlag(
869 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
873 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
876 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
878 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
880 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
881 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
882 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
886 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
891 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
892 options::OPT_fvisibility_ms_compat) &&
894 CC1Args.push_back(
"-fvisibility=hidden");
895 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
901 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
902 CC1Args.push_back(
"-fembed-bitcode=marker");
916 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
917 CC1Args.push_back(
"-disable-llvm-optzns");
925 if (DriverArgs.hasArg(options::OPT_nostdlib))
932 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
942 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
943 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
944 :
"-mlink-bitcode-file");
945 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
952 CC1Args.push_back(
"-Werror=atomic-alignment");
956 ArgStringList &CC1Args)
const {
960 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
964 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
965 DriverArgs.hasArg(options::OPT_nostdlibinc))
974 llvm::sys::path::append(Dir, M.includeSuffix());
987 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
992 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
993 if (TargetID.empty())
996 llvm::StringMap<bool> FeatureMap;
998 if (!OptionalGpuArch)
999 return {TargetID.str(), std::nullopt, std::nullopt};
1001 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1007 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1009 << *PTID.OptionalTargetID;
1017 std::string Program;
1018 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1019 Program = A->getValue();
1025 return StdoutOrErr.takeError();
1028 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1030 GPUArchs.push_back(
Arch.str());
1032 if (GPUArchs.empty())
1033 return llvm::createStringError(std::error_code(),
1034 "No AMD GPU detected in the system");
1036 return std::move(GPUArchs);
1040 StringRef GPUArch, StringRef LibDeviceFile,
1043 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1046 if (LibDeviceFile.empty()) {
1047 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1054 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1056 D.Diag(diag::err_drv_no_rocm_device_lib)
1057 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1065 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1067 const bool NeedsASanRT)
const {
1070 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1071 DeviceOffloadingKind, NeedsASanRT};
1074 bool Internalize =
true) {
1075 if (!BCLib.
Path.empty()) {
1077 BCLibs.emplace_back(BCLib);
1080 auto AddSanBCLibs = [&]() {
1089 else if (Pref.GPUSan && Pref.IsOpenMP)
1094 AddBCLib(LibDeviceFile);
1096 if (!ABIVerPath.empty())
1097 AddBCLib(ABIVerPath);
1104 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1106 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1107 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1117 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1127 "spirv should not try to link device libs");
1129 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1140 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1152 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1153 if (!BCLibArgs.empty()) {
1154 ArgStringList LibraryPaths;
1156 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1159 for (StringRef BCName : BCLibArgs) {
1161 for (StringRef LibraryPath : LibraryPaths) {
1163 llvm::sys::path::append(Path, BCName);
1164 if (llvm::sys::fs::exists(Path)) {
1165 BCLibs.emplace_back(Path);
1184 BCLibs.emplace_back(N);
1188 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1189 if (!InstLib.empty()) {
1190 if (llvm::sys::fs::exists(InstLib))
1191 BCLibs.emplace_back(InstLib);
1203 BCLibs.emplace_back(BCLib);
1219 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1227 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1237 return HostTC->GetCXXStdlibType(Args);
1242 const ArgList &Args, ArgStringList &CC1Args)
const {
1244 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1250 ArgStringList &CC1Args)
const {
1252 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1256 ArgStringList &CC1Args)
const {
1257 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1258 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1259 options::OPT_no_offload_inc,
true) &&
1260 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1261 !DriverArgs.hasArg(options::OPT_nobuiltininc))
1262 CC1Args.append({
"-include",
"__clang_gpu_device_functions.h"});
1270 const ArgList &Args)
const {
1272 return HostTC->computeMSVCVersion(D, Args);
1284 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1285 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1293 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1294 : llvm::AMDGPU::parseArchR600(Processor);
1295 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1296 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1299 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1300 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1305 llvm::StringMap<bool> FeatureMap;
1306 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1307 if (!OptionalGpuArch)
1309 auto Loc = FeatureMap.find(
"xnack");
1310 return (Loc != FeatureMap.end() && Loc->second);
1321 SupportedMask |= SanitizerKind::Address;
1323 return SupportedMask;
1329 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.
LTOKind
Describes the kind of LTO mode selected via -f(no-)?lto(=.*)? options.
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()