CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
304 lines
12 KiB
C++
304 lines
12 KiB
C++
//===--- AMDGPU.h - AMDGPU ToolChain Implementations ----------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H
|
|
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H
|
|
|
|
#include "Gnu.h"
|
|
#include "clang/Basic/TargetID.h"
|
|
#include "clang/Driver/Tool.h"
|
|
#include "clang/Driver/ToolChain.h"
|
|
#include "clang/Options/Options.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/TargetParser/AMDGPUTargetParser.h"
|
|
|
|
#include <map>
|
|
|
|
namespace clang {
|
|
namespace driver {
|
|
|
|
namespace tools {
|
|
namespace amdgpu {
|
|
|
|
class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
|
|
public:
|
|
Linker(const ToolChain &TC) : Tool("amdgpu::Linker", "ld.lld", TC) {}
|
|
bool isLinkJob() const override { return true; }
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
|
|
void getAMDGPUTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args,
|
|
std::vector<StringRef> &Features,
|
|
StringRef TcTargetID = StringRef());
|
|
|
|
namespace dlr {
|
|
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
|
|
getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
|
|
const SanitizerArgs &SanArgs, const Driver &D,
|
|
const std::string &GPUArch, bool isOpenMP,
|
|
const RocmInstallationDetector &RocmInstallation,
|
|
const clang::driver::Action::OffloadKind DeviceOffloadingKind = Action::OFK_OpenMP);
|
|
|
|
const char *
|
|
getCbslCommandArgs(Compilation &C, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CbslArgs,
|
|
const SmallVectorImpl<std::string> &InputFileNames,
|
|
llvm::StringRef OutputFilePrefix);
|
|
|
|
const char *
|
|
getLinkCommandArgs(Compilation &C, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &LastLinkArgs, const ToolChain &TC,
|
|
const llvm::Triple &Triple, llvm::StringRef TargetID,
|
|
llvm::StringRef OutputFilePrefix, const char *InputFileName,
|
|
const RocmInstallationDetector &RocmInstallation,
|
|
llvm::opt::ArgStringList &EnvironmentLibraryPaths);
|
|
|
|
const char *getOptCommandArgs(Compilation &C, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &OptArgs,
|
|
const llvm::Triple &Triple,
|
|
llvm::StringRef TargetID,
|
|
llvm::StringRef OutputFilePrefix,
|
|
const char *InputFileName);
|
|
|
|
const char *
|
|
getLlcCommandArgs(Compilation &C, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &LlcArgs, const llvm::Triple &Triple,
|
|
llvm::StringRef TargetID, llvm::StringRef OutputFilePrefix,
|
|
const char *InputFileName, bool OutputIsAsm = false);
|
|
|
|
const char *getLldCommandArgs(
|
|
Compilation &C, const InputInfo &Output, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &LldArgs, const llvm::Triple &Triple,
|
|
llvm::StringRef TargetID, const char *InputFileName,
|
|
const std::optional<std::string> OutputFilePrefix = std::nullopt);
|
|
} // end namespace dlr
|
|
|
|
void addFullLTOPartitionOption(const Driver &D, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs);
|
|
} // end namespace amdgpu
|
|
} // end namespace tools
|
|
|
|
namespace toolchains {
|
|
|
|
class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
|
|
protected:
|
|
const std::map<options::ID, const StringRef> OptionsDefault;
|
|
unsigned CodeObjectVersion = 5;
|
|
Tool *buildLinker() const override;
|
|
StringRef getOptionDefault(options::ID OptID) const {
|
|
auto opt = OptionsDefault.find(OptID);
|
|
assert(opt != OptionsDefault.end() && "No Default for Option");
|
|
return opt->second;
|
|
}
|
|
|
|
public:
|
|
AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args);
|
|
unsigned GetDefaultDwarfVersion() const override { return 5; }
|
|
|
|
bool IsMathErrnoDefault() const override { return false; }
|
|
bool isCrossCompiling() const override { return true; }
|
|
bool isPICDefault() const override { return true; }
|
|
bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
|
|
return false;
|
|
}
|
|
bool isPICDefaultForced() const override { return true; }
|
|
bool SupportsProfiling() const override { return false; }
|
|
|
|
llvm::opt::DerivedArgList *
|
|
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
|
|
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::opt::ArgStringList &CC1Args,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
void
|
|
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::opt::ArgStringList &CC1Args) const override;
|
|
|
|
/// Return whether denormals should be flushed, and treated as 0 by default
|
|
/// for the subtarget.
|
|
static bool getDefaultDenormsAreZeroForTarget(llvm::AMDGPU::GPUKind GPUKind);
|
|
|
|
llvm::DenormalMode getDefaultDenormalModeForType(
|
|
const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
|
|
const llvm::fltSemantics *FPType = nullptr) const override;
|
|
|
|
static bool isWave64(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::AMDGPU::GPUKind Kind);
|
|
/// Needed for using lto.
|
|
bool HasNativeLLVMSupport() const override {
|
|
return true;
|
|
}
|
|
|
|
/// Needed for translating LTO options.
|
|
const char *getDefaultLinker() const override { return "ld.lld"; }
|
|
|
|
/// Should skip sanitize option.
|
|
bool shouldSkipSanitizeOption(const ToolChain &TC,
|
|
const llvm::opt::ArgList &DriverArgs,
|
|
StringRef TargetID,
|
|
const llvm::opt::Arg *A) const;
|
|
|
|
/// Should skip argument.
|
|
bool shouldSkipArgument(const llvm::opt::Arg *Arg) const;
|
|
|
|
unsigned GetCodeObjectVersion() const { return CodeObjectVersion; }
|
|
|
|
/// Uses amdgpu-arch tool to get arch of the system GPU. Will return error
|
|
/// if unable to find one.
|
|
virtual Expected<SmallVector<std::string>>
|
|
getSystemGPUArchs(const llvm::opt::ArgList &Args) const override;
|
|
|
|
void checkAndAddAMDGPUSanLibPaths(const llvm::opt::ArgList &Args);
|
|
|
|
protected:
|
|
/// Check and diagnose invalid target ID specified by -mcpu.
|
|
virtual void checkTargetID(const llvm::opt::ArgList &DriverArgs) const;
|
|
|
|
/// The struct type returned by getParsedTargetID.
|
|
struct ParsedTargetIDType {
|
|
std::optional<std::string> OptionalTargetID;
|
|
std::optional<std::string> OptionalGPUArch;
|
|
std::optional<llvm::StringMap<bool>> OptionalFeatures;
|
|
};
|
|
|
|
/// Get target ID, GPU arch, and target ID features if the target ID is
|
|
/// specified and valid.
|
|
ParsedTargetIDType
|
|
getParsedTargetID(const llvm::opt::ArgList &DriverArgs) const;
|
|
|
|
/// Get GPU arch from -mcpu without checking.
|
|
StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;
|
|
|
|
/// Common warning options shared by AMDGPU HIP, OpenCL and OpenMP toolchains.
|
|
/// Language specific warning options should go to derived classes.
|
|
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
|
|
public:
|
|
ROCMToolChain(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args);
|
|
void
|
|
addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::opt::ArgStringList &CC1Args,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
|
|
// Returns a list of device library names shared by different languages
|
|
llvm::SmallVector<BitCodeLibraryInfo, 12>
|
|
getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::StringRef GPUArch,
|
|
Action::OffloadKind DeviceOffloadingKind) const;
|
|
|
|
// FIXME: Remove this and make use of OffloadKind argument to
|
|
// getSupportedSanitizers
|
|
static constexpr SanitizerMask getOffloadSupportedSanitizers() {
|
|
return SanitizerKind::Address | SanitizerKind::Undefined |
|
|
SanitizerKind::UndefinedGroup;
|
|
}
|
|
|
|
SanitizerMask
|
|
getSupportedSanitizers(StringRef BoundArch,
|
|
Action::OffloadKind DeviceOffloadKind) const override {
|
|
assert(DeviceOffloadKind == Action::OFK_None);
|
|
return getOffloadSupportedSanitizers();
|
|
}
|
|
|
|
bool diagnoseUnsupportedOption(const llvm::opt::Arg *A,
|
|
const llvm::opt::DerivedArgList &DAL,
|
|
const llvm::opt::ArgList &DriverArgs,
|
|
const char *Value = nullptr) const {
|
|
auto &Diags = getDriver().getDiags();
|
|
bool IsExplicitDevice =
|
|
A->getBaseArg().getOption().matches(options::OPT_Xarch_device);
|
|
|
|
if (Value) {
|
|
unsigned DiagID =
|
|
IsExplicitDevice
|
|
? clang::diag::err_drv_unsupported_option_part_for_target
|
|
: clang::diag::warn_drv_unsupported_option_part_for_target;
|
|
Diags.Report(DiagID) << Value << A->getAsString(DriverArgs)
|
|
<< getTriple().str();
|
|
} else {
|
|
unsigned DiagID =
|
|
IsExplicitDevice
|
|
? clang::diag::err_drv_unsupported_option_for_target
|
|
: clang::diag::warn_drv_unsupported_option_for_target;
|
|
Diags.Report(DiagID) << A->getAsString(DAL) << getTriple().str();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool handleSanitizeOption(const ToolChain &TC, llvm::opt::DerivedArgList &DAL,
|
|
const llvm::opt::ArgList &DriverArgs,
|
|
StringRef TargetID, const llvm::opt::Arg *A) const {
|
|
if (TargetID.empty())
|
|
return false;
|
|
// If we shouldn't do sanitizing, skip it.
|
|
if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
|
|
options::OPT_fno_gpu_sanitize, true))
|
|
return true;
|
|
const llvm::opt::Option &Opt = A->getOption();
|
|
// Sanitizer coverage is currently not supported for AMDGPU, so warn/error
|
|
// on every related option.
|
|
if (Opt.matches(options::OPT_fsan_cov_Group)) {
|
|
diagnoseUnsupportedOption(A, DAL, DriverArgs);
|
|
}
|
|
// If this isn't a sanitizer option, don't handle it.
|
|
if (!Opt.matches(options::OPT_fsanitize_EQ))
|
|
return false;
|
|
|
|
SmallVector<const char *, 4> SupportedSanitizers;
|
|
SmallVector<const char *, 4> UnSupportedSanitizers;
|
|
|
|
SanitizerMask Supported = ROCMToolChain::getOffloadSupportedSanitizers();
|
|
SanitizerMask SupportedMask;
|
|
for (const char *Value : A->getValues()) {
|
|
SanitizerMask K = parseSanitizerValue(Value, /*Allow Groups*/ true);
|
|
if (K & Supported) {
|
|
SupportedSanitizers.push_back(Value);
|
|
SupportedMask |= K;
|
|
} else {
|
|
UnSupportedSanitizers.push_back(Value);
|
|
}
|
|
}
|
|
|
|
// If there are no supported sanitizers, drop the whole argument.
|
|
if (SupportedSanitizers.empty()) {
|
|
diagnoseUnsupportedOption(A, DAL, DriverArgs);
|
|
return true;
|
|
}
|
|
// If only some sanitizers are unsupported, report each one individually.
|
|
if (!UnSupportedSanitizers.empty()) {
|
|
for (const char *Value : UnSupportedSanitizers) {
|
|
diagnoseUnsupportedOption(A, DAL, DriverArgs, Value);
|
|
}
|
|
}
|
|
// The xnack+ feature is only required for ASan on AMDGPU.
|
|
if ((SupportedMask & SanitizerKind::Address) &&
|
|
shouldSkipSanitizeOption(TC, DriverArgs, TargetID, A))
|
|
return true;
|
|
|
|
// Add a new argument with only the supported sanitizers.
|
|
DAL.AddJoinedArg(A, A->getOption(), llvm::join(SupportedSanitizers, ","));
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // end namespace toolchains
|
|
} // end namespace driver
|
|
} // end namespace clang
|
|
|
|
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H
|