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 llvm::AMDGPU::AMDGPUFeatureBitset &Features =
48 llvm::AMDGPU::getFeatureBitset(Kind);
52 const bool HasWave32 = Features.test(llvm::AMDGPU::FEAT_SUPPORTS_WAVE32);
54 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
55 options::OPT_mno_wavefrontsize64,
false);
62 const bool DefaultDAZ =
63 (Kind == llvm::AMDGPU::GK_NONE)
65 : !(Features.test(
llvm::
AMDGPU::FEAT_FAST_FMAF) &&
66 Features.test(
llvm::
AMDGPU::FEAT_FAST_DENORMAL_F32));
69 DAZ = IsKnownOffloading
70 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
71 options::OPT_fno_gpu_flush_denormals_to_zero,
73 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
75 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
76 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
77 options::OPT_fno_finite_math_only,
false);
80 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
81 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
82 options::OPT_fno_unsafe_math_optimizations,
false);
84 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
85 DriverArgs.hasFlag(options::OPT_ffast_math,
86 options::OPT_fno_fast_math,
false);
90 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
91 options::OPT_fno_gpu_sanitize,
true) &&
95void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
96 assert(!Path.empty());
98 const StringRef Suffix(
".bc");
99 const StringRef Suffix2(
".amdgcn.bc");
102 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
103 !EC && LI != LE; LI = LI.increment(EC)) {
104 StringRef FilePath = LI->path();
105 StringRef
FileName = llvm::sys::path::filename(FilePath);
111 BaseName =
FileName.drop_back(Suffix2.size());
112 else if (
FileName.ends_with(Suffix))
113 BaseName =
FileName.drop_back(Suffix.size());
115 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
116 if (BaseName ==
"ocml") {
118 }
else if (BaseName ==
"ockl") {
120 }
else if (BaseName ==
"opencl") {
122 }
else if (BaseName ==
"asanrtl") {
124 }
else if (BaseName ==
"oclc_finite_only_off") {
125 FiniteOnly.Off = FilePath;
126 }
else if (BaseName ==
"oclc_finite_only_on") {
127 FiniteOnly.On = FilePath;
128 }
else if (BaseName ==
"oclc_unsafe_math_on") {
129 UnsafeMath.On = FilePath;
130 }
else if (BaseName ==
"oclc_unsafe_math_off") {
131 UnsafeMath.Off = FilePath;
132 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
133 WavefrontSize64.On = FilePath;
134 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
135 WavefrontSize64.Off = FilePath;
136 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
137 unsigned ABIVersionNumber;
138 if (BaseName.drop_front(ABIVersionPrefix.size())
139 .getAsInteger(0, ABIVersionNumber))
141 ABIVersionMap[ABIVersionNumber] = FilePath.str();
145 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
146 if (!BaseName.starts_with(DeviceLibPrefix))
149 StringRef IsaVersionNumber =
150 BaseName.drop_front(DeviceLibPrefix.size());
152 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
154 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
161bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
162 SmallVector<StringRef, 4> VersionParts;
163 V.split(VersionParts,
'\n');
164 unsigned Major = ~0U;
165 unsigned Minor = ~0U;
166 for (
auto Part : VersionParts) {
167 auto Splits = Part.rtrim().split(
'=');
168 if (Splits.first ==
"HIP_VERSION_MAJOR") {
169 if (Splits.second.getAsInteger(0, Major))
171 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
172 if (Splits.second.getAsInteger(0, Minor))
174 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
175 VersionPatch = Splits.second.str();
177 if (Major == ~0U || Minor == ~0U)
179 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
181 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
187const SmallVectorImpl<RocmInstallationDetector::Candidate> &
188RocmInstallationDetector::getInstallationPathCandidates() {
191 if (!ROCmSearchDirs.empty())
192 return ROCmSearchDirs;
194 auto DoPrintROCmSearchDirs = [&]() {
195 if (PrintROCmSearchDirs)
196 for (
auto Cand : ROCmSearchDirs) {
197 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
203 if (!RocmPathArg.empty()) {
204 ROCmSearchDirs.emplace_back(RocmPathArg.str());
205 DoPrintROCmSearchDirs();
206 return ROCmSearchDirs;
207 }
else if (std::optional<std::string> RocmPathEnv =
208 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
209 if (!RocmPathEnv->empty()) {
210 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
211 DoPrintROCmSearchDirs();
212 return ROCmSearchDirs;
217 StringRef InstallDir = D.Dir;
222 auto DeduceROCmPath = [](StringRef ClangPath) {
224 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
225 StringRef ParentName = llvm::sys::path::filename(ParentDir);
228 if (ParentName ==
"bin") {
229 ParentDir = llvm::sys::path::parent_path(ParentDir);
230 ParentName = llvm::sys::path::filename(ParentDir);
235 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
236 ParentDir = llvm::sys::path::parent_path(ParentDir);
237 ParentName = llvm::sys::path::filename(ParentDir);
241 if (ParentName ==
"lib")
242 ParentDir = llvm::sys::path::parent_path(ParentDir);
245 return Candidate(ParentDir.str(),
true);
250 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
254 llvm::SmallString<256> RealClangPath;
255 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
256 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
257 if (ParentPath != InstallDir)
258 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
261 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
262 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
263 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
264 if (RealClangRoot != ClangRoot)
265 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
266 ROCmSearchDirs.emplace_back(D.ResourceDir,
269 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
274 std::string LatestROCm;
275 llvm::VersionTuple LatestVer;
277 auto GetROCmVersion = [](StringRef DirName) {
278 llvm::VersionTuple
V;
279 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
282 llvm::replace(VerStr,
'-',
'.');
286 for (llvm::vfs::directory_iterator
287 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
289 File != FileEnd && !EC;
File.increment(EC)) {
290 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
293 if (LatestROCm.empty()) {
295 LatestVer = GetROCmVersion(LatestROCm);
298 auto Ver = GetROCmVersion(
FileName);
299 if (LatestVer < Ver) {
304 if (!LatestROCm.empty())
305 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
308 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
310 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
313 DoPrintROCmSearchDirs();
314 return ROCmSearchDirs;
318 const Driver &D,
const llvm::Triple &HostTriple,
319 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
321 Verbose = Args.hasArg(options::OPT_v);
322 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
323 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
324 RocmDeviceLibPathArg =
325 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
326 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
327 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
328 HasHIPStdParLibrary =
329 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
330 "/hipstdpar_lib.hpp");
331 HIPRocThrustPathArg =
332 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
333 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
334 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
335 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
336 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
337 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
339 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
340 HIPVersionArg = A->getValue();
341 unsigned Major = ~0U;
342 unsigned Minor = ~0U;
343 SmallVector<StringRef, 3> Parts;
344 HIPVersionArg.split(Parts,
'.');
346 Parts[0].getAsInteger(0, Major);
347 if (Parts.size() > 1)
348 Parts[1].getAsInteger(0, Minor);
349 if (Parts.size() > 2)
350 VersionPatch = Parts[2].str();
351 if (VersionPatch.empty())
353 if (Major != ~0U && Minor == ~0U)
355 if (Major == ~0U || Minor == ~0U)
356 D.Diag(diag::err_drv_invalid_value)
357 << A->getAsString(Args) << HIPVersionArg;
359 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
361 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
363 VersionPatch = DefaultVersionPatch;
365 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
366 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
367 Twine(DefaultVersionMinor) +
"." + VersionPatch)
371 if (DetectHIPRuntime)
376 assert(LibDevicePath.empty());
378 if (!RocmDeviceLibPathArg.empty())
379 LibDevicePath = RocmDeviceLibPathArg.back();
380 else if (std::optional<std::string> LibPathEnv =
381 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
382 LibDevicePath = std::move(*LibPathEnv);
384 auto &FS = D.getVFS();
385 if (!LibDevicePath.empty()) {
389 if (!FS.exists(LibDevicePath))
392 scanLibDevicePath(LibDevicePath);
393 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
398 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
399 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
400 if (CheckLibDevice && !FS.exists(Path))
403 scanLibDevicePath(Path);
405 if (!NoBuiltinLibs) {
407 if (!allGenericLibsValid())
412 if (LibDeviceMap.empty())
419 LibDevicePath = D.ResourceDir;
420 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
421 "amdgcn",
"bitcode");
422 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
423 if (HasDeviceLibrary)
428 auto &ROCmDirs = getInstallationPathCandidates();
429 for (
const auto &Candidate : ROCmDirs) {
430 LibDevicePath = Candidate.Path;
431 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
432 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
433 if (HasDeviceLibrary)
439 const llvm::Triple &HostTriple) {
441 if (!HIPPathArg.empty())
442 HIPSearchDirs.emplace_back(HIPPathArg.str());
443 else if (std::optional<std::string> HIPPathEnv =
444 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
445 if (!HIPPathEnv->empty())
446 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
448 if (HIPSearchDirs.empty())
449 HIPSearchDirs.append(getInstallationPathCandidates());
450 auto &FS = D.getVFS();
452 for (
const auto &Candidate : HIPSearchDirs) {
453 InstallPath = Candidate.Path;
454 if (InstallPath.empty() || !FS.exists(InstallPath))
457 BinPath = InstallPath;
458 llvm::sys::path::append(BinPath,
"bin");
459 IncludePath = InstallPath;
460 llvm::sys::path::append(IncludePath,
"include");
464 StringRef LibAmdHip64 =
465 HostTriple.isOSMSVCRT() ?
"amdhip64.lib" :
"libamdhip64.so";
467 for (StringRef LibPathSuffix : {
"lib",
"lib64"}) {
469 llvm::sys::path::append(LibAmdHip64Location, InstallPath, LibPathSuffix,
471 if (FS.exists(LibAmdHip64Location)) {
472 llvm::sys::path::append(LibPath, InstallPath, LibPathSuffix);
478 llvm::sys::path::append(LibPath, InstallPath,
"lib");
480 SharePath = InstallPath;
481 llvm::sys::path::append(SharePath,
"share");
484 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
485 llvm::sys::path::append(ParentSharePath,
"share");
488 const Twine &c =
"",
const Twine &d =
"") {
490 llvm::sys::path::append(newpath, a, b, c, d);
494 std::vector<SmallString<0>> VersionFilePaths = {
495 Append(SharePath,
"hip",
"version"),
496 InstallPath != D.SysRoot +
"/usr/local"
497 ?
Append(ParentSharePath,
"hip",
"version")
499 Append(BinPath,
".hipVersion")};
501 for (
const auto &VersionFilePath : VersionFilePaths) {
502 if (VersionFilePath.empty())
504 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
505 FS.getBufferForFile(VersionFilePath);
508 if (HIPVersionArg.empty() && VersionFile)
509 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
512 HasHIPRuntime =
true;
517 if (!Candidate.StrictChecking) {
518 HasHIPRuntime =
true;
522 HasHIPRuntime =
false;
527 OS <<
"Found HIP installation: " << InstallPath <<
", version "
528 << DetectedVersion <<
'\n';
532 ArgStringList &CC1Args)
const {
533 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
534 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
535 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
537 if (DriverArgs.hasFlag(options::OPT_foffload_via_llvm,
538 options::OPT_fno_offload_via_llvm,
false))
541 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
556 if (UsesRuntimeWrapper)
557 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
558 CC1Args.push_back(
"-internal-isystem");
559 CC1Args.push_back(DriverArgs.MakeArgString(P));
562 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
564 auto &FS = D.getVFS();
567 if (!HIPStdParPathArg.empty() ||
568 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
569 D.Diag(diag::err_drv_no_hipstdpar_lib);
572 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
573 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
576 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
577 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
580 const char *ThrustPath;
581 if (HasRocThrustLibrary)
582 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
584 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
586 const char *HIPStdParPath;
588 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
590 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
591 "/system/hip/hipstdpar");
593 const char *PrimPath;
594 if (HasRocPrimLibrary)
595 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
597 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
599 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
600 "-idirafter", HIPStdParPath,
"-include",
601 "hipstdpar_lib.hpp"});
604 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
613 D.Diag(diag::err_drv_no_hip_runtime);
617 CC1Args.push_back(
"-idirafter");
620 llvm::sys::path::append(LibHipCxxPath,
"libhipcxx");
621 if (D.getVFS().exists(LibHipCxxPath)) {
622 CC1Args.push_back(
"-idirafter");
623 CC1Args.push_back(DriverArgs.MakeArgString(LibHipCxxPath));
625 if (UsesRuntimeWrapper)
626 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
635 const char *LinkingOutput)
const {
637 ArgStringList CmdArgs;
638 if (!Args.hasArg(options::OPT_r)) {
639 CmdArgs.push_back(
"--no-undefined");
640 CmdArgs.push_back(
"-shared");
643 if (Args.hasArg(options::OPT_hipstdpar))
644 CmdArgs.push_back(
"-plugin-opt=-amdgpu-enable-hipstdpar");
649 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
650 CmdArgs.push_back(Args.MakeArgString(
651 "-plugin-opt=mcpu=" +
653 Args.getLastArgValue(options::OPT_mcpu_EQ))));
657 Args.AddAllArgs(CmdArgs, options::OPT_L);
661 std::vector<StringRef> Features;
664 if (!Features.empty()) {
666 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
671 if (!
getToolChain().getSanitizerArgs(Args).needsAsanRt())
674 if (Args.hasArg(options::OPT_stdlib))
675 CmdArgs.append({
"-lc",
"-lm"});
676 if (Args.hasArg(options::OPT_startfiles)) {
677 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
679 IncludePath =
"/lib";
681 llvm::sys::path::append(P,
"crt1.o");
682 CmdArgs.push_back(Args.MakeArgString(P));
685 CmdArgs.push_back(
"-o");
687 C.addCommand(std::make_unique<Command>(
689 CmdArgs, Inputs, Output));
693 const llvm::Triple &Triple,
694 const llvm::opt::ArgList &Args,
695 std::vector<StringRef> &Features,
697 if (Args.hasFlag(options::OPT_mwavefrontsize64,
698 options::OPT_mno_wavefrontsize64,
false))
699 Features.push_back(
"+wavefrontsize64");
701 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
702 options::OPT_mno_amdgpu_precise_memory_op,
false))
703 Features.push_back(
"+precise-memory");
708 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
710 A->getOption().matches(options::OPT_mxnack) ?
"+xnack" :
"-xnack");
714 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
715 Features.push_back(A->getOption().matches(options::OPT_msramecc)
722 options::OPT_m_amdgpu_Features_Group);
727 const ArgList &Args,
const ToolChain *HostTC_,
732 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
734 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
735 loadMultilibsFromYAML(Args, D);
743 bool UsesLLVMOffloading = Args.hasFlag(
744 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
745 if (Triple.getOS() == llvm::Triple::AMDHSA &&
746 Triple.getEnvironment() != llvm::Triple::LLVM && !UsesLLVMOffloading)
747 RocmInstallation->detectDeviceLibrary();
750 getProgramPaths().push_back(getDriver().Dir);
765 DAL =
new DerivedArgList(Args.getBaseArgs());
774 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
775 DAL->eraseArg(options::OPT_march_EQ);
776 if (!DAL->hasArg(options::OPT_mcpu_EQ))
777 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
783 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
784 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
785 DAL->eraseArg(options::OPT_mcpu_EQ);
789 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
791 auto &GPUs = *GPUsOrErr;
792 if (!llvm::all_equal(GPUs))
794 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
795 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
796 Args.MakeArgString(GPUs.front()));
801 DAL->eraseArg(options::OPT_mcpu_EQ);
802 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
813 auto XnackIt = FeatureMap.find(
"xnack");
814 if (XnackIt != FeatureMap.end()) {
815 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
816 ? options::OPT_mxnack
817 : options::OPT_mno_xnack));
820 auto SrameccIt = FeatureMap.find(
"sramecc");
821 if (SrameccIt != FeatureMap.end()) {
822 DAL->AddFlagArg(
nullptr,
823 Opts.getOption(SrameccIt->second
824 ? options::OPT_msramecc
825 : options::OPT_mno_sramecc));
831 for (Arg *A : Args) {
833 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
835 bool IsExplicitDevice =
836 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
838 ? diag::err_drv_unsupported_option_for_target
839 : diag::warn_drv_unsupported_option_for_target)
840 << A->getAsString(Args) <<
getTriple().str();
844 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
848 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
851 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
853 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
861 llvm::AMDGPU::GPUKind Kind) {
864 if (Kind == llvm::AMDGPU::GK_NONE)
867 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
868 llvm::AMDGPU::getFeatureBitset(Kind);
872 const bool BothDenormAndFMAFast =
873 Features.test(llvm::AMDGPU::FEAT_FAST_FMAF) &&
874 Features.test(llvm::AMDGPU::FEAT_FAST_DENORMAL_F32);
875 return !BothDenormAndFMAFast;
879 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
880 const llvm::fltSemantics *FPType)
const {
882 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
883 return llvm::DenormalMode::getIEEE();
890 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
891 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
892 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
893 options::OPT_fno_gpu_flush_denormals_to_zero,
895 return llvm::DenormalMode::getPreserveSign();
897 return llvm::DenormalMode::getIEEE();
900 const StringRef GpuArch =
getGPUArch(DriverArgs);
901 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
905 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
910 return DAZ ? llvm::DenormalMode::getPreserveSign() :
911 llvm::DenormalMode::getIEEE();
915 llvm::AMDGPU::GPUKind Kind) {
916 bool HasWave32 = llvm::AMDGPU::getFeatureBitset(Kind).test(
917 llvm::AMDGPU::FEAT_SUPPORTS_WAVE32);
919 return !HasWave32 || DriverArgs.hasFlag(
920 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
924 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
926 bool UsesLLVMOffloading = DriverArgs.hasFlag(
927 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
930 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
932 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
934 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
935 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
936 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
940 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
945 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
946 options::OPT_fvisibility_ms_compat) &&
948 CC1Args.push_back(
"-fvisibility=hidden");
949 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
955 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
956 CC1Args.push_back(
"-fembed-bitcode=marker");
970 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
971 CC1Args.push_back(
"-disable-llvm-optzns");
979 if (DriverArgs.hasArg(options::OPT_nostdlib))
986 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
996 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
997 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
998 :
"-mlink-bitcode-file");
999 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
1006 CC1Args.push_back(
"-Werror=atomic-alignment");
1010 ArgStringList &CC1Args)
const {
1014 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
1018 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
1019 DriverArgs.hasArg(options::OPT_nostdlibinc))
1028 llvm::sys::path::append(Dir, M.includeSuffix());
1041 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
1046 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1047 if (TargetID.empty())
1050 llvm::StringMap<bool> FeatureMap;
1052 if (!OptionalGpuArch)
1053 return {TargetID.str(), std::nullopt, std::nullopt};
1055 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1061 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1063 << *PTID.OptionalTargetID;
1067 if (
getTriple().getSubArch() != llvm::Triple::NoSubArch &&
1068 PTID.OptionalGPUArch) {
1069 llvm::AMDGPU::GPUKind Kind =
1070 llvm::AMDGPU::parseArchAMDGCN(*PTID.OptionalGPUArch);
1071 llvm::Triple::SubArchType KindSubArch =
1072 static_cast<llvm::Triple::SubArchType
>(llvm::AMDGPU::getSubArch(Kind));
1073 if (
getTriple().getSubArch() != KindSubArch &&
1075 llvm::AMDGPU::getMajorSubArch(KindSubArch)) {
1077 << *PTID.OptionalGPUArch <<
getTriple().getArchName();
1086 std::string Program;
1087 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1088 Program = A->getValue();
1094 return StdoutOrErr.takeError();
1097 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1099 GPUArchs.push_back(
Arch.str());
1101 if (GPUArchs.empty())
1102 return llvm::createStringError(std::error_code(),
1103 "No AMD GPU detected in the system");
1105 return std::move(GPUArchs);
1109 StringRef GPUArch, StringRef LibDeviceFile,
1112 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1115 if (LibDeviceFile.empty()) {
1116 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1123 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1125 D.Diag(diag::err_drv_no_rocm_device_lib)
1126 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1134 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1136 const bool NeedsASanRT)
const {
1139 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1140 DeviceOffloadingKind, NeedsASanRT};
1143 bool Internalize =
true) {
1144 if (!BCLib.
Path.empty()) {
1146 BCLibs.emplace_back(BCLib);
1149 auto AddSanBCLibs = [&]() {
1158 else if (Pref.GPUSan && Pref.IsOpenMP)
1163 AddBCLib(LibDeviceFile);
1165 if (!ABIVerPath.empty())
1166 AddBCLib(ABIVerPath);
1173 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1175 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1176 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1186 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1196 "spirv should not try to link device libs");
1198 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1209 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1221 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1222 if (!BCLibArgs.empty()) {
1223 ArgStringList LibraryPaths;
1225 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1228 for (StringRef BCName : BCLibArgs) {
1230 for (StringRef LibraryPath : LibraryPaths) {
1232 llvm::sys::path::append(Path, BCName);
1233 if (llvm::sys::fs::exists(Path)) {
1234 BCLibs.emplace_back(Path);
1253 BCLibs.emplace_back(N);
1257 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1258 if (!InstLib.empty()) {
1259 if (llvm::sys::fs::exists(InstLib))
1260 BCLibs.emplace_back(InstLib);
1272 BCLibs.emplace_back(BCLib);
1288 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1296 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1306 return HostTC->GetCXXStdlibType(Args);
1311 const ArgList &Args, ArgStringList &CC1Args)
const {
1313 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1319 ArgStringList &CC1Args)
const {
1321 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1325 ArgStringList &CC1Args)
const {
1326 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1327 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1328 options::OPT_no_offload_inc,
true) &&
1329 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1330 !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1332 llvm::sys::path::append(P,
"include",
"hip_wrappers");
1333 CC1Args.push_back(
"-internal-isystem");
1334 CC1Args.push_back(DriverArgs.MakeArgString(P));
1343 const ArgList &Args)
const {
1345 return HostTC->computeMSVCVersion(D, Args);
1357 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1358 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1368 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1369 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
1370 llvm::AMDGPU::getFeatureBitset(ProcKind);
1373 bool XnackAlwaysOn = Features.test(llvm::AMDGPU::FEAT_XNACK_SUPPORT) &&
1374 !Features.test(llvm::AMDGPU::FEAT_XNACK_ON_OFF_MODES);
1379 llvm::StringMap<bool> FeatureMap;
1380 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1381 if (!OptionalGpuArch)
1383 auto Loc = FeatureMap.find(
"xnack");
1384 return (Loc != FeatureMap.end() && Loc->second);
1395 SupportedMask |= SanitizerKind::Address;
1397 return SupportedMask;
1403 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()