forked from OSchip/llvm-project
Add HIP toolchain
This patch adds HIP toolchain to support HIP language mode. It includes: Create specific compiler jobs for HIP. Choose specific libraries for HIP. With contribution from Greg Rodgers. Differential Revision: https://reviews.llvm.org/D45212 llvm-svn: 333484
This commit is contained in:
parent
3af038beec
commit
f614422da9
|
@ -588,6 +588,10 @@ def fno_cuda_rdc : Flag<["-"], "fno-cuda-rdc">;
|
|||
def fcuda_short_ptr : Flag<["-"], "fcuda-short-ptr">, Flags<[CC1Option]>,
|
||||
HelpText<"Use 32-bit pointers for accessing const/local/shared address spaces.">;
|
||||
def fno_cuda_short_ptr : Flag<["-"], "fno-cuda-short-ptr">;
|
||||
def hip_device_lib_path_EQ : Joined<["--"], "hip-device-lib-path=">, Group<Link_Group>,
|
||||
HelpText<"HIP device library path">;
|
||||
def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>,
|
||||
HelpText<"HIP device library">;
|
||||
def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">,
|
||||
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
|
||||
def dA : Flag<["-"], "dA">, Group<d_Group>;
|
||||
|
|
|
@ -45,6 +45,7 @@ add_clang_library(clangDriver
|
|||
ToolChains/Fuchsia.cpp
|
||||
ToolChains/Gnu.cpp
|
||||
ToolChains/Haiku.cpp
|
||||
ToolChains/HIP.cpp
|
||||
ToolChains/Hexagon.cpp
|
||||
ToolChains/Linux.cpp
|
||||
ToolChains/MipsLinux.cpp
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "ToolChains/AMDGPU.h"
|
||||
#include "ToolChains/AVR.h"
|
||||
#include "ToolChains/Ananas.h"
|
||||
#include "ToolChains/BareMetal.h"
|
||||
#include "ToolChains/Clang.h"
|
||||
#include "ToolChains/CloudABI.h"
|
||||
#include "ToolChains/Contiki.h"
|
||||
|
@ -22,15 +23,15 @@
|
|||
#include "ToolChains/FreeBSD.h"
|
||||
#include "ToolChains/Fuchsia.h"
|
||||
#include "ToolChains/Gnu.h"
|
||||
#include "ToolChains/BareMetal.h"
|
||||
#include "ToolChains/HIP.h"
|
||||
#include "ToolChains/Haiku.h"
|
||||
#include "ToolChains/Hexagon.h"
|
||||
#include "ToolChains/Lanai.h"
|
||||
#include "ToolChains/Linux.h"
|
||||
#include "ToolChains/MSVC.h"
|
||||
#include "ToolChains/MinGW.h"
|
||||
#include "ToolChains/Minix.h"
|
||||
#include "ToolChains/MipsLinux.h"
|
||||
#include "ToolChains/MSVC.h"
|
||||
#include "ToolChains/Myriad.h"
|
||||
#include "ToolChains/NaCl.h"
|
||||
#include "ToolChains/NetBSD.h"
|
||||
|
@ -70,9 +71,9 @@
|
|||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
@ -540,7 +541,7 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|||
//
|
||||
// CUDA/HIP
|
||||
//
|
||||
// We need to generate a CUDA toolchain if any of the inputs has a CUDA
|
||||
// We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA
|
||||
// or HIP type. However, mixed CUDA/HIP compilation is not supported.
|
||||
bool IsCuda =
|
||||
llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
|
||||
|
@ -556,21 +557,15 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|||
Diag(clang::diag::err_drv_mix_cuda_hip);
|
||||
return;
|
||||
}
|
||||
if (IsCuda || IsHIP) {
|
||||
if (IsCuda) {
|
||||
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
|
||||
const llvm::Triple &HostTriple = HostTC->getTriple();
|
||||
StringRef DeviceTripleStr;
|
||||
auto OFK = IsHIP ? Action::OFK_HIP : Action::OFK_Cuda;
|
||||
if (IsHIP) {
|
||||
// HIP is only supported on amdgcn.
|
||||
DeviceTripleStr = "amdgcn-amd-amdhsa";
|
||||
} else {
|
||||
// CUDA is only supported on nvptx.
|
||||
DeviceTripleStr = HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda"
|
||||
: "nvptx-nvidia-cuda";
|
||||
}
|
||||
auto OFK = Action::OFK_Cuda;
|
||||
DeviceTripleStr =
|
||||
HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda";
|
||||
llvm::Triple CudaTriple(DeviceTripleStr);
|
||||
// Use the CUDA/HIP and host triples as the key into the ToolChains map,
|
||||
// Use the CUDA and host triples as the key into the ToolChains map,
|
||||
// because the device toolchain we create depends on both.
|
||||
auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
|
||||
if (!CudaTC) {
|
||||
|
@ -578,6 +573,21 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
|
|||
*this, CudaTriple, *HostTC, C.getInputArgs(), OFK);
|
||||
}
|
||||
C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
|
||||
} else if (IsHIP) {
|
||||
const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
|
||||
const llvm::Triple &HostTriple = HostTC->getTriple();
|
||||
StringRef DeviceTripleStr;
|
||||
auto OFK = Action::OFK_HIP;
|
||||
DeviceTripleStr = "amdgcn-amd-amdhsa";
|
||||
llvm::Triple HIPTriple(DeviceTripleStr);
|
||||
// Use the HIP and host triples as the key into the ToolChains map,
|
||||
// because the device toolchain we create depends on both.
|
||||
auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()];
|
||||
if (!HIPTC) {
|
||||
HIPTC = llvm::make_unique<toolchains::HIPToolChain>(
|
||||
*this, HIPTriple, *HostTC, C.getInputArgs());
|
||||
}
|
||||
C.addOffloadDeviceToolChain(HIPTC.get(), OFK);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
//===--- HIP.cpp - HIP Tool and ToolChain Implementations -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HIP.h"
|
||||
#include "CommonArgs.h"
|
||||
#include "InputInfo.h"
|
||||
#include "clang/Basic/Cuda.h"
|
||||
#include "clang/Driver/Compilation.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
#include "clang/Driver/DriverDiagnostic.h"
|
||||
#include "clang/Driver/Options.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
using namespace clang::driver;
|
||||
using namespace clang::driver::toolchains;
|
||||
using namespace clang::driver::tools;
|
||||
using namespace clang;
|
||||
using namespace llvm::opt;
|
||||
|
||||
namespace {
|
||||
|
||||
static void addBCLib(Compilation &C, const ArgList &Args,
|
||||
ArgStringList &CmdArgs, ArgStringList LibraryPaths,
|
||||
StringRef BCName) {
|
||||
StringRef FullName;
|
||||
for (std::string LibraryPath : LibraryPaths) {
|
||||
SmallString<128> Path(LibraryPath);
|
||||
llvm::sys::path::append(Path, BCName);
|
||||
FullName = Path;
|
||||
if (llvm::sys::fs::exists(FullName)) {
|
||||
CmdArgs.push_back(Args.MakeArgString(FullName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
C.getDriver().Diag(diag::err_drv_no_such_file) << BCName;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
const char *AMDGCN::Linker::constructLLVMLinkCommand(
|
||||
Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
|
||||
const ArgList &Args, StringRef SubArchName,
|
||||
StringRef OutputFilePrefix) const {
|
||||
ArgStringList CmdArgs;
|
||||
// Add the input bc's created by compile step.
|
||||
for (const auto &II : Inputs)
|
||||
CmdArgs.push_back(II.getFilename());
|
||||
|
||||
ArgStringList LibraryPaths;
|
||||
|
||||
// Find in --hip-device-lib-path and HIP_LIBRARY_PATH.
|
||||
for (auto Path : Args.getAllArgValues(options::OPT_hip_device_lib_path_EQ))
|
||||
LibraryPaths.push_back(Args.MakeArgString(Path));
|
||||
|
||||
addDirectoryList(Args, LibraryPaths, "-L", "HIP_DEVICE_LIB_PATH");
|
||||
|
||||
llvm::SmallVector<std::string, 10> BCLibs;
|
||||
|
||||
// Add bitcode library in --hip-device-lib.
|
||||
for (auto Lib : Args.getAllArgValues(options::OPT_hip_device_lib_EQ)) {
|
||||
BCLibs.push_back(Args.MakeArgString(Lib));
|
||||
}
|
||||
|
||||
// If --hip-device-lib is not set, add the default bitcode libraries.
|
||||
if (BCLibs.empty()) {
|
||||
// Get the bc lib file name for ISA version. For example,
|
||||
// gfx803 => oclc_isa_version_803.amdgcn.bc.
|
||||
std::string ISAVerBC =
|
||||
"oclc_isa_version_" + SubArchName.drop_front(3).str() + ".amdgcn.bc";
|
||||
|
||||
BCLibs.append({"hip.amdgcn.bc", "hc.amdgcn.bc", "opencl.amdgcn.bc",
|
||||
"ockl.amdgcn.bc", "irif.amdgcn.bc", "ocml.amdgcn.bc",
|
||||
"oclc_finite_only_off.amdgcn.bc",
|
||||
"oclc_daz_opt_off.amdgcn.bc",
|
||||
"oclc_correctly_rounded_sqrt_on.amdgcn.bc",
|
||||
"oclc_unsafe_math_off.amdgcn.bc", "hc.amdgcn.bc", ISAVerBC});
|
||||
}
|
||||
for (auto Lib : BCLibs)
|
||||
addBCLib(C, Args, CmdArgs, LibraryPaths, Lib);
|
||||
|
||||
// Add an intermediate output file.
|
||||
CmdArgs.push_back("-o");
|
||||
std::string TmpName =
|
||||
C.getDriver().GetTemporaryPath(OutputFilePrefix.str() + "-linked", "bc");
|
||||
const char *OutputFileName =
|
||||
C.addTempFile(C.getArgs().MakeArgString(TmpName));
|
||||
CmdArgs.push_back(OutputFileName);
|
||||
SmallString<128> ExecPath(C.getDriver().Dir);
|
||||
llvm::sys::path::append(ExecPath, "llvm-link");
|
||||
const char *Exec = Args.MakeArgString(ExecPath);
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
||||
return OutputFileName;
|
||||
}
|
||||
|
||||
const char *AMDGCN::Linker::constructOptCommand(
|
||||
Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
|
||||
const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
|
||||
llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
|
||||
// Construct opt command.
|
||||
ArgStringList OptArgs;
|
||||
// The input to opt is the output from llvm-link.
|
||||
OptArgs.push_back(InputFileName);
|
||||
// Pass optimization arg to opt.
|
||||
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
|
||||
StringRef OOpt = "3";
|
||||
if (A->getOption().matches(options::OPT_O4) ||
|
||||
A->getOption().matches(options::OPT_Ofast))
|
||||
OOpt = "3";
|
||||
else if (A->getOption().matches(options::OPT_O0))
|
||||
OOpt = "0";
|
||||
else if (A->getOption().matches(options::OPT_O)) {
|
||||
// -Os, -Oz, and -O(anything else) map to -O2
|
||||
OOpt = llvm::StringSwitch<const char *>(A->getValue())
|
||||
.Case("1", "1")
|
||||
.Case("2", "2")
|
||||
.Case("3", "3")
|
||||
.Case("s", "2")
|
||||
.Case("z", "2")
|
||||
.Default("2");
|
||||
}
|
||||
OptArgs.push_back(Args.MakeArgString("-O" + OOpt));
|
||||
}
|
||||
OptArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
|
||||
OptArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
|
||||
OptArgs.push_back("-o");
|
||||
std::string TmpFileName = C.getDriver().GetTemporaryPath(
|
||||
OutputFilePrefix.str() + "-optimized", "bc");
|
||||
const char *OutputFileName =
|
||||
C.addTempFile(C.getArgs().MakeArgString(TmpFileName));
|
||||
OptArgs.push_back(OutputFileName);
|
||||
SmallString<128> OptPath(C.getDriver().Dir);
|
||||
llvm::sys::path::append(OptPath, "opt");
|
||||
const char *OptExec = Args.MakeArgString(OptPath);
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs));
|
||||
return OutputFileName;
|
||||
}
|
||||
|
||||
const char *AMDGCN::Linker::constructLlcCommand(
|
||||
Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
|
||||
const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
|
||||
llvm::StringRef OutputFilePrefix, const char *InputFileName) const {
|
||||
// Construct llc command.
|
||||
ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa",
|
||||
"-filetype=obj",
|
||||
Args.MakeArgString("-mcpu=" + SubArchName), "-o"};
|
||||
std::string LlcOutputFileName =
|
||||
C.getDriver().GetTemporaryPath(OutputFilePrefix, "o");
|
||||
const char *LlcOutputFile =
|
||||
C.addTempFile(C.getArgs().MakeArgString(LlcOutputFileName));
|
||||
LlcArgs.push_back(LlcOutputFile);
|
||||
SmallString<128> LlcPath(C.getDriver().Dir);
|
||||
llvm::sys::path::append(LlcPath, "llc");
|
||||
const char *Llc = Args.MakeArgString(LlcPath);
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs));
|
||||
return LlcOutputFile;
|
||||
}
|
||||
|
||||
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
|
||||
const InputInfoList &Inputs,
|
||||
const InputInfo &Output,
|
||||
const llvm::opt::ArgList &Args,
|
||||
const char *InputFileName) const {
|
||||
// Construct lld command.
|
||||
// The output from ld.lld is an HSA code object file.
|
||||
ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined",
|
||||
"-shared", "-o", Output.getFilename(),
|
||||
InputFileName};
|
||||
SmallString<128> LldPath(C.getDriver().Dir);
|
||||
llvm::sys::path::append(LldPath, "lld");
|
||||
const char *Lld = Args.MakeArgString(LldPath);
|
||||
C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs));
|
||||
}
|
||||
|
||||
// For amdgcn the inputs of the linker job are device bitcode and output is
|
||||
// object file. It calls llvm-link, opt, llc, then lld steps.
|
||||
void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
const InputInfo &Output,
|
||||
const InputInfoList &Inputs,
|
||||
const ArgList &Args,
|
||||
const char *LinkingOutput) const {
|
||||
|
||||
const auto &TC =
|
||||
static_cast<const toolchains::HIPToolChain &>(getToolChain());
|
||||
assert(TC.getTriple().getArch() == llvm::Triple::amdgcn &&
|
||||
"Unsupported target");
|
||||
|
||||
std::string SubArchName = JA.getOffloadingArch();
|
||||
assert(StringRef(SubArchName).startswith("gfx") && "Unsupported sub arch");
|
||||
|
||||
// Prefix for temporary file name.
|
||||
std::string Prefix =
|
||||
llvm::sys::path::stem(Inputs[0].getFilename()).str() + "-" + SubArchName;
|
||||
|
||||
// Each command outputs different files.
|
||||
const char *LLVMLinkCommand =
|
||||
constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix);
|
||||
const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName,
|
||||
Prefix, LLVMLinkCommand);
|
||||
const char *LlcCommand =
|
||||
constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand);
|
||||
constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
|
||||
}
|
||||
|
||||
HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple,
|
||||
const ToolChain &HostTC, const ArgList &Args)
|
||||
: ToolChain(D, Triple, Args), HostTC(HostTC) {
|
||||
// Lookup binaries into the driver directory, this is used to
|
||||
// discover the clang-offload-bundler executable.
|
||||
getProgramPaths().push_back(getDriver().Dir);
|
||||
}
|
||||
|
||||
void HIPToolChain::addClangTargetOptions(
|
||||
const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args,
|
||||
Action::OffloadKind DeviceOffloadingKind) const {
|
||||
HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
|
||||
|
||||
StringRef GpuArch = DriverArgs.getLastArgValue(options::OPT_march_EQ);
|
||||
assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
|
||||
assert(DeviceOffloadingKind == Action::OFK_HIP &&
|
||||
"Only HIP offloading kinds are supported for GPUs.");
|
||||
|
||||
CC1Args.push_back("-fcuda-is-device");
|
||||
|
||||
if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero,
|
||||
options::OPT_fno_cuda_flush_denormals_to_zero, false))
|
||||
CC1Args.push_back("-fcuda-flush-denormals-to-zero");
|
||||
|
||||
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
|
||||
options::OPT_fno_cuda_approx_transcendentals, false))
|
||||
CC1Args.push_back("-fcuda-approx-transcendentals");
|
||||
|
||||
if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc,
|
||||
false))
|
||||
CC1Args.push_back("-fcuda-rdc");
|
||||
}
|
||||
|
||||
llvm::opt::DerivedArgList *
|
||||
HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
|
||||
StringRef BoundArch,
|
||||
Action::OffloadKind DeviceOffloadKind) const {
|
||||
DerivedArgList *DAL =
|
||||
HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
|
||||
if (!DAL)
|
||||
DAL = new DerivedArgList(Args.getBaseArgs());
|
||||
|
||||
const OptTable &Opts = getDriver().getOpts();
|
||||
|
||||
for (Arg *A : Args) {
|
||||
if (A->getOption().matches(options::OPT_Xarch__)) {
|
||||
// Skip this argument unless the architecture matches BoundArch
|
||||
if (BoundArch.empty() || A->getValue(0) != BoundArch)
|
||||
continue;
|
||||
|
||||
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
|
||||
unsigned Prev = Index;
|
||||
std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index));
|
||||
|
||||
// If the argument parsing failed or more than one argument was
|
||||
// consumed, the -Xarch_ argument's parameter tried to consume
|
||||
// extra arguments. Emit an error and ignore.
|
||||
//
|
||||
// We also want to disallow any options which would alter the
|
||||
// driver behavior; that isn't going to work in our model. We
|
||||
// use isDriverOption() as an approximation, although things
|
||||
// like -O4 are going to slip through.
|
||||
if (!XarchArg || Index > Prev + 1) {
|
||||
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
|
||||
<< A->getAsString(Args);
|
||||
continue;
|
||||
} else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
|
||||
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
|
||||
<< A->getAsString(Args);
|
||||
continue;
|
||||
}
|
||||
XarchArg->setBaseArg(A);
|
||||
A = XarchArg.release();
|
||||
DAL->AddSynthesizedArg(A);
|
||||
}
|
||||
DAL->append(A);
|
||||
}
|
||||
|
||||
if (!BoundArch.empty()) {
|
||||
DAL->eraseArg(options::OPT_march_EQ);
|
||||
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch);
|
||||
}
|
||||
|
||||
return DAL;
|
||||
}
|
||||
|
||||
Tool *HIPToolChain::buildLinker() const {
|
||||
assert(getTriple().getArch() == llvm::Triple::amdgcn);
|
||||
return new tools::AMDGCN::Linker(*this);
|
||||
}
|
||||
|
||||
void HIPToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
|
||||
HostTC.addClangWarningOptions(CC1Args);
|
||||
}
|
||||
|
||||
ToolChain::CXXStdlibType
|
||||
HIPToolChain::GetCXXStdlibType(const ArgList &Args) const {
|
||||
return HostTC.GetCXXStdlibType(Args);
|
||||
}
|
||||
|
||||
void HIPToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
||||
ArgStringList &CC1Args) const {
|
||||
HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
|
||||
}
|
||||
|
||||
void HIPToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
|
||||
ArgStringList &CC1Args) const {
|
||||
HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
|
||||
}
|
||||
|
||||
void HIPToolChain::AddIAMCUIncludeArgs(const ArgList &Args,
|
||||
ArgStringList &CC1Args) const {
|
||||
HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
|
||||
}
|
||||
|
||||
SanitizerMask HIPToolChain::getSupportedSanitizers() const {
|
||||
// The HIPToolChain only supports sanitizers in the sense that it allows
|
||||
// sanitizer arguments on the command line if they are supported by the host
|
||||
// toolchain. The HIPToolChain will actually ignore any command line
|
||||
// arguments for any of these "supported" sanitizers. That means that no
|
||||
// sanitization of device code is actually supported at this time.
|
||||
//
|
||||
// This behavior is necessary because the host and device toolchains
|
||||
// invocations often share the command line, so the device toolchain must
|
||||
// tolerate flags meant only for the host toolchain.
|
||||
return HostTC.getSupportedSanitizers();
|
||||
}
|
||||
|
||||
VersionTuple HIPToolChain::computeMSVCVersion(const Driver *D,
|
||||
const ArgList &Args) const {
|
||||
return HostTC.computeMSVCVersion(D, Args);
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
//===--- HIP.h - HIP ToolChain Implementations ------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
|
||||
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
|
||||
|
||||
#include "clang/Driver/ToolChain.h"
|
||||
#include "clang/Driver/Tool.h"
|
||||
|
||||
namespace clang {
|
||||
namespace driver {
|
||||
|
||||
namespace tools {
|
||||
|
||||
namespace AMDGCN {
|
||||
// Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with
|
||||
// device library, then compiles it to ISA in a shared object.
|
||||
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
|
||||
public:
|
||||
Linker(const ToolChain &TC) : Tool("AMDGCN::Linker", "amdgcn-link", TC) {}
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
/// \return llvm-link output file name.
|
||||
const char *constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
|
||||
const InputInfoList &Inputs,
|
||||
const llvm::opt::ArgList &Args,
|
||||
llvm::StringRef SubArchName,
|
||||
llvm::StringRef OutputFilePrefix) const;
|
||||
|
||||
/// \return opt output file name.
|
||||
const char *constructOptCommand(Compilation &C, const JobAction &JA,
|
||||
const InputInfoList &Inputs,
|
||||
const llvm::opt::ArgList &Args,
|
||||
llvm::StringRef SubArchName,
|
||||
llvm::StringRef OutputFilePrefix,
|
||||
const char *InputFileName) const;
|
||||
|
||||
/// \return llc output file name.
|
||||
const char *constructLlcCommand(Compilation &C, const JobAction &JA,
|
||||
const InputInfoList &Inputs,
|
||||
const llvm::opt::ArgList &Args,
|
||||
llvm::StringRef SubArchName,
|
||||
llvm::StringRef OutputFilePrefix,
|
||||
const char *InputFileName) const;
|
||||
|
||||
void constructLldCommand(Compilation &C, const JobAction &JA,
|
||||
const InputInfoList &Inputs, const InputInfo &Output,
|
||||
const llvm::opt::ArgList &Args,
|
||||
const char *InputFileName) const;
|
||||
};
|
||||
|
||||
} // end namespace AMDGCN
|
||||
} // end namespace tools
|
||||
|
||||
namespace toolchains {
|
||||
|
||||
class LLVM_LIBRARY_VISIBILITY HIPToolChain : public ToolChain {
|
||||
public:
|
||||
HIPToolChain(const Driver &D, const llvm::Triple &Triple,
|
||||
const ToolChain &HostTC, const llvm::opt::ArgList &Args);
|
||||
|
||||
const llvm::Triple *getAuxTriple() const override {
|
||||
return &HostTC.getTriple();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool useIntegratedAs() const override { return true; }
|
||||
bool isCrossCompiling() const override { return true; }
|
||||
bool isPICDefault() const override { return false; }
|
||||
bool isPIEDefault() const override { return false; }
|
||||
bool isPICDefaultForced() const override { return false; }
|
||||
bool SupportsProfiling() const override { return false; }
|
||||
bool IsMathErrnoDefault() const override { return false; }
|
||||
|
||||
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
|
||||
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
|
||||
void
|
||||
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
void AddClangCXXStdlibIncludeArgs(
|
||||
const llvm::opt::ArgList &Args,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
|
||||
SanitizerMask getSupportedSanitizers() const override;
|
||||
|
||||
VersionTuple
|
||||
computeMSVCVersion(const Driver *D,
|
||||
const llvm::opt::ArgList &Args) const override;
|
||||
|
||||
unsigned GetDefaultDwarfVersion() const override { return 2; }
|
||||
|
||||
const ToolChain &HostTC;
|
||||
|
||||
protected:
|
||||
Tool *buildLinker() const override;
|
||||
};
|
||||
|
||||
} // end namespace toolchains
|
||||
} // end namespace driver
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIP_H
|
|
@ -0,0 +1,84 @@
|
|||
// REQUIRES: clang-driver
|
||||
// REQUIRES: x86-registered-target
|
||||
// REQUIRES: amdgpu-registered-target
|
||||
|
||||
// RUN: %clang -### -target x86_64-linux-gnu \
|
||||
// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
|
||||
// RUN: --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc \
|
||||
// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
|
||||
// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
|
||||
// RUN: -fuse-ld=lld \
|
||||
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
|
||||
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
|
||||
// RUN: 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-fcuda-is-device"
|
||||
// CHECK-SAME: {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[A_SRC:".*a.cu"]]
|
||||
|
||||
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-fcuda-is-device"
|
||||
// CHECK-SAME: {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[B_SRC:".*b.hip"]]
|
||||
|
||||
// CHECK: [[LLVM_LINK:"*.llvm-link"]] [[A_BC]] [[B_BC]]
|
||||
// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
|
||||
// CHECK-SAME: "-o" [[LINKED_BC_DEV1:".*-gfx803-linked-.*bc"]]
|
||||
|
||||
// CHECK: [[OPT:".*opt"]] [[LINKED_BC_DEV1]] "-mtriple=amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-mcpu=gfx803"
|
||||
// CHECK-SAME: "-o" [[OPT_BC_DEV1:".*-gfx803-optimized.*bc"]]
|
||||
|
||||
// CHECK: [[LLC: ".*llc"]] [[OPT_BC_DEV1]] "-mtriple=amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-filetype=obj" "-mcpu=gfx803" "-o" [[OBJ_DEV1:".*-gfx803-.*o"]]
|
||||
|
||||
// CHECK: [[LLD: ".*lld"]] "-flavor" "gnu" "--no-undefined" "-shared"
|
||||
// CHECK-SAME: "-o" "[[IMG_DEV1:.*out]]" [[OBJ_DEV1]]
|
||||
|
||||
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu" {{.*}} "-fcuda-is-device"
|
||||
// CHECK-SAME: {{.*}} "-o" [[A_BC:".*bc"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[A_SRC]]
|
||||
|
||||
// CHECK: [[CLANG]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-aux-triple" "x86_64--linux-gnu" "-emit-llvm-bc"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip" {{.*}} "-fcuda-is-device"
|
||||
// CHECK-SAME: {{.*}} "-o" [[B_BC:".*bc"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[B_SRC]]
|
||||
|
||||
// CHECK: [[LLVM_LINK]] [[A_BC]] [[B_BC]]
|
||||
// CHECK-SAME: "{{.*}}lib1.bc" "{{.*}}lib2.bc"
|
||||
// CHECK-SAME: "-o" [[LINKED_BC_DEV2:".*-gfx900-linked-.*bc"]]
|
||||
|
||||
// CHECK: [[OPT]] [[LINKED_BC_DEV2]] "-mtriple=amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-mcpu=gfx900"
|
||||
// CHECK-SAME: "-o" [[OPT_BC_DEV2:".*-gfx900-optimized.*bc"]]
|
||||
|
||||
// CHECK: [[LLC]] [[OPT_BC_DEV2]] "-mtriple=amdgcn-amd-amdhsa"
|
||||
// CHECK-SAME: "-filetype=obj" "-mcpu=gfx900" "-o" [[OBJ_DEV2:".*-gfx900-.*o"]]
|
||||
|
||||
// CHECK: [[LLD]] "-flavor" "gnu" "--no-undefined" "-shared"
|
||||
// CHECK-SAME: "-o" "[[IMG_DEV2:.*out]]" [[OBJ_DEV2]]
|
||||
|
||||
// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
|
||||
// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "a.cu"
|
||||
// CHECK-SAME: {{.*}} "-o" [[A_OBJ_HOST:".*o"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[A_SRC]]
|
||||
|
||||
// CHECK: [[CLANG]] "-cc1" "-triple" "x86_64--linux-gnu"
|
||||
// CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" "-emit-obj"
|
||||
// CHECK-SAME: {{.*}} "-main-file-name" "b.hip"
|
||||
// CHECK-SAME: {{.*}} "-o" [[B_OBJ_HOST:".*o"]] "-x" "hip"
|
||||
// CHECK-SAME: {{.*}} [[B_SRC]]
|
||||
|
||||
// CHECK: [[BUNDLER:".*clang-offload-bundler"]] "-type=o"
|
||||
// CHECK-SAME: "-targets={{.*}},hip-amdgcn-amd-amdhsa-gfx803,hip-amdgcn-amd-amdhsa-gfx900"
|
||||
// CHECK-SAME: "-inputs={{.*}},[[IMG_DEV1]],[[IMG_DEV2]]" "-outputs=[[BUNDLE:.*o]]"
|
||||
|
||||
// CHECK: [[LD:".*ld.lld"]] {{.*}} [[A_OBJ_HOST]] [[B_OBJ_HOST]]
|
||||
// CHECK-SAME: {{.*}} "-T" "{{.*}}.lk"
|
Loading…
Reference in New Issue