Skip to content

Commit 98c2128

Browse files
committed
[CUDA][HIP] Add -fuse-cuid
This patch added a distinct CUID for each input file, which is represented by InputAction. clang initially creates an InputAction for each input file for the host compilation. In CUDA/HIP action builder, each InputAction is given a CUID and cloned for each GPU arch, and the CUID is also cloned. In this way, we guarantee the corresponding device and host compilation for the same file shared the same CUID. On the other hand, different compilation units have different CUID. -fuse-cuid=random|hash|none is added to control the method to generate CUID. The default is hash. -cuid=X is also added to specify CUID explicitly, which overrides -fuse-cuid. Reviewed by: Artem Belevich Differential Revision: https://reviews.llvm.org/D95007
1 parent 7dc324a commit 98c2128

File tree

9 files changed

+219
-5
lines changed

9 files changed

+219
-5
lines changed

clang/include/clang/Basic/LangOptions.h

+6
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,12 @@ class LangOptions : public LangOptionsBase {
331331
/// host code generation.
332332
std::string OMPHostIRFile;
333333

334+
/// The user provided compilation unit ID, if non-empty. This is used to
335+
/// externalize static variables which is needed to support accessing static
336+
/// device variables in host code for single source offloading languages
337+
/// like CUDA/HIP.
338+
std::string CUID;
339+
334340
/// Indicates whether the front-end is explicitly told that the
335341
/// input is a header file (i.e. -x c-header).
336342
bool IsHeaderFile = false;

clang/include/clang/Driver/Action.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,18 @@ class Action {
214214

215215
class InputAction : public Action {
216216
const llvm::opt::Arg &Input;
217-
217+
std::string Id;
218218
virtual void anchor();
219219

220220
public:
221-
InputAction(const llvm::opt::Arg &Input, types::ID Type);
221+
InputAction(const llvm::opt::Arg &Input, types::ID Type,
222+
StringRef Id = StringRef());
222223

223224
const llvm::opt::Arg &getInputArg() const { return Input; }
224225

226+
void setId(StringRef _Id) { Id = _Id.str(); }
227+
StringRef getId() const { return Id; }
228+
225229
static bool classof(const Action *A) {
226230
return A->getKind() == InputClass;
227231
}

clang/include/clang/Driver/Options.td

+12
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,18 @@ def gpu_max_threads_per_block_EQ : Joined<["--"], "gpu-max-threads-per-block=">,
930930
def gpu_instrument_lib_EQ : Joined<["--"], "gpu-instrument-lib=">,
931931
HelpText<"Instrument device library for HIP, which is a LLVM bitcode containing "
932932
"__cyg_profile_func_enter and __cyg_profile_func_exit">;
933+
def cuid_EQ : Joined<["-"], "cuid=">, Flags<[CC1Option]>,
934+
HelpText<"An ID for compilation unit, which should be the same for the same "
935+
"compilation unit but different for different compilation units. "
936+
"It is used to externalize device-side static variables for single "
937+
"source offloading languages CUDA and HIP so that they can be "
938+
"accessed by the host code of the same compilation unit.">;
939+
def fuse_cuid_EQ : Joined<["-"], "fuse-cuid=">,
940+
HelpText<"Method to generate ID's for compilation units for single source "
941+
"offloading languages CUDA and HIP: 'hash' (ID's generated by hashing "
942+
"file path and command line options) | 'random' (ID's generated as "
943+
"random numbers) | 'none' (disabled). Default is 'hash'. This option "
944+
"will be overriden by option '-cuid=[ID]' if it is specified." >;
933945
def libomptarget_nvptx_bc_path_EQ : Joined<["--"], "libomptarget-nvptx-bc-path=">, Group<i_Group>,
934946
HelpText<"Path to libomptarget-nvptx bitcode library">;
935947
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,

clang/lib/Driver/Action.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ StringRef Action::GetOffloadKindName(OffloadKind Kind) {
165165

166166
void InputAction::anchor() {}
167167

168-
InputAction::InputAction(const Arg &_Input, types::ID _Type)
169-
: Action(InputClass, _Type), Input(_Input) {}
168+
InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
169+
: Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}
170170

171171
void BindArchAction::anchor() {}
172172

clang/lib/Driver/Driver.cpp

+48-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "llvm/Support/FileSystem.h"
7878
#include "llvm/Support/FormatVariadic.h"
7979
#include "llvm/Support/Host.h"
80+
#include "llvm/Support/MD5.h"
8081
#include "llvm/Support/Path.h"
8182
#include "llvm/Support/PrettyStackTrace.h"
8283
#include "llvm/Support/Process.h"
@@ -2453,6 +2454,14 @@ class OffloadingActionBuilder final {
24532454
/// Default GPU architecture if there's no one specified.
24542455
CudaArch DefaultCudaArch = CudaArch::UNKNOWN;
24552456

2457+
/// Method to generate compilation unit ID specified by option
2458+
/// '-fuse-cuid='.
2459+
enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
2460+
UseCUIDKind UseCUID = CUID_Hash;
2461+
2462+
/// Compilation unit ID specified by option '-cuid='.
2463+
StringRef FixedCUID;
2464+
24562465
public:
24572466
CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
24582467
const Driver::InputList &Inputs,
@@ -2489,9 +2498,32 @@ class OffloadingActionBuilder final {
24892498
// Replicate inputs for each GPU architecture.
24902499
auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
24912500
: types::TY_CUDA_DEVICE;
2501+
std::string CUID = FixedCUID.str();
2502+
if (CUID.empty()) {
2503+
if (UseCUID == CUID_Random)
2504+
CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
2505+
/*LowerCase=*/true);
2506+
else if (UseCUID == CUID_Hash) {
2507+
llvm::MD5 Hasher;
2508+
llvm::MD5::MD5Result Hash;
2509+
SmallString<256> RealPath;
2510+
llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
2511+
/*expand_tilde=*/true);
2512+
Hasher.update(RealPath);
2513+
for (auto *A : Args) {
2514+
if (A->getOption().matches(options::OPT_INPUT))
2515+
continue;
2516+
Hasher.update(A->getAsString(Args));
2517+
}
2518+
Hasher.final(Hash);
2519+
CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
2520+
}
2521+
}
2522+
IA->setId(CUID);
2523+
24922524
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
24932525
CudaDeviceActions.push_back(
2494-
C.MakeAction<InputAction>(IA->getInputArg(), Ty));
2526+
C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));
24952527
}
24962528

