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);
717 DerivedArgList *DAL =
720 DAL =
new DerivedArgList(Args.getBaseArgs());
729 if (Arg *A = DAL->getLastArg(options::OPT_march_EQ)) {
730 DAL->eraseArg(options::OPT_march_EQ);
731 if (!DAL->hasArg(options::OPT_mcpu_EQ))
732 DAL->AddJoinedArg(A, Opts.getOption(options::OPT_mcpu_EQ),
738 Arg *LastMCPUArg = DAL->getLastArg(options::OPT_mcpu_EQ);
739 if (LastMCPUArg && StringRef(LastMCPUArg->getValue()) ==
"native") {
740 DAL->eraseArg(options::OPT_mcpu_EQ);
744 <<
getArchName() << llvm::toString(GPUsOrErr.takeError()) <<
"-mcpu";
746 auto &GPUs = *GPUsOrErr;
747 if (!llvm::all_equal(GPUs))
749 <<
getArchName() << llvm::join(GPUs,
", ") <<
"-mcpu";
750 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ),
751 Args.MakeArgString(GPUs.front()));
755 if (!BoundArch.empty()) {
756 DAL->eraseArg(options::OPT_mcpu_EQ);
757 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_mcpu_EQ), BoundArch);
763 if (Args.getLastArgValue(options::OPT_x) !=
"cl")
767 if (Args.hasArg(options::OPT_c) && Args.hasArg(options::OPT_emit_llvm)) {
770 if (!Args.hasArg(options::OPT_O, options::OPT_O0, options::OPT_O4,
772 DAL->AddJoinedArg(
nullptr, Opts.getOption(options::OPT_O),
780 llvm::AMDGPU::GPUKind Kind) {
783 if (Kind == llvm::AMDGPU::GK_NONE)
786 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
790 const bool BothDenormAndFMAFast =
791 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
792 (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32);
793 return !BothDenormAndFMAFast;
797 const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
798 const llvm::fltSemantics *FPType)
const {
800 if (!FPType || FPType != &llvm::APFloat::IEEEsingle())
801 return llvm::DenormalMode::getIEEE();
806 auto Kind = llvm::AMDGPU::parseArchAMDGCN(
Arch);
807 if (FPType && FPType == &llvm::APFloat::IEEEsingle() &&
808 DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
809 options::OPT_fno_gpu_flush_denormals_to_zero,
811 return llvm::DenormalMode::getPreserveSign();
813 return llvm::DenormalMode::getIEEE();
816 const StringRef GpuArch =
getGPUArch(DriverArgs);
817 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
821 bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
826 return DAZ ? llvm::DenormalMode::getPreserveSign() :
827 llvm::DenormalMode::getIEEE();
831 llvm::AMDGPU::GPUKind Kind) {
832 const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
833 bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
835 return !HasWave32 || DriverArgs.hasFlag(
836 options::OPT_mwavefrontsize64, options::OPT_mno_wavefrontsize64,
false);
844 if (Triple.getEnvironment() != llvm::Triple::LLVM)
851 DerivedArgList *DAL =
855 for (Arg *A : Args) {
857 if (A->getOption().matches(options::OPT_fsan_cov_Group)) {
859 bool IsExplicitDevice =
860 A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
862 ? diag::err_drv_unsupported_option_for_target
863 : diag::warn_drv_unsupported_option_for_target)
864 << A->getAsString(Args) <<
getTriple().str();
872 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
877 if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ,
878 options::OPT_fvisibility_ms_compat) &&
880 CC1Args.push_back(
"-fvisibility=hidden");
881 CC1Args.push_back(
"-fapply-global-visibility-to-externs");
895 !DriverArgs.hasArg(options::OPT_disable_llvm_optzns))
896 CC1Args.push_back(
"-disable-llvm-optzns");
905 CC1Args.push_back(
"-Werror=atomic-alignment");
909 ArgStringList &CC1Args)
const {
910 if (DriverArgs.hasArg(options::OPT_nostdinc) ||
911 DriverArgs.hasArg(options::OPT_nostdlibinc))
920 llvm::sys::path::append(Dir, M.includeSuffix());
933 getTriple(), DriverArgs.getLastArgValue(options::OPT_mcpu_EQ));
938 StringRef TargetID = DriverArgs.getLastArgValue(options::OPT_mcpu_EQ);
939 if (TargetID.empty())
942 llvm::StringMap<bool> FeatureMap;
944 if (!OptionalGpuArch)
945 return {TargetID.str(), std::nullopt, std::nullopt};
947 return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
951 const llvm::opt::ArgList &DriverArgs)
const {
953 if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
955 << *PTID.OptionalTargetID;
963 if (Arg *A = Args.getLastArg(options::OPT_offload_arch_tool_EQ))
964 Program = A->getValue();
970 return StdoutOrErr.takeError();
973 for (StringRef
Arch : llvm::split((*StdoutOrErr)->getBuffer(),
"\n"))
975 GPUArchs.push_back(
Arch.str());
977 if (GPUArchs.empty())
978 return llvm::createStringError(std::error_code(),
979 "No AMD GPU detected in the system");
981 return std::move(GPUArchs);
985 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
988 DeviceOffloadingKind);
993 DriverArgs.hasArg(options::OPT_nostdlib))
996 if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
1008 if (TT.getEnvironment() == llvm::Triple::LLVM)
1014 StringRef TargetID = BoundArch.empty()
1015 ? DriverArgs.getLastArgValue(options::OPT_mcpu_EQ)
1023 if (!
RocmInstallation->checkCommonBitcodeLibs(GpuArch, LibDeviceFile, ABIVer))
1032 DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
1036 for (
auto [BCFile, Internalize] : BCLibs) {
1038 CC1Args.push_back(
"-mlink-builtin-bitcode");
1040 CC1Args.push_back(
"-mlink-bitcode-file");
1041 CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
1046 StringRef GPUArch, StringRef LibDeviceFile,
1049 D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
1052 if (LibDeviceFile.empty()) {
1053 D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
1060 D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.
toString() << 0;
1062 D.Diag(diag::err_drv_no_rocm_device_lib)
1063 << 2 << ABIVer.
toString() << 1 <<
"6.3";
1071 const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
1073 const bool NeedsASanRT)
const {
1076 CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
1077 DeviceOffloadingKind, NeedsASanRT};
1080 bool Internalize =
true) {
1081 if (!BCLib.
Path.empty()) {
1083 BCLibs.emplace_back(BCLib);
1086 auto AddSanBCLibs = [&]() {
1095 else if (Pref.GPUSan && Pref.IsOpenMP)
1100 AddBCLib(LibDeviceFile);
1102 if (!ABIVerPath.empty())
1103 AddBCLib(ABIVerPath);
1110 const llvm::opt::ArgList &DriverArgs, llvm::StringRef TargetID,
1112 auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
1113 const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
1123 DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
1131 auto ProcKind = TT.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Processor)
1132 : llvm::AMDGPU::parseArchR600(Processor);
1133 auto Features = TT.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)
1134 : llvm::AMDGPU::getArchAttrR600(ProcKind);
1137 bool XnackAvailable = (Features & llvm::AMDGPU::FEATURE_XNACK_ALWAYS);
1142 llvm::StringMap<bool> FeatureMap;
1143 auto OptionalGpuArch =
parseTargetID(TT, TargetID, &FeatureMap);
1144 if (!OptionalGpuArch)
1146 auto Loc = FeatureMap.find(
"xnack");
1147 return (Loc != FeatureMap.end() && Loc->second);
1158 SupportedMask |= SanitizerKind::Address;
1160 return SupportedMask;
1164 StringRef BoundArch)
const {
1166 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()