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:
Yaxun Liu 2018-05-30 00:53:50 +00:00
parent 3af038beec
commit f614422da9
8 changed files with 580 additions and 15 deletions

View File

@ -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>;

View File

@ -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

View File

@ -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);
}
//

View File

@ -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);
}

View File

@ -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

View File

@ -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"