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) {
663 StringRef TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
664 if (!TargetID.empty()) {
665 llvm::StringMap<bool> FeatureMap;
666 auto OptionalGpuArch =
parseTargetID(Triple, TargetID, &FeatureMap);
667 if (OptionalGpuArch) {
668 StringRef GpuArch = *OptionalGpuArch;
674 auto Pos = FeatureMap.find(
Feature);
675 if (Pos == FeatureMap.end())
677 Features.push_back(Args.MakeArgStringRef(
678 (Twine(Pos->second ?
"+" :
"-") +
Feature).str()));
683 if (Args.hasFlag(options::OPT_mwavefrontsize64,
684 options::OPT_mno_wavefrontsize64,
false))
685 Features.push_back(
"+wavefrontsize64");
687 if (Args.hasFlag(options::OPT_mamdgpu_precise_memory_op,
688 options::OPT_mno_amdgpu_precise_memory_op,
false))
689 Features.push_back(
"+precise-memory");
692 options::OPT_m_amdgpu_Features_Group);
700 {{options::OPT_O,
"3"}, {options::OPT_cl_std_EQ,
"CL1.2"}}) {
701 loadMultilibsFromYAML(Args, D);
718 DerivedArgList *DAL =
724 DAL =
new DerivedArgList(Args.getBaseArgs());
730 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
731 DAL->eraseArg(options::OPT_march_EQ);
732 if (!DAL->hasArg(options::OPT_mcpu_EQ))
733 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ), A->getValue());
737 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
738 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
739 DAL->eraseArg(options::OPT_mcpu_EQ);
743 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
745 auto &GPUs = *GPUsOrErr;
746 if (!llvm::all_equal(GPUs))
748 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
749 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
750 Args.MakeArgString(GPUs.front()));
756 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
760 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
763 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
765 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
773 llvm::AMDGPU::GPUKind Kind) {
776 if (Kind == llvm::AMDGPU::GK_NONE)
779 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
783 const bool BothDenormAndFMAFast =
784 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
785 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
786 return !BothDenormAndFMAFast;
790 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
791 const llvm::fltSemantics *FPType)
const {
793 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
794 return llvm::DenormalMode::getIEEE();
799 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
800 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
801 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
802 options::OPT_fno_gpu_flush_denormals_to_zero,
804 return llvm::DenormalMode::getPreserveSign();
806 return llvm::DenormalMode::getIEEE();
809 const StringRef GpuArch =
getGPUArch(DriverArgs);
810 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
814 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
819 return DAZ ? llvm::DenormalMode::getPreserveSign() :
820 llvm::DenormalMode::getIEEE();
824 llvm::AMDGPU::GPUKind Kind) {
825 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
826 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
828 return !HasWave32 || DriverArgs.hasFlag(
829 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
837 if (Triple.getEnvironment() != llvm::Triple::LLVM)
842 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
847 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
848 options::OPT_fvisibility_ms_compat) &&
850 CC1Args.push_back(
"-fvisibility=hidden");
851 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
865 !DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
866 CC1Args.push_back(
"-disable-llvm-optzns");
875 CC1Args.push_back(
"-Werror=atomic-alignment");
879 ArgStringList &CC1Args)
const {
880 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
881 DriverArgs.hasArg(options::OPT_nostdlibinc))
890 llvm::sys::path::append(Dir, M.includeSuffix());
903 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
908 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
909 if (TargetID.empty())
912 llvm::StringMap<bool> FeatureMap;
914 if (!OptionalGpuArch)
915 return {TargetID.str(), std::nullopt, std::nullopt};
917 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
921 const llvm::opt::ArgList &DriverArgs)
const {
923 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
925 << *PTID.OptionalTargetID;
933 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
934 Program = A->getValue();
940 return StdoutOrErr.takeError();
943 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
945 GPUArchs.push_back(
Arch.str());
947 if (GPUArchs.empty())
948 return llvm::createStringError(std::error_code(),
949 "No AMD GPU detected in the system");
951 return std::move(GPUArchs);
955 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
958 DeviceOffloadingKind);
963 DriverArgs.hasArg(options::OPT_nostdlib))
966 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
978 if (TT.getEnvironment() == llvm::Triple::LLVM)
984 StringRef TargetID = BoundArch.empty()
985 ? DriverArgs.getLastArgValue(options::OPT_mcpu_EQ)
993 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1002 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
1006 for (
auto [BCFile, Internalize] : BCLibs) {
1008 CC1Args.push_back(
"-mlink-builtin-bitcode");
1010 CC1Args.push_back(
"-mlink-bitcode-file");
1011 CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
1016 StringRef GPUArch, StringRef LibDeviceFile,
1019 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1022 if (LibDeviceFile.empty()) {
1023 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1030 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1032 D.Diag(diag::err_drv_no_rocm_device_lib)
1033 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1041 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1043 const bool NeedsASanRT)
const {
1046 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1047 DeviceOffloadingKind, NeedsASanRT};
1050 bool Internalize =
true) {
1051 if (!BCLib.
Path.empty()) {
1053 BCLibs.emplace_back(BCLib);
1056 auto AddSanBCLibs = [&]() {
1065 else if (Pref.GPUSan && Pref.IsOpenMP)
1070 AddBCLib(LibDeviceFile);
1072 if (!ABIVerPath.empty())
1073 AddBCLib(ABIVerPath);
1080 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1082 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1083 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1093 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1101 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1102 : llvm::AMDGPU::parseArchR600(Processor);
1103 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1104 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1107 bool XnackAvailable = (Features & llvm::AMDGPU::FEATURE_XNACK_ALWAYS);
1112 llvm::StringMap<bool> FeatureMap;
1113 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1114 if (!OptionalGpuArch)
1116 auto Loc = FeatureMap.find(
"xnack");
1117 return (Loc != FeatureMap.end() && Loc->second);
1128 SupportedMask |= SanitizerKind::Address;
1130 return SupportedMask;
1134 StringRef BoundArch)
const {
1136 if ((Kinds & SanitizerKind::Address) && !BoundArch.empty() &&
static StringRef getTriple(const Command &Job)
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, unsigned &BufferCapacity)
const char * 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.
llvm::SmallVector< llvm::StringRef, 4 > getAllPossibleTargetIDFeatures(const llvm::Triple &T, llvm::StringRef Processor)
Get all feature strings that can be used in target ID for Processor.
Diagnostic wrappers for TextAPI types for error reporting.
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()