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),
807 std::optional<llvm::AMDGPU::TargetID> PTID =
checkTargetID(*DAL);
812 using llvm::AMDGPU::TargetIDSetting;
813 if (PTID->isXnackOnOrOff())
814 DAL->AddFlagArg(
nullptr, Opts.getOption(PTID->getXnackSetting() ==
816 ? options::OPT_mxnack
817 : options::OPT_mno_xnack));
819 if (PTID->isSramEccOnOrOff())
822 Opts.getOption(PTID->getSramEccSetting() == TargetIDSetting::On
823 ? options::OPT_msramecc
824 : options::OPT_mno_sramecc));
829 for (Arg *A : Args) {
831 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
833 bool IsExplicitDevice =
834 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
836 ? diag::err_drv_unsupported_option_for_target
837 : diag::warn_drv_unsupported_option_for_target)
838 << A->getAsString(Args) <<
getTriple().str();
842 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
846 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
849 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
851 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
859 llvm::AMDGPU::GPUKind Kind) {
862 if (Kind == llvm::AMDGPU::GK_NONE)
865 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
866 llvm::AMDGPU::getFeatureBitset(Kind);
870 const bool BothDenormAndFMAFast =
871 Features.test(llvm::AMDGPU::FEAT_FAST_FMAF) &&
872 Features.test(llvm::AMDGPU::FEAT_FAST_DENORMAL_F32);
873 return !BothDenormAndFMAFast;
877 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
878 const llvm::fltSemantics *FPType)
const {
880 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
881 return llvm::DenormalMode::getIEEE();
888 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
889 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
890 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
891 options::OPT_fno_gpu_flush_denormals_to_zero,
893 return llvm::DenormalMode::getPreserveSign();
895 return llvm::DenormalMode::getIEEE();
898 const StringRef GpuArch =
getGPUArch(DriverArgs);
899 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
903 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
908 return DAZ ? llvm::DenormalMode::getPreserveSign() :
909 llvm::DenormalMode::getIEEE();
913 llvm::AMDGPU::GPUKind Kind) {
914 bool HasWave32 = llvm::AMDGPU::getFeatureBitset(Kind).test(
915 llvm::AMDGPU::FEAT_SUPPORTS_WAVE32);
917 return !HasWave32 || DriverArgs.hasFlag(
918 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
922 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
924 bool UsesLLVMOffloading = DriverArgs.hasFlag(
925 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
928 CC1Args.append({
"-fcuda-is-device",
"-fno-threadsafe-statics"});
930 if (!DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
932 CC1Args.append({
"-mllvm",
"-amdgpu-internalize-symbols"});
933 if (DriverArgs.hasArgNoClaim(options::OPT_hipstdpar))
934 CC1Args.append({
"-mllvm",
"-amdgpu-enable-hipstdpar"});
938 DriverArgs.AddLastArg(CC1Args, options::OPT_gpu_max_threads_per_block_EQ);
943 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
944 options::OPT_fvisibility_ms_compat) &&
946 CC1Args.push_back(
"-fvisibility=hidden");
947 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
953 !DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
954 CC1Args.push_back(
"-fembed-bitcode=marker");
968 if (!DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
969 CC1Args.push_back(
"-disable-llvm-optzns");
977 if (DriverArgs.hasArg(options::OPT_nostdlib))
984 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
994 for (
auto BCFile :
getDeviceLibs(DriverArgs, BA, DeviceOffloadingKind)) {
995 CC1Args.push_back(BCFile.ShouldInternalize ?
"-mlink-builtin-bitcode"
996 :
"-mlink-bitcode-file");
997 CC1Args.push_back(DriverArgs.MakeArgStringRef(BCFile.Path));
1004 CC1Args.push_back(
"-Werror=atomic-alignment");
1008 ArgStringList &CC1Args)
const {
1012 HostTC->AddClangSystemIncludeArgs(DriverArgs, CC1Args);
1016 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
1017 DriverArgs.hasArg(options::OPT_nostdlibinc))
1026 llvm::sys::path::append(Dir, M.includeSuffix());
1039 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
1047 return DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1050std::optional<llvm::AMDGPU::TargetID>
1053 if (TargetID.empty())
1054 return std::nullopt;
1056 return llvm::AMDGPU::TargetID::parse(
getTriple(), TargetID);
1059std::optional<llvm::AMDGPU::TargetID>
1066 if (TargetID.empty())
1073 llvm::AMDGPU::GPUKind Kind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1074 if (
getTriple().getSubArch() != llvm::Triple::NoSubArch &&
1075 Kind != llvm::AMDGPU::GK_NONE &&
1076 !llvm::AMDGPU::isCPUValidForSubArch(
getTriple().getSubArch(), Kind)) {
1078 << Processor <<
getTriple().getArchName();
1082 getDriver().
Diag(clang::diag::err_drv_bad_target_id) << TargetID;
1089 std::string Program;
1090 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1091 Program = A->getValue();
1097 return StdoutOrErr.takeError();
1100 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1102 GPUArchs.push_back(
Arch.str());
1104 if (GPUArchs.empty())
1105 return llvm::createStringError(std::error_code(),
1106 "No AMD GPU detected in the system");
1108 return std::move(GPUArchs);
1112 StringRef GPUArch, StringRef LibDeviceFile,
1115 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1118 if (LibDeviceFile.empty()) {
1119 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1126 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1128 D.Diag(diag::err_drv_no_rocm_device_lib)
1129 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1137 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1139 const bool NeedsASanRT)
const {
1142 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1143 DeviceOffloadingKind, NeedsASanRT};
1146 bool Internalize =
true) {
1147 if (!BCLib.
Path.empty()) {
1149 BCLibs.emplace_back(BCLib);
1152 auto AddSanBCLibs = [&]() {
1161 else if (Pref.GPUSan && Pref.IsOpenMP)
1166 AddBCLib(LibDeviceFile);
1168 if (!ABIVerPath.empty())
1169 AddBCLib(ABIVerPath);
1176 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1178 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1179 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1189 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1199 "spirv should not try to link device libs");
1201 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1212 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1224 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1225 if (!BCLibArgs.empty()) {
1226 ArgStringList LibraryPaths;
1228 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1231 for (StringRef BCName : BCLibArgs) {
1233 for (StringRef LibraryPath : LibraryPaths) {
1235 llvm::sys::path::append(Path, BCName);
1236 if (llvm::sys::fs::exists(Path)) {
1237 BCLibs.emplace_back(Path);
1256 BCLibs.emplace_back(N);
1260 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1261 if (!InstLib.empty()) {
1262 if (llvm::sys::fs::exists(InstLib))
1263 BCLibs.emplace_back(InstLib);
1275 BCLibs.emplace_back(BCLib);
1291 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1299 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1309 return HostTC->GetCXXStdlibType(Args);
1314 const ArgList &Args, ArgStringList &CC1Args)
const {
1316 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1322 ArgStringList &CC1Args)
const {
1324 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1328 ArgStringList &CC1Args)
const {
1329 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1330 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1331 options::OPT_no_offload_inc,
true) &&
1332 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1333 !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1335 llvm::sys::path::append(P,
"include",
"hip_wrappers");
1336 CC1Args.push_back(
"-internal-isystem");
1337 CC1Args.push_back(DriverArgs.MakeArgString(P));
1346 const ArgList &Args)
const {
1348 return HostTC->computeMSVCVersion(D, Args);
1360 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1361 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1367 std::optional<llvm::AMDGPU::TargetID> ID =
1368 llvm::AMDGPU::TargetID::parse(TT, TargetID);
1371 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
1372 llvm::AMDGPU::getFeatureBitset(ID->getGPUKind());
1376 if (Features.test(llvm::AMDGPU::FEAT_XNACK_SUPPORT) &&
1377 !Features.test(llvm::AMDGPU::FEAT_XNACK_ON_OFF_MODES))
1381 return ID->getXnackSetting() == llvm::AMDGPU::TargetIDSetting::On;
1392 SupportedMask |= SanitizerKind::Address;
1394 return SupportedMask;
1400 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())))
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()