Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CUDA][HIP] Support CUID in new driver #122859

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -501,10 +527,11 @@ class Driver {
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
/// \param Input - The input type and arguments
/// \param CUID - The CUID for \p Input
/// \param HostAction - The host action used in the offloading toolchain.
Action *BuildOffloadingActions(Compilation &C,
llvm::opt::DerivedArgList &Args,
const InputTy &Input,
const InputTy &Input, StringRef CUID,
Action *HostAction) const;

/// Returns the set of bound architectures active for this offload kind.
Expand Down Expand Up @@ -728,6 +755,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.
Expand Down
116 changes: 65 additions & 51 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,50 @@ 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)
Expand Down Expand Up @@ -875,6 +919,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
C.addOffloadDeviceToolChain(HIPTC, OFK);
}

if (IsCuda || IsHIP)
CUIDOpts = CUIDOptions(C.getArgs(), *this);

//
// OpenMP
//
Expand Down Expand Up @@ -3156,19 +3203,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,
Expand Down Expand Up @@ -3199,28 +3242,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;
Expand Down Expand Up @@ -3346,21 +3369,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) &&
Expand Down Expand Up @@ -4360,6 +4368,12 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Build the pipeline for this file.
Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);

std::string CUID;
if (CUIDOpts.isEnabled() && types::isSrcFile(InputType)) {
CUID = CUIDOpts.getCUID(InputArg->getValue(), Args);
cast<InputAction>(Current)->setId(CUID);
}

// Use the current host action in any of the offloading actions, if
// required.
if (!UseNewOffloadingDriver)
Expand Down Expand Up @@ -4423,7 +4437,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Try to build the offloading actions and add the result as a dependency
// to the host.
if (UseNewOffloadingDriver)
Current = BuildOffloadingActions(C, Args, I, Current);
Current = BuildOffloadingActions(C, Args, I, CUID, Current);
// Use the current host action in any of the offloading actions, if
// required.
else if (OffloadBuilder->addHostDependenceToDeviceActions(Current,
Expand Down Expand Up @@ -4760,7 +4774,7 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,

Action *Driver::BuildOffloadingActions(Compilation &C,
llvm::opt::DerivedArgList &Args,
const InputTy &Input,
const InputTy &Input, StringRef CUID,
Action *HostAction) const {
// Don't build offloading actions if explicitly disabled or we do not have a
// valid source input and compile action to embed it in. If preprocessing only
Expand Down Expand Up @@ -4801,13 +4815,13 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
llvm::DenseSet<StringRef> Arches = getOffloadArchs(C, Args, Kind, TC);
SmallVector<StringRef, 0> Sorted(Arches.begin(), Arches.end());
llvm::sort(Sorted);
for (StringRef Arch : Sorted)
for (StringRef Arch : Sorted) {
TCAndArchs.push_back(std::make_pair(TC, Arch));
DeviceActions.push_back(
C.MakeAction<InputAction>(*InputArg, InputType, CUID));
}
}

for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)
DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));

if (DeviceActions.empty())
return HostAction;

Expand Down
37 changes: 29 additions & 8 deletions clang/test/Driver/hip-cuid.hip
Original file line number Diff line number Diff line change
Expand Up @@ -80,32 +80,53 @@
// 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

// Check cuid is supported by CUDA by the default new driver.
// RUN: %clang -### -x cu \
// RUN: --target=x86_64-unknown-linux-gnu \
// RUN: --offload-arch=sm_60 \
// RUN: --offload-arch=sm_70 \
// RUN: -c -nogpuinc -nogpulib \
// 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"
// COMMON-SAME: "-target-cpu" "gfx900"
// COMMON: "-cc1"{{.*}} "-triple" "[[TRIP:(amdgcn-amd-amdhsa|nvptx64-nvidia-cuda)]]"
// COMMON-SAME: "-target-cpu" "[[G1:(gfx900|sm_60)]]"
// HEX-SAME: "-cuid=[[CUID:[0-9a-f]+]]"
// FIXED-SAME: "-cuid=[[CUID:xyz_123]]"
// COMMON-SAME: "{{.*}}a.cu"

// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
// COMMON-SAME: "-target-cpu" "gfx906"
// COMMON: "-cc1"{{.*}} "-triple" "[[TRIP]]"
// COMMON-SAME: "-target-cpu" "[[G2:(gfx906|sm_70)]]"
// COMMON-SAME: "-cuid=[[CUID]]"
// COMMON-SAME: "{{.*}}a.cu"

// COMMON: "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu"
// COMMON-SAME: "-cuid=[[CUID]]"
// COMMON-SAME: "{{.*}}a.cu"

// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
// COMMON-SAME: "-target-cpu" "gfx900"
// COMMON: "-cc1"{{.*}} "-triple" "[[TRIP]]"
// COMMON-SAME: "-target-cpu" "[[G1]]"
// HEX-NOT: "-cuid=[[CUID]]"
// HEX-SAME: "-cuid=[[CUID2:[0-9a-f]+]]"
// FIXED-SAME: "-cuid=[[CUID2:xyz_123]]"
// COMMON-SAME: "{{.*}}b.hip"

// COMMON: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
// COMMON-SAME: "-target-cpu" "gfx906"
// COMMON: "-cc1"{{.*}} "-triple" "[[TRIP]]"
// COMMON-SAME: "-target-cpu" "[[G2]]"
// HEX-NOT: "-cuid=[[CUID]]"
// COMMON-SAME: "-cuid=[[CUID2]]"
// COMMON-SAME: "{{.*}}b.hip"
Expand Down
Loading