[clang] [CUDA][HIP] Support CUID in new driver (PR #122859)
Yaxun Liu via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 13 21:13:28 PST 2025
https://github.com/yxsamliu created https://github.com/llvm/llvm-project/pull/122859
CUID is needed by CUDA/HIP for supporting accessing static device variables in host function.
Currently CUID is only supported by the old driver for CUDA/HIP. The new driver does not support it, which causes CUDA/HIP programs using static device variables in host functions to fail with the new driver for CUDA/HIP.
This patch refactors the CUID support in the old driver so that CUID is supported by both the old and the new drivers for CUDA/HIP.
>From 201fabb541657e76725e09ab949ecbf479e42533 Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Mon, 13 Jan 2025 14:12:52 -0500
Subject: [PATCH] [CUDA][HIP] Support CUID in new driver
CUID is needed by CUDA/HIP for supporting accessing static device variables
in host function.
Currently CUID is only supported by the old driver for CUDA/HIP.
The new clang driver does not support it, which causes CUDA/HIP programs
using static device variables in host functions to fail with
the new driver for CUDA/HIP.
This patch refactors the CUID support in the old driver so that CUID
is supported by both the old and the new drivers for CUDA/HIP.
---
clang/include/clang/Driver/Driver.h | 29 ++++++++
clang/lib/Driver/Driver.cpp | 111 ++++++++++++++++------------
clang/test/Driver/hip-cuid.hip | 11 +++
3 files changed, 104 insertions(+), 47 deletions(-)
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 80bce574a3b647..8c3b00e8a2da79 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -72,6 +72,29 @@ enum ModuleHeaderMode {
HeaderMode_System
};
+/// Options for specifying CUID used by CUDA/HIP for uniquely identifying
+/// compilation units.
+class CUIDOptions {
+public:
+ enum class Kind { Hash, Random, Fixed, None, Invalid };
+
+ CUIDOptions() = default;
+ CUIDOptions(const CUIDOptions &) = default;
+ CUIDOptions(llvm::opt::DerivedArgList &Args, const Driver &D);
+
+ // Get the CUID for an input string
+ std::string getCUID(StringRef InputFile,
+ llvm::opt::DerivedArgList &Args) const;
+
+ bool isEnabled() const {
+ return UseCUID != Kind::None && UseCUID != Kind::Invalid;
+ }
+
+private:
+ Kind UseCUID = Kind::None;
+ StringRef FixedCUID;
+};
+
/// Driver - Encapsulate logic for constructing compilation processes
/// from a set of gcc-driver-like command line arguments.
class Driver {
@@ -119,6 +142,9 @@ class Driver {
/// LTO mode selected via -f(no-offload-)?lto(=.*)? options.
LTOKind OffloadLTOMode;
+ /// Options for CUID
+ CUIDOptions CUIDOpts;
+
public:
enum OpenMPRuntimeKind {
/// An unknown OpenMP runtime. We can't generate effective OpenMP code
@@ -728,6 +754,9 @@ class Driver {
/// Get the specific kind of offload LTO being performed.
LTOKind getOffloadLTOMode() const { return OffloadLTOMode; }
+ /// Get the CUID option.
+ const CUIDOptions &getCUIDOpts() const { return CUIDOpts; }
+
private:
/// Tries to load options from configuration files.
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 57fa7c1110a68e..fb99cd513e01c0 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -197,6 +197,51 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath) {
return std::string(P);
}
+CUIDOptions::CUIDOptions(llvm::opt::DerivedArgList &Args, const Driver &D)
+ : UseCUID(Kind::Hash) {
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
+ StringRef UseCUIDStr = A->getValue();
+ UseCUID = llvm::StringSwitch<Kind>(UseCUIDStr)
+ .Case("hash", Kind::Hash)
+ .Case("random", Kind::Random)
+ .Case("none", Kind::None)
+ .Default(Kind::Invalid);
+ if (UseCUID == Kind::Invalid) {
+ D.Diag(clang::diag::err_drv_invalid_value)
+ << A->getAsString(Args) << UseCUIDStr;
+ }
+ }
+
+ FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
+ if (!FixedCUID.empty())
+ UseCUID = Kind::Fixed;
+}
+
+std::string CUIDOptions::getCUID(StringRef InputFile,
+ llvm::opt::DerivedArgList &Args) const {
+ std::string CUID = FixedCUID.str();
+ if (CUID.empty()) {
+ if (UseCUID == Kind::Random)
+ CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
+ /*LowerCase=*/true);
+ else if (UseCUID == Kind::Hash) {
+ llvm::MD5 Hasher;
+ llvm::MD5::MD5Result Hash;
+ SmallString<256> RealPath;
+ llvm::sys::fs::real_path(InputFile, RealPath,
+ /*expand_tilde=*/true);
+ Hasher.update(RealPath);
+ for (auto *A : Args) {
+ if (A->getOption().matches(options::OPT_INPUT))
+ continue;
+ Hasher.update(A->getAsString(Args));
+ }
+ Hasher.final(Hash);
+ CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
+ }
+ }
+ return CUID;
+}
Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
@@ -875,6 +920,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
C.addOffloadDeviceToolChain(HIPTC, OFK);
}
+ if (IsCuda || IsHIP)
+ CUIDOpts = CUIDOptions(C.getArgs(), *this);
+
//
// OpenMP
//
@@ -3156,19 +3204,15 @@ class OffloadingActionBuilder final {
/// Default GPU architecture if there's no one specified.
OffloadArch DefaultOffloadArch = OffloadArch::UNKNOWN;
- /// Method to generate compilation unit ID specified by option
- /// '-fuse-cuid='.
- enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
- UseCUIDKind UseCUID = CUID_Hash;
-
- /// Compilation unit ID specified by option '-cuid='.
- StringRef FixedCUID;
+ /// Compilation unit ID specified by option '-fuse-cuid=' or'-cuid='.
+ const CUIDOptions &CUIDOpts;
public:
CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs,
Action::OffloadKind OFKind)
- : DeviceActionBuilder(C, Args, Inputs, OFKind) {
+ : DeviceActionBuilder(C, Args, Inputs, OFKind),
+ CUIDOpts(C.getDriver().getCUIDOpts()) {
CompileDeviceOnly = C.getDriver().offloadDeviceOnly();
Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
@@ -3199,28 +3243,8 @@ class OffloadingActionBuilder final {
// Set the flag to true, so that the builder acts on the current input.
IsActive = true;
- std::string CUID = FixedCUID.str();
- if (CUID.empty()) {
- if (UseCUID == CUID_Random)
- CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
- /*LowerCase=*/true);
- else if (UseCUID == CUID_Hash) {
- llvm::MD5 Hasher;
- llvm::MD5::MD5Result Hash;
- SmallString<256> RealPath;
- llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
- /*expand_tilde=*/true);
- Hasher.update(RealPath);
- for (auto *A : Args) {
- if (A->getOption().matches(options::OPT_INPUT))
- continue;
- Hasher.update(A->getAsString(Args));
- }
- Hasher.final(Hash);
- CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
- }
- }
- IA->setId(CUID);
+ if (CUIDOpts.isEnabled())
+ IA->setId(CUIDOpts.getCUID(IA->getInputArg().getValue(), Args));
if (CompileHostOnly)
return ABRT_Success;
@@ -3346,21 +3370,6 @@ class OffloadingActionBuilder final {
CompileHostOnly = C.getDriver().offloadHostOnly();
EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
EmitAsm = Args.getLastArg(options::OPT_S);
- FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
- if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
- StringRef UseCUIDStr = A->getValue();
- UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
- .Case("hash", CUID_Hash)
- .Case("random", CUID_Random)
- .Case("none", CUID_None)
- .Default(CUID_Invalid);
- if (UseCUID == CUID_Invalid) {
- C.getDriver().Diag(diag::err_drv_invalid_value)
- << A->getAsString(Args) << UseCUIDStr;
- C.setContainsError();
- return true;
- }
- }
// --offload and --offload-arch options are mutually exclusive.
if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
@@ -4360,6 +4369,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Build the pipeline for this file.
Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
+ if (CUIDOpts.isEnabled() && types::isSrcFile(InputType))
+ cast<InputAction>(Current)->setId(
+ CUIDOpts.getCUID(InputArg->getValue(), Args));
+
// Use the current host action in any of the offloading actions, if
// required.
if (!UseNewOffloadingDriver)
@@ -4805,8 +4818,12 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
TCAndArchs.push_back(std::make_pair(TC, Arch));
}
- for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)
- DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));
+ for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I) {
+ auto *IA = C.MakeAction<InputAction>(*InputArg, InputType);
+ if (CUIDOpts.isEnabled())
+ IA->setId(CUIDOpts.getCUID(IA->getInputArg().getValue(), Args));
+ DeviceActions.push_back(IA);
+ }
if (DeviceActions.empty())
return HostAction;
diff --git a/clang/test/Driver/hip-cuid.hip b/clang/test/Driver/hip-cuid.hip
index 2e38c59ccf5ef1..48264950b22344 100644
--- a/clang/test/Driver/hip-cuid.hip
+++ b/clang/test/Driver/hip-cuid.hip
@@ -80,6 +80,17 @@
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
// RUN: 2>&1 | FileCheck -check-prefixes=DEVICE %s
+// Check cuid is supported by the new driver.
+// RUN: %clang -### -x hip \
+// RUN: --target=x86_64-unknown-linux-gnu \
+// RUN: --no-offload-new-driver \
+// RUN: --offload-arch=gfx900 \
+// RUN: --offload-arch=gfx906 \
+// RUN: -c -nogpuinc -nogpulib --offload-new-driver \
+// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
+// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
+// RUN: 2>&1 | FileCheck -check-prefixes=COMMON,HEX %s
+
// INVALID: invalid value 'invalid' in '-fuse-cuid=invalid'
// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
More information about the cfe-commits
mailing list