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)
438 const llvm::Triple &HostTriple) {
440 if (!HIPPathArg.empty())
441 HIPSearchDirs.emplace_back(HIPPathArg.str());
442 else if (std::optional<std::string> HIPPathEnv =
443 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
444 if (!HIPPathEnv->empty())
445 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
447 if (HIPSearchDirs.empty())
448 HIPSearchDirs.append(getInstallationPathCandidates());
449 auto &FS = D.getVFS();
451 for (
const auto &Candidate : HIPSearchDirs) {
452 InstallPath = Candidate.Path;
453 if (InstallPath.empty() || !FS.exists(InstallPath))
456 BinPath = InstallPath;
457 llvm::sys::path::append(BinPath,
"bin");
458 IncludePath = InstallPath;
459 llvm::sys::path::append(IncludePath,
"include");
463 StringRef LibAmdHip64 =
464 HostTriple.isOSMSVCRT() ?
"amdhip64.lib" :
"libamdhip64.so";
466 for (StringRef LibPathSuffix : {
"lib",
"lib64"}) {
468 llvm::sys::path::append(LibAmdHip64Location, InstallPath, LibPathSuffix,
470 if (FS.exists(LibAmdHip64Location)) {
471 llvm::sys::path::append(LibPath, InstallPath, LibPathSuffix);
477 llvm::sys::path::append(LibPath, InstallPath,
"lib");
479 SharePath = InstallPath;
480 llvm::sys::path::append(SharePath,
"share");
483 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
484 llvm::sys::path::append(ParentSharePath,
"share");
487 const Twine &c =
"",
const Twine &d =
"") {
489 llvm::sys::path::append(newpath, a, b, c, d);
493 std::vector<SmallString<0>> VersionFilePaths = {
494 Append(SharePath,
"hip",
"version"),
495 InstallPath != D.SysRoot +
"/usr/local"
496 ?
Append(ParentSharePath,
"hip",
"version")
498 Append(BinPath,
".hipVersion")};
500 for (
const auto &VersionFilePath : VersionFilePaths) {
501 if (VersionFilePath.empty())
503 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
504 FS.getBufferForFile(VersionFilePath);
507 if (HIPVersionArg.empty() && VersionFile)
508 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
511 HasHIPRuntime =
true;
516 if (!Candidate.StrictChecking) {
517 HasHIPRuntime =
true;
521 HasHIPRuntime =
false;
526 OS <<
"Found HIP installation: " << InstallPath <<
", version "
527 << DetectedVersion <<
'\n';
531 ArgStringList &CC1Args)
const {
532 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
533 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
534 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
536 if (DriverArgs.hasFlag(options::OPT_foffload_via_llvm,
537 options::OPT_fno_offload_via_llvm,
false))
540 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
555 if (UsesRuntimeWrapper)
556 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
557 CC1Args.push_back(
"-internal-isystem");
558 CC1Args.push_back(DriverArgs.MakeArgString(P));
561 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
563 auto &FS = D.getVFS();
566 if (!HIPStdParPathArg.empty() ||
567 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
568 D.Diag(diag::err_drv_no_hipstdpar_lib);
571 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
572 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
575 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
576 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
579 const char *ThrustPath;
580 if (HasRocThrustLibrary)
581 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
583 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
585 const char *HIPStdParPath;
587 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
589 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
590 "/system/hip/hipstdpar");
592 const char *PrimPath;
593 if (HasRocPrimLibrary)
594 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
596 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
598 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
599 "-idirafter", HIPStdParPath,
"-include",
600 "hipstdpar_lib.hpp"});
603 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
612 D.Diag(diag::err_drv_no_hip_runtime);
616 CC1Args.push_back(
"-idirafter");
619 llvm::sys::path::append(LibHipCxxPath,
"libhipcxx");
620 if (D.getVFS().exists(LibHipCxxPath)) {
621 CC1Args.push_back(
"-idirafter");
622 CC1Args.push_back(DriverArgs.MakeArgString(LibHipCxxPath));
624 if (UsesRuntimeWrapper)
625 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
634 const char *LinkingOutput)
const {
636 ArgStringList CmdArgs;
637 if (!Args.hasArg(options::OPT_r)) {
638 CmdArgs.push_back(
"--no-undefined");
639 CmdArgs.push_back(
"-shared");
642 if (Args.hasArg(options::OPT_hipstdpar))
643 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
648 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
649 CmdArgs.push_back(Args.MakeArgString(
650 "-plugin-opt=mcpu=" +
652 Args.getLastArgValue(options::OPT_mcpu_EQ))));
656 Args.AddAllArgs(CmdArgs, options::OPT_L);
660 std::vector<StringRef> Features;
663 if (!Features.empty()) {
665 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
671 if (Args.hasArg(options::OPT_stdlib))
672 CmdArgs.append({
"-lc",
"-lm"});
673 if (Args.hasArg(options::OPT_startfiles)) {
674 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
676 IncludePath =
"/lib";
678 llvm::sys::path::append(P,
"crt1.o");
679 CmdArgs.push_back(Args.MakeArgString(P));
682 CmdArgs.push_back(
"-o");
684 C.addCommand(std::make_unique<Command>(
686 CmdArgs, Inputs, Output));
690 const llvm::Triple &Triple,
691 const llvm::opt::ArgList &Args,
692 std::vector<StringRef> &Features,
694 if (Args.hasFlag(options::OPT_mwavefrontsize64,
695 options::OPT_mno_wavefrontsize64,
false))
696 Features.push_back(
"+wavefrontsize64");
698 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
699 options::OPT_mno_amdgpu_precise_memory_op,
false))
700 Features.push_back(
"+precise-memory");
705 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
707 A->getOption().matches(options::OPT_mxnack) ?
"+xnack" :
"-xnack");
711 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
712 Features.push_back(A->getOption().matches(options::OPT_msramecc)
719 options::OPT_m_amdgpu_Features_Group);
724 const ArgList &Args,
const ToolChain *HostTC_,
729 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
731 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
732 loadMultilibsFromYAML(Args, D);
740 bool UsesLLVMOffloading = Args.hasFlag(
741 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
742 if (Triple.getOS() == llvm::Triple::AMDHSA &&
743 Triple.getEnvironment() != llvm::Triple::LLVM && !UsesLLVMOffloading)
744 RocmInstallation->detectDeviceLibrary();
747 getProgramPaths().push_back(getDriver().Dir);
762 DAL =
new DerivedArgList(Args.getBaseArgs());
771 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
772 DAL->eraseArg(options::OPT_march_EQ);
773 if (!DAL->hasArg(options::OPT_mcpu_EQ))
774 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
780 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
781 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
782 DAL->eraseArg(options::OPT_mcpu_EQ);
786 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
788 auto &GPUs = *GPUsOrErr;
789 if (!llvm::all_equal(GPUs))
791 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
792 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
793 Args.MakeArgString(GPUs.front()));
798 DAL->eraseArg(options::OPT_mcpu_EQ);
799 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
810 auto XnackIt = FeatureMap.find(
"xnack");
811 if (XnackIt != FeatureMap.end()) {
812 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
813 ? options::OPT_mxnack
814 : options::OPT_mno_xnack));
817 auto SrameccIt = FeatureMap.find(
"sramecc");
818 if (SrameccIt != FeatureMap.end()) {
819 DAL->AddFlagArg(
nullptr,
820 Opts.getOption(SrameccIt->second
821 ? options::OPT_msramecc
822 : options::OPT_mno_sramecc));
828 for (Arg *A : Args) {
830 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
832 bool IsExplicitDevice =
833 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
835 ? diag::err_drv_unsupported_option_for_target
836 : diag::warn_drv_unsupported_option_for_target)
837 << A->getAsString(Args) <<
getTriple().str();
841 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
845 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
848 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
850 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
858 llvm::AMDGPU::GPUKind Kind) {
861 if (Kind == llvm::AMDGPU::GK_NONE)
864 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
868 const bool BothDenormAndFMAFast =
869 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
870 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
871 return !BothDenormAndFMAFast;
875 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
876 const llvm::fltSemantics *FPType)
const {
878 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
879 return llvm::DenormalMode::getIEEE();
886 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
887 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
888 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
889 options::OPT_fno_gpu_flush_denormals_to_zero,
891 return llvm::DenormalMode::getPreserveSign();
893 return llvm::DenormalMode::getIEEE();
896 const StringRef GpuArch =
getGPUArch(DriverArgs);
897 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
901 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
906 return DAZ ? llvm::DenormalMode::getPreserveSign() :
907 llvm::DenormalMode::getIEEE();
911 llvm::AMDGPU::GPUKind Kind) {
912 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
913 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
915 return !HasWave32 || DriverArgs.hasFlag(
916 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
920 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
922 bool UsesLLVMOffloading = DriverArgs.hasFlag(
923 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
926 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
928 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
930 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
931 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
932 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
936 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
941 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
942 options::OPT_fvisibility_ms_compat) &&
944 CC1Args.push_back(
"-fvisibility=hidden");
945 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
951 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
952 CC1Args.push_back(
"-fembed-bitcode=marker");
966 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
967 CC1Args.push_back(
"-disable-llvm-optzns");
975 if (DriverArgs.hasArg(options::OPT_nostdlib))
982 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
992 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
993 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
994 :
"-mlink-bitcode-file");
995 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
1002 CC1Args.push_back(
"-Werror=atomic-alignment");
1006 ArgStringList &CC1Args)
const {
1010 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
1014 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
1015 DriverArgs.hasArg(options::OPT_nostdlibinc))
1024 llvm::sys::path::append(Dir, M.includeSuffix());
1037 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
1042 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1043 if (TargetID.empty())
1046 llvm::StringMap<bool> FeatureMap;
1048 if (!OptionalGpuArch)
1049 return {TargetID.str(), std::nullopt, std::nullopt};
1051 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1057 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1059 << *PTID.OptionalTargetID;
1067 std::string Program;
1068 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1069 Program = A->getValue();
1075 return StdoutOrErr.takeError();
1078 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1080 GPUArchs.push_back(
Arch.str());
1082 if (GPUArchs.empty())
1083 return llvm::createStringError(std::error_code(),
1084 "No AMD GPU detected in the system");
1086 return std::move(GPUArchs);
1090 StringRef GPUArch, StringRef LibDeviceFile,
1093 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1096 if (LibDeviceFile.empty()) {
1097 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1104 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1106 D.Diag(diag::err_drv_no_rocm_device_lib)
1107 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1115 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1117 const bool NeedsASanRT)
const {
1120 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1121 DeviceOffloadingKind, NeedsASanRT};
1124 bool Internalize =
true) {
1125 if (!BCLib.
Path.empty()) {
1127 BCLibs.emplace_back(BCLib);
1130 auto AddSanBCLibs = [&]() {
1139 else if (Pref.GPUSan && Pref.IsOpenMP)
1144 AddBCLib(LibDeviceFile);
1146 if (!ABIVerPath.empty())
1147 AddBCLib(ABIVerPath);
1154 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1156 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1157 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1167 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1177 "spirv should not try to link device libs");
1179 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1190 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1202 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1203 if (!BCLibArgs.empty()) {
1204 ArgStringList LibraryPaths;
1206 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1209 for (StringRef BCName : BCLibArgs) {
1211 for (StringRef LibraryPath : LibraryPaths) {
1213 llvm::sys::path::append(Path, BCName);
1214 if (llvm::sys::fs::exists(Path)) {
1215 BCLibs.emplace_back(Path);
1234 BCLibs.emplace_back(N);
1238 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1239 if (!InstLib.empty()) {
1240 if (llvm::sys::fs::exists(InstLib))
1241 BCLibs.emplace_back(InstLib);
1253 BCLibs.emplace_back(BCLib);
1269 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1277 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1287 return HostTC->GetCXXStdlibType(Args);
1292 const ArgList &Args, ArgStringList &CC1Args)
const {
1294 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1300 ArgStringList &CC1Args)
const {
1302 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1306 ArgStringList &CC1Args)
const {
1307 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1308 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1309 options::OPT_no_offload_inc,
true) &&
1310 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1311 !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1313 llvm::sys::path::append(P,
"include",
"hip_wrappers");
1314 CC1Args.push_back(
"-internal-isystem");
1315 CC1Args.push_back(DriverArgs.MakeArgString(P));
1324 const ArgList &Args)
const {
1326 return HostTC->computeMSVCVersion(D, Args);
1338 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1339 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1349 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1350 unsigned Features = llvm::AMDGPU::getArchAttrAMDGCN(ProcKind);
1353 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1354 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1359 llvm::StringMap<bool> FeatureMap;
1360 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1361 if (!OptionalGpuArch)
1363 auto Loc = FeatureMap.find(
"xnack");
1364 return (Loc != FeatureMap.end() && Loc->second);
1375 SupportedMask |= SanitizerKind::Address;
1377 return SupportedMask;
1383 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()
void detectHIPRuntime(const llvm::Triple &HostTriple)
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
Top level wrappers for InstallAPI frontend operations.
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()