24972529
return ABRT_Success;
@@ -2613,6 +2645,21 @@ class OffloadingActionBuilder final {
26132645
options::OPT_cuda_device_only);
26142646
EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
26152647
EmitAsm = Args.getLastArg(options::OPT_S);
2648+
FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
2649+
if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
2650+
StringRef UseCUIDStr = A->getValue();
2651+
UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
2652+
.Case("hash", CUID_Hash)
2653+
.Case("random", CUID_Random)
2654+
.Case("none", CUID_None)
2655+
.Default(CUID_Invalid);
2656+
if (UseCUID == CUID_Invalid) {
2657+
C.getDriver().Diag(diag::err_drv_invalid_value)
2658+
<< A->getAsString(Args) << UseCUIDStr;
2659+
C.setContainsError();
2660+
return true;
2661+
}
2662+
}
26162663

26172664
// Collect all cuda_gpu_arch parameters, removing duplicates.
26182665
std::set<StringRef> GpuArchs;

clang/lib/Driver/ToolChains/Clang.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -6332,6 +6332,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
63326332
CmdArgs.push_back("-fcuda-short-ptr");
63336333
}
63346334

6335+
if (IsCuda || IsHIP) {
6336+
// Determine the original source input.
6337+
const Action *SourceAction = &JA;
6338+
while (SourceAction->getKind() != Action::InputClass) {
6339+
assert(!SourceAction->getInputs().empty() && "unexpected root action!");
6340+
SourceAction = SourceAction->getInputs()[0];
6341+
}
6342+
auto CUID = cast<InputAction>(SourceAction)->getId();
6343+
if (!CUID.empty())
6344+
CmdArgs.push_back(Args.MakeArgString(Twine("-cuid=") + Twine(CUID)));
6345+
}
6346+
63356347
if (IsHIP)
63366348
CmdArgs.push_back("-fcuda-allow-variadic-functions");
63376349

clang/lib/Frontend/CompilerInvocation.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -2741,6 +2741,11 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
27412741
}
27422742
}
27432743

