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,
",")));
672 if (Args.hasArg(options::OPT_stdlib))
673 CmdArgs.append({
"-lc",
"-lm"});
674 if (Args.hasArg(options::OPT_startfiles)) {
675 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
677 IncludePath =
"/lib";
679 llvm::sys::path::append(P,
"crt1.o");
680 CmdArgs.push_back(Args.MakeArgString(P));
683 CmdArgs.push_back(
"-o");
685 C.addCommand(std::make_unique<Command>(
687 CmdArgs, Inputs, Output));
691 const llvm::Triple &Triple,
692 const llvm::opt::ArgList &Args,
693 std::vector<StringRef> &Features,
695 if (Args.hasFlag(options::OPT_mwavefrontsize64,
696 options::OPT_mno_wavefrontsize64,
false))
697 Features.push_back(
"+wavefrontsize64");
699 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
700 options::OPT_mno_amdgpu_precise_memory_op,
false))
701 Features.push_back(
"+precise-memory");
706 if (Arg *A = Args.getLastArg(options::OPT_mxnack, options::OPT_mno_xnack)) {
708 A->getOption().matches(options::OPT_mxnack) ?
"+xnack" :
"-xnack");
712 Args.getLastArg(options::OPT_msramecc, options::OPT_mno_sramecc)) {
713 Features.push_back(A->getOption().matches(options::OPT_msramecc)
720 options::OPT_m_amdgpu_Features_Group);
725 const ArgList &Args,
const ToolChain *HostTC_,
730 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}),
732 ShouldLinkDeviceLibs(ShouldLinkDeviceLibs) {
733 loadMultilibsFromYAML(Args, D);
741 bool UsesLLVMOffloading = Args.hasFlag(
742 options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm,
false);
743 if (Triple.getOS() == llvm::Triple::AMDHSA &&
744 Triple.getEnvironment() != llvm::Triple::LLVM && !UsesLLVMOffloading)
745 RocmInstallation->detectDeviceLibrary();
748 getProgramPaths().push_back(getDriver().Dir);
763 DAL =
new DerivedArgList(Args.getBaseArgs());
772 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
773 DAL->eraseArg(options::OPT_march_EQ);
774 if (!DAL->hasArg(options::OPT_mcpu_EQ))
775 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
781 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
782 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
783 DAL->eraseArg(options::OPT_mcpu_EQ);
787 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
789 auto &GPUs = *GPUsOrErr;
790 if (!llvm::all_equal(GPUs))
792 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
793 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
794 Args.MakeArgString(GPUs.front()));
799 DAL->eraseArg(options::OPT_mcpu_EQ);
800 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
811 auto XnackIt = FeatureMap.find(
"xnack");
812 if (XnackIt != FeatureMap.end()) {
813 DAL->AddFlagArg(
nullptr, Opts.getOption(XnackIt->second
814 ? options::OPT_mxnack
815 : options::OPT_mno_xnack));
818 auto SrameccIt = FeatureMap.find(
"sramecc");
819 if (SrameccIt != FeatureMap.end()) {
820 DAL->AddFlagArg(
nullptr,
821 Opts.getOption(SrameccIt->second
822 ? options::OPT_msramecc
823 : 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));
1044 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1045 if (TargetID.empty())
1048 llvm::StringMap<bool> FeatureMap;
1050 if (!OptionalGpuArch)
1051 return {TargetID.str(), std::nullopt, std::nullopt};
1053 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
1059 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
1061 << *PTID.OptionalTargetID;
1065 if (
getTriple().getSubArch() != llvm::Triple::NoSubArch &&
1066 PTID.OptionalGPUArch) {
1067 llvm::AMDGPU::GPUKind Kind =
1068 llvm::AMDGPU::parseArchAMDGCN(*PTID.OptionalGPUArch);
1069 llvm::Triple::SubArchType KindSubArch =
1070 static_cast<llvm::Triple::SubArchType
>(llvm::AMDGPU::getSubArch(Kind));
1071 if (
getTriple().getSubArch() != KindSubArch &&
1073 llvm::AMDGPU::getMajorSubArch(KindSubArch)) {
1075 << *PTID.OptionalGPUArch <<
getTriple().getArchName();
1084 std::string Program;
1085 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
1086 Program = A->getValue();
1092 return StdoutOrErr.takeError();
1095 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
1097 GPUArchs.push_back(
Arch.str());
1099 if (GPUArchs.empty())
1100 return llvm::createStringError(std::error_code(),
1101 "No AMD GPU detected in the system");
1103 return std::move(GPUArchs);
1107 StringRef GPUArch, StringRef LibDeviceFile,
1110 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1113 if (LibDeviceFile.empty()) {
1114 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1121 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1123 D.Diag(diag::err_drv_no_rocm_device_lib)
1124 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1132 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1134 const bool NeedsASanRT)
const {
1137 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1138 DeviceOffloadingKind, NeedsASanRT};
1141 bool Internalize =
true) {
1142 if (!BCLib.
Path.empty()) {
1144 BCLibs.emplace_back(BCLib);
1147 auto AddSanBCLibs = [&]() {
1156 else if (Pref.GPUSan && Pref.IsOpenMP)
1161 AddBCLib(LibDeviceFile);
1163 if (!ABIVerPath.empty())
1164 AddBCLib(ABIVerPath);
1171 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1173 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1174 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1184 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1194 "spirv should not try to link device libs");
1196 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1207 TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1219 auto BCLibArgs = DriverArgs.getAllArgValues(options::OPT_hip_device_lib_EQ);
1220 if (!BCLibArgs.empty()) {
1221 ArgStringList LibraryPaths;
1223 LibraryPaths.push_back(DriverArgs.MakeArgStringRef(Path));
1226 for (StringRef BCName : BCLibArgs) {
1228 for (StringRef LibraryPath : LibraryPaths) {
1230 llvm::sys::path::append(Path, BCName);
1231 if (llvm::sys::fs::exists(Path)) {
1232 BCLibs.emplace_back(Path);
1251 BCLibs.emplace_back(N);
1255 DriverArgs.getLastArgValue(options::OPT_gpu_instrument_lib_EQ);
1256 if (!InstLib.empty()) {
1257 if (llvm::sys::fs::exists(InstLib))
1258 BCLibs.emplace_back(InstLib);
1270 BCLibs.emplace_back(BCLib);
1286 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1294 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadKind,
1304 return HostTC->GetCXXStdlibType(Args);
1309 const ArgList &Args, ArgStringList &CC1Args)
const {
1311 HostTC->AddClangCXXStdlibIncludeArgs(Args, CC1Args);
1317 ArgStringList &CC1Args)
const {
1319 HostTC->AddIAMCUIncludeArgs(Args, CC1Args);
1323 ArgStringList &CC1Args)
const {
1324 if (
getTriple().getEnvironment() == llvm::Triple::LLVM) {
1325 if (DriverArgs.hasFlag(options::OPT_offload_inc,
1326 options::OPT_no_offload_inc,
true) &&
1327 !DriverArgs.hasArg(options::OPT_nohipwrapperinc) &&
1328 !DriverArgs.hasArg(options::OPT_nobuiltininc)) {
1330 llvm::sys::path::append(P,
"include",
"hip_wrappers");
1331 CC1Args.push_back(
"-internal-isystem");
1332 CC1Args.push_back(DriverArgs.MakeArgString(P));
1341 const ArgList &Args)
const {
1343 return HostTC->computeMSVCVersion(D, Args);
1355 !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false) &&
1356 !Args.hasArg(options::OPT_foffload_lto, options::OPT_foffload_lto_EQ))
1366 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Processor);
1367 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
1368 llvm::AMDGPU::getFeatureBitset(ProcKind);
1371 bool XnackAlwaysOn = Features.test(llvm::AMDGPU::FEAT_XNACK_SUPPORT) &&
1372 !Features.test(llvm::AMDGPU::FEAT_XNACK_ON_OFF_MODES);
1377 llvm::StringMap<bool> FeatureMap;
1378 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1379 if (!OptionalGpuArch)
1381 auto Loc = FeatureMap.find(
"xnack");
1382 return (Loc != FeatureMap.end() && Loc->second);
1393 SupportedMask |= SanitizerKind::Address;
1395 return SupportedMask;
1401 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()