11#include "clang/Config/config.h"
18#include "llvm/ADT/SmallSet.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Support/Error.h"
22#include "llvm/Support/LineIterator.h"
23#include "llvm/Support/Path.h"
24#include "llvm/Support/Process.h"
25#include "llvm/Support/VirtualFileSystem.h"
26#include "llvm/TargetParser/AMDGPUTargetParser.h"
27#include "llvm/TargetParser/Host.h"
29#include <system_error>
37RocmInstallationDetector::CommonBitcodeLibsPreferences::
38 CommonBitcodeLibsPreferences(
const Driver &D,
39 const llvm::opt::ArgList &DriverArgs,
42 const bool NeedsASanRT)
45 const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
46 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
50 const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
52 !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
53 options::OPT_mno_wavefrontsize64,
false);
60 const bool DefaultDAZ =
61 (Kind == llvm::AMDGPU::GK_NONE)
63 : !((ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_FMA_F32) &&
64 (ArchAttr &
llvm::
AMDGPU::FEATURE_FAST_DENORMAL_F32));
67 DAZ = IsKnownOffloading
68 ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
69 options::OPT_fno_gpu_flush_denormals_to_zero,
71 : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
73 FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
74 DriverArgs.hasFlag(options::OPT_ffinite_math_only,
75 options::OPT_fno_finite_math_only,
false);
78 DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
79 DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
80 options::OPT_fno_unsafe_math_optimizations,
false);
82 FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
83 DriverArgs.hasFlag(options::OPT_ffast_math,
84 options::OPT_fno_fast_math,
false);
88 GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
89 options::OPT_fno_gpu_sanitize,
true) &&
93void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
94 assert(!Path.empty());
96 const StringRef Suffix(
".bc");
97 const StringRef Suffix2(
".amdgcn.bc");
100 for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(Path, EC), LE;
101 !EC && LI != LE; LI = LI.increment(EC)) {
102 StringRef FilePath = LI->path();
103 StringRef
FileName = llvm::sys::path::filename(FilePath);
109 BaseName =
FileName.drop_back(Suffix2.size());
110 else if (
FileName.ends_with(Suffix))
111 BaseName =
FileName.drop_back(Suffix.size());
113 const StringRef ABIVersionPrefix =
"oclc_abi_version_";
114 if (BaseName ==
"ocml") {
116 }
else if (BaseName ==
"ockl") {
118 }
else if (BaseName ==
"opencl") {
120 }
else if (BaseName ==
"asanrtl") {
122 }
else if (BaseName ==
"oclc_finite_only_off") {
123 FiniteOnly.Off = FilePath;
124 }
else if (BaseName ==
"oclc_finite_only_on") {
125 FiniteOnly.On = FilePath;
126 }
else if (BaseName ==
"oclc_unsafe_math_on") {
127 UnsafeMath.On = FilePath;
128 }
else if (BaseName ==
"oclc_unsafe_math_off") {
129 UnsafeMath.Off = FilePath;
130 }
else if (BaseName ==
"oclc_wavefrontsize64_on") {
131 WavefrontSize64.On = FilePath;
132 }
else if (BaseName ==
"oclc_wavefrontsize64_off") {
133 WavefrontSize64.Off = FilePath;
134 }
else if (BaseName.starts_with(ABIVersionPrefix)) {
135 unsigned ABIVersionNumber;
136 if (BaseName.drop_front(ABIVersionPrefix.size())
137 .getAsInteger(0, ABIVersionNumber))
139 ABIVersionMap[ABIVersionNumber] = FilePath.str();
143 const StringRef DeviceLibPrefix =
"oclc_isa_version_";
144 if (!BaseName.starts_with(DeviceLibPrefix))
147 StringRef IsaVersionNumber =
148 BaseName.drop_front(DeviceLibPrefix.size());
150 llvm::Twine GfxName = Twine(
"gfx") + IsaVersionNumber;
152 LibDeviceMap.insert({GfxName.toStringRef(Tmp), FilePath.str()});
159bool RocmInstallationDetector::parseHIPVersionFile(llvm::StringRef
V) {
160 SmallVector<StringRef, 4> VersionParts;
161 V.split(VersionParts,
'\n');
162 unsigned Major = ~0U;
163 unsigned Minor = ~0U;
164 for (
auto Part : VersionParts) {
165 auto Splits = Part.rtrim().split(
'=');
166 if (Splits.first ==
"HIP_VERSION_MAJOR") {
167 if (Splits.second.getAsInteger(0, Major))
169 }
else if (Splits.first ==
"HIP_VERSION_MINOR") {
170 if (Splits.second.getAsInteger(0, Minor))
172 }
else if (Splits.first ==
"HIP_VERSION_PATCH")
173 VersionPatch = Splits.second.str();
175 if (Major == ~0U || Minor == ~0U)
177 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
179 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
185const SmallVectorImpl<RocmInstallationDetector::Candidate> &
186RocmInstallationDetector::getInstallationPathCandidates() {
189 if (!ROCmSearchDirs.empty())
190 return ROCmSearchDirs;
192 auto DoPrintROCmSearchDirs = [&]() {
193 if (PrintROCmSearchDirs)
194 for (
auto Cand : ROCmSearchDirs) {
195 llvm::errs() <<
"ROCm installation search path: " << Cand.Path <<
'\n';
201 if (!RocmPathArg.empty()) {
202 ROCmSearchDirs.emplace_back(RocmPathArg.str());
203 DoPrintROCmSearchDirs();
204 return ROCmSearchDirs;
205 }
else if (std::optional<std::string> RocmPathEnv =
206 llvm::sys::Process::GetEnv(
"ROCM_PATH")) {
207 if (!RocmPathEnv->empty()) {
208 ROCmSearchDirs.emplace_back(std::move(*RocmPathEnv));
209 DoPrintROCmSearchDirs();
210 return ROCmSearchDirs;
215 StringRef InstallDir = D.Dir;
220 auto DeduceROCmPath = [](StringRef ClangPath) {
222 StringRef ParentDir = llvm::sys::path::parent_path(ClangPath);
223 StringRef ParentName = llvm::sys::path::filename(ParentDir);
226 if (ParentName ==
"bin") {
227 ParentDir = llvm::sys::path::parent_path(ParentDir);
228 ParentName = llvm::sys::path::filename(ParentDir);
233 if (ParentName ==
"llvm" || ParentName.starts_with(
"aomp")) {
234 ParentDir = llvm::sys::path::parent_path(ParentDir);
235 ParentName = llvm::sys::path::filename(ParentDir);
239 if (ParentName ==
"lib")
240 ParentDir = llvm::sys::path::parent_path(ParentDir);
243 return Candidate(ParentDir.str(),
true);
248 ROCmSearchDirs.emplace_back(DeduceROCmPath(InstallDir));
252 llvm::SmallString<256> RealClangPath;
253 llvm::sys::fs::real_path(D.getDriverProgramPath(), RealClangPath);
254 auto ParentPath = llvm::sys::path::parent_path(RealClangPath);
255 if (ParentPath != InstallDir)
256 ROCmSearchDirs.emplace_back(DeduceROCmPath(ParentPath));
259 auto ClangRoot = llvm::sys::path::parent_path(InstallDir);
260 auto RealClangRoot = llvm::sys::path::parent_path(ParentPath);
261 ROCmSearchDirs.emplace_back(ClangRoot.str(),
true);
262 if (RealClangRoot != ClangRoot)
263 ROCmSearchDirs.emplace_back(RealClangRoot.str(),
true);
264 ROCmSearchDirs.emplace_back(D.ResourceDir,
267 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/rocm",
272 std::string LatestROCm;
273 llvm::VersionTuple LatestVer;
275 auto GetROCmVersion = [](StringRef DirName) {
276 llvm::VersionTuple
V;
277 std::string VerStr = DirName.drop_front(strlen(
"rocm-")).str();
280 llvm::replace(VerStr,
'-',
'.');
284 for (llvm::vfs::directory_iterator
285 File = D.getVFS().dir_begin(D.SysRoot +
"/opt", EC),
287 File != FileEnd && !EC;
File.increment(EC)) {
288 llvm::StringRef
FileName = llvm::sys::path::filename(
File->path());
291 if (LatestROCm.empty()) {
293 LatestVer = GetROCmVersion(LatestROCm);
296 auto Ver = GetROCmVersion(
FileName);
297 if (LatestVer < Ver) {
302 if (!LatestROCm.empty())
303 ROCmSearchDirs.emplace_back(D.SysRoot +
"/opt/" + LatestROCm,
306 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr/local",
308 ROCmSearchDirs.emplace_back(D.SysRoot +
"/usr",
311 DoPrintROCmSearchDirs();
312 return ROCmSearchDirs;
316 const Driver &D,
const llvm::Triple &HostTriple,
317 const llvm::opt::ArgList &Args,
bool DetectHIPRuntime)
319 Verbose = Args.hasArg(options::OPT_v);
320 RocmPathArg = Args.getLastArgValue(options::OPT_rocm_path_EQ);
321 PrintROCmSearchDirs = Args.hasArg(options::OPT_print_rocm_search_dirs);
322 RocmDeviceLibPathArg =
323 Args.getAllArgValues(options::OPT_rocm_device_lib_path_EQ);
324 HIPPathArg = Args.getLastArgValue(options::OPT_hip_path_EQ);
325 HIPStdParPathArg = Args.getLastArgValue(options::OPT_hipstdpar_path_EQ);
326 HasHIPStdParLibrary =
327 !HIPStdParPathArg.empty() && D.getVFS().exists(HIPStdParPathArg +
328 "/hipstdpar_lib.hpp");
329 HIPRocThrustPathArg =
330 Args.getLastArgValue(options::OPT_hipstdpar_thrust_path_EQ);
331 HasRocThrustLibrary = !HIPRocThrustPathArg.empty() &&
332 D.getVFS().exists(HIPRocThrustPathArg +
"/thrust");
333 HIPRocPrimPathArg = Args.getLastArgValue(options::OPT_hipstdpar_prim_path_EQ);
334 HasRocPrimLibrary = !HIPRocPrimPathArg.empty() &&
335 D.getVFS().exists(HIPRocPrimPathArg +
"/rocprim");
337 if (
auto *A = Args.getLastArg(options::OPT_hip_version_EQ)) {
338 HIPVersionArg = A->getValue();
339 unsigned Major = ~0U;
340 unsigned Minor = ~0U;
341 SmallVector<StringRef, 3> Parts;
342 HIPVersionArg.split(Parts,
'.');
344 Parts[0].getAsInteger(0, Major);
345 if (Parts.size() > 1)
346 Parts[1].getAsInteger(0, Minor);
347 if (Parts.size() > 2)
348 VersionPatch = Parts[2].str();
349 if (VersionPatch.empty())
351 if (Major != ~0U && Minor == ~0U)
353 if (Major == ~0U || Minor == ~0U)
354 D.Diag(diag::err_drv_invalid_value)
355 << A->getAsString(Args) << HIPVersionArg;
357 VersionMajorMinor = llvm::VersionTuple(Major, Minor);
359 (Twine(Major) +
"." + Twine(Minor) +
"." + VersionPatch).str();
361 VersionPatch = DefaultVersionPatch;
363 llvm::VersionTuple(DefaultVersionMajor, DefaultVersionMinor);
364 DetectedVersion = (Twine(DefaultVersionMajor) +
"." +
365 Twine(DefaultVersionMinor) +
"." + VersionPatch)
369 if (DetectHIPRuntime)
374 assert(LibDevicePath.empty());
376 if (!RocmDeviceLibPathArg.empty())
377 LibDevicePath = RocmDeviceLibPathArg.back();
378 else if (std::optional<std::string> LibPathEnv =
379 llvm::sys::Process::GetEnv(
"HIP_DEVICE_LIB_PATH"))
380 LibDevicePath = std::move(*LibPathEnv);
382 auto &FS = D.getVFS();
383 if (!LibDevicePath.empty()) {
387 if (!FS.exists(LibDevicePath))
390 scanLibDevicePath(LibDevicePath);
391 HasDeviceLibrary = allGenericLibsValid() && !LibDeviceMap.empty();
396 auto CheckDeviceLib = [&](StringRef Path,
bool StrictChecking) {
397 bool CheckLibDevice = (!NoBuiltinLibs || StrictChecking);
398 if (CheckLibDevice && !FS.exists(Path))
401 scanLibDevicePath(Path);
403 if (!NoBuiltinLibs) {
405 if (!allGenericLibsValid())
410 if (LibDeviceMap.empty())
417 LibDevicePath = D.ResourceDir;
418 llvm::sys::path::append(LibDevicePath, CLANG_INSTALL_LIBDIR_BASENAME,
419 "amdgcn",
"bitcode");
420 HasDeviceLibrary = CheckDeviceLib(LibDevicePath,
true);
421 if (HasDeviceLibrary)
426 auto &ROCmDirs = getInstallationPathCandidates();
427 for (
const auto &Candidate : ROCmDirs) {
428 LibDevicePath = Candidate.Path;
429 llvm::sys::path::append(LibDevicePath,
"amdgcn",
"bitcode");
430 HasDeviceLibrary = CheckDeviceLib(LibDevicePath, Candidate.StrictChecking);
431 if (HasDeviceLibrary)
438 if (!HIPPathArg.empty())
439 HIPSearchDirs.emplace_back(HIPPathArg.str());
440 else if (std::optional<std::string> HIPPathEnv =
441 llvm::sys::Process::GetEnv(
"HIP_PATH")) {
442 if (!HIPPathEnv->empty())
443 HIPSearchDirs.emplace_back(std::move(*HIPPathEnv));
445 if (HIPSearchDirs.empty())
446 HIPSearchDirs.append(getInstallationPathCandidates());
447 auto &FS = D.getVFS();
449 for (
const auto &Candidate : HIPSearchDirs) {
450 InstallPath = Candidate.Path;
451 if (InstallPath.empty() || !FS.exists(InstallPath))
454 BinPath = InstallPath;
455 llvm::sys::path::append(BinPath,
"bin");
456 IncludePath = InstallPath;
457 llvm::sys::path::append(IncludePath,
"include");
458 LibPath = InstallPath;
459 llvm::sys::path::append(LibPath,
"lib");
460 SharePath = InstallPath;
461 llvm::sys::path::append(SharePath,
"share");
464 SmallString<0> ParentSharePath = llvm::sys::path::parent_path(InstallPath);
465 llvm::sys::path::append(ParentSharePath,
"share");
468 const Twine &c =
"",
const Twine &d =
"") {
470 llvm::sys::path::append(newpath, a, b, c, d);
474 std::vector<SmallString<0>> VersionFilePaths = {
475 Append(SharePath,
"hip",
"version"),
476 InstallPath != D.SysRoot +
"/usr/local"
477 ?
Append(ParentSharePath,
"hip",
"version")
479 Append(BinPath,
".hipVersion")};
481 for (
const auto &VersionFilePath : VersionFilePaths) {
482 if (VersionFilePath.empty())
484 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
485 FS.getBufferForFile(VersionFilePath);
488 if (HIPVersionArg.empty() && VersionFile)
489 if (parseHIPVersionFile((*VersionFile)->getBuffer()))
492 HasHIPRuntime =
true;
497 if (!Candidate.StrictChecking) {
498 HasHIPRuntime =
true;
502 HasHIPRuntime =
false;
507 OS <<
"Found HIP installation: " << InstallPath <<
", version "
508 << DetectedVersion <<
'\n';
512 ArgStringList &CC1Args)
const {
513 bool UsesRuntimeWrapper = VersionMajorMinor > llvm::VersionTuple(3, 5) &&
514 !DriverArgs.hasArg(options::OPT_nohipwrapperinc);
515 bool HasHipStdPar = DriverArgs.hasArg(options::OPT_hipstdpar);
517 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
532 if (UsesRuntimeWrapper)
533 llvm::sys::path::append(P,
"include",
"cuda_wrappers");
534 CC1Args.push_back(
"-internal-isystem");
535 CC1Args.push_back(DriverArgs.MakeArgString(P));
538 const auto HandleHipStdPar = [=, &DriverArgs, &CC1Args]() {
540 auto &FS = D.getVFS();
543 if (!HIPStdParPathArg.empty() ||
544 !FS.exists(Inc +
"/thrust/system/hip/hipstdpar/hipstdpar_lib.hpp")) {
545 D.Diag(diag::err_drv_no_hipstdpar_lib);
548 if (!HasRocThrustLibrary && !FS.exists(Inc +
"/thrust")) {
549 D.Diag(diag::err_drv_no_hipstdpar_thrust_lib);
552 if (!HasRocPrimLibrary && !FS.exists(Inc +
"/rocprim")) {
553 D.Diag(diag::err_drv_no_hipstdpar_prim_lib);
556 const char *ThrustPath;
557 if (HasRocThrustLibrary)
558 ThrustPath = DriverArgs.MakeArgString(HIPRocThrustPathArg);
560 ThrustPath = DriverArgs.MakeArgString(Inc +
"/thrust");
562 const char *HIPStdParPath;
564 HIPStdParPath = DriverArgs.MakeArgString(HIPStdParPathArg);
566 HIPStdParPath = DriverArgs.MakeArgString(StringRef(ThrustPath) +
567 "/system/hip/hipstdpar");
569 const char *PrimPath;
570 if (HasRocPrimLibrary)
571 PrimPath = DriverArgs.MakeArgString(HIPRocPrimPathArg);
573 PrimPath = DriverArgs.MakeArgString(
getIncludePath() +
"/rocprim");
575 CC1Args.append({
"-idirafter", ThrustPath,
"-idirafter", PrimPath,
576 "-idirafter", HIPStdParPath,
"-include",
577 "hipstdpar_lib.hpp"});
580 if (!DriverArgs.hasFlag(options::OPT_offload_inc, options::OPT_no_offload_inc,
589 D.Diag(diag::err_drv_no_hip_runtime);
593 CC1Args.push_back(
"-idirafter");
595 if (UsesRuntimeWrapper)
596 CC1Args.append({
"-include",
"__clang_hip_runtime_wrapper.h"});
605 const char *LinkingOutput)
const {
607 ArgStringList CmdArgs;
608 if (!Args.hasArg(options::OPT_r)) {
609 CmdArgs.push_back(
"--no-undefined");
610 CmdArgs.push_back(
"-shared");
616 }
else if (Args.hasArg(options::OPT_mcpu_EQ)) {
617 CmdArgs.push_back(Args.MakeArgString(
618 "-plugin-opt=mcpu=" +
620 Args.getLastArgValue(options::OPT_mcpu_EQ))));
624 Args.AddAllArgs(CmdArgs, options::OPT_L);
628 std::vector<StringRef> Features;
631 if (!Features.empty()) {
633 Args.MakeArgString(
"-plugin-opt=-mattr=" + llvm::join(Features,
",")));
639 if (Args.hasArg(options::OPT_stdlib))
640 CmdArgs.append({
"-lc",
"-lm"});
641 if (Args.hasArg(options::OPT_startfiles)) {
642 std::optional<std::string> IncludePath =
getToolChain().getStdlibPath();
644 IncludePath =
"/lib";
646 llvm::sys::path::append(P,
"crt1.o");
647 CmdArgs.push_back(Args.MakeArgString(P));
650 CmdArgs.push_back(
"-o");
652 C.addCommand(std::make_unique<Command>(
654 CmdArgs, Inputs, Output));
658 const llvm::Triple &Triple,
659 const llvm::opt::ArgList &Args,
660 std::vector<StringRef> &Features) {
661 if (Args.hasFlag(options::OPT_mwavefrontsize64,
662 options::OPT_mno_wavefrontsize64,
false))
663 Features.push_back(
"+wavefrontsize64");
665 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
666 options::OPT_mno_amdgpu_precise_memory_op,
false))
667 Features.push_back(
"+precise-memory");
670 options::OPT_m_amdgpu_Features_Group);
678 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}) {
679 loadMultilibsFromYAML(Args, D);
697 DAL =
new DerivedArgList(Args.getBaseArgs());
706 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
707 DAL->eraseArg(options::OPT_march_EQ);
708 if (!DAL->hasArg(options::OPT_mcpu_EQ))
709 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
715 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
716 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
717 DAL->eraseArg(options::OPT_mcpu_EQ);
721 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
723 auto &GPUs = *GPUsOrErr;
724 if (!llvm::all_equal(GPUs))
726 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
727 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
728 Args.MakeArgString(GPUs.front()));
733 DAL->eraseArg(options::OPT_mcpu_EQ);
734 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
744 auto XnackIt = FeatureMap.find(
"xnack");
745 if (XnackIt != FeatureMap.end()) {
746 DAL->AddFlagArg(
nullptr,
747 Opts.getOption(XnackIt->second ? options::OPT_mxnack
748 : options::OPT_mno_xnack));
751 auto SrameccIt = FeatureMap.find(
"sramecc");
752 if (SrameccIt != FeatureMap.end()) {
753 DAL->AddFlagArg(
nullptr, Opts.getOption(SrameccIt->second
754 ? options::OPT_msramecc
755 : options::OPT_mno_sramecc));
759 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
763 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
766 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
768 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
776 llvm::AMDGPU::GPUKind Kind) {
779 if (Kind == llvm::AMDGPU::GK_NONE)
782 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
786 const bool BothDenormAndFMAFast =
787 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
788 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
789 return !BothDenormAndFMAFast;
793 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
794 const llvm::fltSemantics *FPType)
const {
796 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
797 return llvm::DenormalMode::getIEEE();
804 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
805 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
806 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
807 options::OPT_fno_gpu_flush_denormals_to_zero,
809 return llvm::DenormalMode::getPreserveSign();
811 return llvm::DenormalMode::getIEEE();
814 const StringRef GpuArch =
getGPUArch(DriverArgs);
815 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
819 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
824 return DAZ ? llvm::DenormalMode::getPreserveSign() :
825 llvm::DenormalMode::getIEEE();
829 llvm::AMDGPU::GPUKind Kind) {
830 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
831 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
833 return !HasWave32 || DriverArgs.hasFlag(
834 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
842 if (Triple.getEnvironment() != llvm::Triple::LLVM)
849 DerivedArgList *DAL =
853 for (Arg *A : Args) {
855 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
857 bool IsExplicitDevice =
858 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
860 ? diag::err_drv_unsupported_option_for_target
861 : diag::warn_drv_unsupported_option_for_target)
862 << A->getAsString(Args) <<
getTriple().str();
870 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
875 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
876 options::OPT_fvisibility_ms_compat) &&
878 CC1Args.push_back(
"-fvisibility=hidden");
879 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
893 !DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
894 CC1Args.push_back(
"-disable-llvm-optzns");
903 CC1Args.push_back(
"-Werror=atomic-alignment");
907 ArgStringList &CC1Args)
const {
908 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
909 DriverArgs.hasArg(options::OPT_nostdlibinc))
918 llvm::sys::path::append(Dir, M.includeSuffix());
931 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
936 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
937 if (TargetID.empty())
940 llvm::StringMap<bool> FeatureMap;
942 if (!OptionalGpuArch)
943 return {TargetID.str(), std::nullopt, std::nullopt};
945 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
951 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
953 << *PTID.OptionalTargetID;
962 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
963 Program = A->getValue();
969 return StdoutOrErr.takeError();
972 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
974 GPUArchs.push_back(
Arch.str());
976 if (GPUArchs.empty())
977 return llvm::createStringError(std::error_code(),
978 "No AMD GPU detected in the system");
980 return std::move(GPUArchs);
984 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
987 DeviceOffloadingKind);
992 DriverArgs.hasArg(options::OPT_nostdlib))
995 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1007 if (TT.getEnvironment() == llvm::Triple::LLVM)
1013 StringRef TargetID =
1014 BA ? BA.
ArchName : DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
1021 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1030 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
1034 for (
auto [BCFile, Internalize] : BCLibs) {
1036 CC1Args.push_back(
"-mlink-builtin-bitcode");
1038 CC1Args.push_back(
"-mlink-bitcode-file");
1039 CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
1044 StringRef GPUArch, StringRef LibDeviceFile,
1047 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1050 if (LibDeviceFile.empty()) {
1051 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1058 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1060 D.Diag(diag::err_drv_no_rocm_device_lib)
1061 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1069 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1071 const bool NeedsASanRT)
const {
1074 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1075 DeviceOffloadingKind, NeedsASanRT};
1078 bool Internalize =
true) {
1079 if (!BCLib.
Path.empty()) {
1081 BCLibs.emplace_back(BCLib);
1084 auto AddSanBCLibs = [&]() {
1093 else if (Pref.GPUSan && Pref.IsOpenMP)
1098 AddBCLib(LibDeviceFile);
1100 if (!ABIVerPath.empty())
1101 AddBCLib(ABIVerPath);
1108 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1110 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1111 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1121 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1129 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1130 : llvm::AMDGPU::parseArchR600(Processor);
1131 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1132 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1135 bool XnackAlwaysOn = (Features & llvm::AMDGPU::FEATURE_XNACK) &&
1136 !(Features & llvm::AMDGPU::FEATURE_XNACK_ON_OFF_MODES);
1141 llvm::StringMap<bool> FeatureMap;
1142 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1143 if (!OptionalGpuArch)
1145 auto Loc = FeatureMap.find(
"xnack");
1146 return (Loc != FeatureMap.end() && Loc->second);
1157 SupportedMask |= SanitizerKind::Address;
1159 return SupportedMask;
1165 if ((Kinds & SanitizerKind::Address) && BA &&
static StringRef getTriple(const Command &Job)
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)
BoundArch getOffloadingArch() const
OffloadKind getOffloadingDeviceKind() const
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > executeProgram(llvm::ArrayRef< llvm::StringRef > Args) const
DiagnosticBuilder Diag(unsigned DiagID) const
const llvm::opt::OptTable & getOpts() const
This corresponds to a single GCC Multilib, or a segment of one controlled by a command line flag.
StringRef getIncludePath() const
Get the detected path to Rocm's bin directory.
StringRef getUnsafeMathPath(bool Enabled) const
StringRef getOCMLPath() const
StringRef getAsanRTLPath() const
Returns empty string of Asan runtime library is not available.
RocmInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, const llvm::opt::ArgList &Args, bool DetectHIPRuntime=true)
StringRef getOCKLPath() const
StringRef getFiniteOnlyPath(bool Enabled) const
bool hasDeviceLibrary() const
Check whether we detected a valid ROCm device library.
bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, DeviceLibABIVersion ABIVer) const
Check file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPStdParLibrary() const
Check whether we detected a valid HIP STDPAR Acceleration library.
StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const
llvm::SmallVector< ToolChain::BitCodeLibraryInfo, 12 > getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, StringRef GPUArch, const Action::OffloadKind DeviceOffloadingKind, const bool NeedsASanRT) const
Get file paths of default bitcode libraries common to AMDGPU based toolchains.
bool hasHIPRuntime() const
Check whether we detected a valid HIP runtime.
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
void detectDeviceLibrary()
StringRef getWavefrontSize64Path(bool Enabled) const
void print(raw_ostream &OS) const
Print information about the detected ROCm installation.
SmallVector< InputInfo, 4 > InputInfoList
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
std::optional< llvm::StringRef > parseTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch, llvm::StringMap< bool > *FeatureMap)
Parse a target ID to get processor and feature map.
llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch)
Get processor name from target ID.
Diagnostic wrappers for TextAPI types for error reporting.
Represents a bound architecture for offload / multiple architecture compilation.
ABI version of device library.
unsigned getAsCodeObjectVersion() const
static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion)
bool requiresLibrary()
Whether ABI version bc file is requested.
static constexpr ResponseFileSupport AtFileCurCP()