2744+
2745+
if (auto *A = Args.getLastArg(OPT_cuid_EQ)) {
2746+
Opts.CUID = std::string(A->getValue());
2747+
}
2748+
27442749
if (Opts.ObjC) {
27452750
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
27462751
StringRef value = arg->getValue();

clang/test/Driver/hip-cuid-hash.hip

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// REQUIRES: clang-driver
2+
// REQUIRES: x86-registered-target
3+
// REQUIRES: amdgpu-registered-target
4+
5+
// Check CUID generated by hash.
6+
// The same CUID is generated for the same file with the same options.
7+
8+
// RUN: %clang -### -x hip -target x86_64-unknown-linux-gnu \
9+
// RUN: --offload-arch=gfx906 -c -nogpulib -fuse-cuid=hash \
10+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu >%t.out 2>&1
11+
12+
// RUN: %clang -### -x hip -target x86_64-unknown-linux-gnu \
13+
// RUN: --offload-arch=gfx906 -c -nogpulib -fuse-cuid=hash \
14+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu >>%t.out 2>&1
15+
16+
// RUN: FileCheck %s -check-prefixes=SAME -input-file %t.out
17+
18+
// Check CUID generated by hash.
19+
// Different CUID's are generated for the same file with different options.
20+
21+
// RUN: %clang -### -x hip -target x86_64-unknown-linux-gnu -DX=1 \
22+
// RUN: --offload-arch=gfx906 -c -nogpulib -fuse-cuid=hash \
23+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu >%t.out 2>&1
24+
25+
// RUN: %clang -### -x hip -target x86_64-unknown-linux-gnu -DX=2 \
26+
// RUN: --offload-arch=gfx906 -c -nogpulib -fuse-cuid=hash \
27+
// RUN: %S/Inputs/../Inputs/hip_multiple_inputs/a.cu >>%t.out 2>&1
28+
29+
// RUN: FileCheck %s -check-prefixes=DIFF -input-file %t.out
30+
31+
// SAME: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]"
32+
// SAME: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]"
33+
34+
// DIFF: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID:[0-9a-f]+]]"
35+
// DIFF-NOT: "{{.*}}clang{{.*}}" {{.*}} "-target-cpu" "gfx906" {{.*}}"-cuid=[[CUID]]"

clang/test/Driver/hip-cuid.hip

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// REQUIRES: clang-driver
2+
// REQUIRES: x86-registered-target
3+
// REQUIRES: amdgpu-registered-target
4+
5+
// Check invalid -fuse-cuid= option.
6+
7+
// RUN: not %clang -### -x hip \
8+
// RUN: -target x86_64-unknown-linux-gnu \
9+
// RUN: --offload-arch=gfx900 \
10+
// RUN: --offload-arch=gfx906 \
11+
// RUN: -c -nogpulib -fuse-cuid=invalid \
12+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
13+
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
14+
// RUN: 2>&1 | FileCheck -check-prefixes=INVALID %s
15+
16+
// Check random CUID generator.
17+
18+
// RUN: %clang -### -x hip \
19+
// RUN: -target x86_64-unknown-linux-gnu \
20+
// RUN: --offload-arch=gfx900 \
21+
// RUN: --offload-arch=gfx906 \
22+
// RUN: -c -nogpulib -fuse-cuid=random \
23+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
24+
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
25+
// RUN: 2>&1 | FileCheck -check-prefixes=COMMON,HEX %s
26+
27+
// Check fixed CUID.
28+
29+
// RUN: %clang -### -x hip \
30+
// RUN: -target x86_64-unknown-linux-gnu \
31+
// RUN: --offload-arch=gfx900 \
32+
// RUN: --offload-arch=gfx906 \
33+
// RUN: -c -nogpulib -cuid=xyz_123 \
34+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
35+
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
36+
// RUN: 2>&1 | FileCheck -check-prefixes=COMMON,FIXED %s
37+
38+
// Check fixed CUID override -fuse-cuid.
39+
40+
// RUN: %clang -### -x hip \
41+
// RUN: -target x86_64-unknown-linux-gnu \
42+
// RUN: --offload-arch=gfx900 \
43+
// RUN: --offload-arch=gfx906 \
44+
// RUN: -c -nogpulib -fuse-cuid=random -cuid=xyz_123 \
45+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
46+
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
47+
// RUN: 2>&1 | FileCheck -check-prefixes=COMMON,FIXED %s
48+
49+
// Check hash CUID generator.
50+
51+
// RUN: %clang -### -x hip \
52+
// RUN: -target x86_64-unknown-linux-gnu \
53+
// RUN: --offload-arch=gfx900 \
54+
// RUN: --offload-arch=gfx906 \
55+
// RUN: -c -nogpulib -fuse-cuid=hash \
56+
// RUN: %S/Inputs/hip_multiple_inputs/a.cu \
57+
// RUN: %S/Inputs/hip_multiple_inputs/b.hip \
58+
// RUN: 2>&1 | FileCheck -check-prefixes=COMMON,HEX %s
59+
60+
// INVALID: invalid value 'invalid' in '-fuse-cuid=invalid'
61+
62+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
63+
// COMMON-SAME: "-target-cpu" "gfx900"
64+
// HEX-SAME: "-cuid=[[CUID:[0-9a-f]+]]"
65+
// FIXED-SAME: "-cuid=[[CUID:xyz_123]]"
66+
// COMMON-SAME: "{{.*}}a.cu"
67+
68+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
69+
// COMMON-SAME: "-target-cpu" "gfx906"
70+
// COMMON-SAME: "-cuid=[[CUID]]"
71+
// COMMON-SAME: "{{.*}}a.cu"
72+
73+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu"
74+
// COMMON-SAME: "-cuid=[[CUID]]"
75+
// COMMON-SAME: "{{.*}}a.cu"
76+
77+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
78+
// COMMON-SAME: "-target-cpu" "gfx900"
79+
// HEX-NOT: "-cuid=[[CUID]]"
80+
// HEX-SAME: "-cuid=[[CUID2:[0-9a-f]+]]"
81+
// FIXED-SAME: "-cuid=[[CUID2:xyz_123]]"
82+
// COMMON-SAME: "{{.*}}b.hip"
83+
84+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa"
85+
// COMMON-SAME: "-target-cpu" "gfx906"
86+
// HEX-NOT: "-cuid=[[CUID]]"
87+
// COMMON-SAME: "-cuid=[[CUID2]]"
88+
// COMMON-SAME: "{{.*}}b.hip"
89+
90+
// COMMON: "{{.*}}clang{{.*}}" "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu"
91+
// HEX-NOT: "-cuid=[[CUID]]"
92+
// COMMON-SAME: "-cuid=[[CUID2]]"
93+
// COMMON-SAME: "{{.*}}b.hip"

0 commit comments

Comments
 (0)