Skip to content

Commit 535d691

Browse files
authored
[Clang] Extract offloading code from static libs with 'offload-arch=' (#147823)
Summary: The semantics of static libraries only extract stuff that's used. We somewhat extend this behavior with the linker wrapper only doing this to fat binaries that match any found architectures. However, this has some unfortunate effects when the user uses static libraries. This is somewhat of a hack, but we now assume that if the user specified `--offload-arch=` on the link job, they *definitely* want that architecture to be used if it exists. This patch just forces extraction of those libraries which resolves an issue observed with some customers. The old behavior will still be present if the user does `--offload-link` with no offloading architecture present, and for the vast, vast majority of cases this will change nothing. Fixes: #147788
1 parent 2fdeeef commit 535d691

File tree

4 files changed

+28
-4
lines changed

4 files changed

+28
-4
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9156,7 +9156,9 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
91569156
// specific architecture via -Xarch_<cpu> will not be forwarded.
91579157
ArgStringList CompilerArgs;
91589158
ArgStringList LinkerArgs;
9159-
for (Arg *A : C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind)) {
9159+
const DerivedArgList &ToolChainArgs =
9160+
C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind);
9161+
for (Arg *A : ToolChainArgs) {
91609162
if (A->getOption().matches(OPT_Zlinker_input))
91619163
LinkerArgs.emplace_back(A->getValue());
91629164
else if (ShouldForward(CompilerOptions, A))
@@ -9165,6 +9167,11 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
91659167
A->render(Args, LinkerArgs);
91669168
}
91679169

9170+
// If the user explicitly requested it via `--offload-arch` we should
9171+
// extract it from any static libraries if present.
9172+
for (StringRef Arg : ToolChainArgs.getAllArgValues(OPT_offload_arch_EQ))
9173+
CmdArgs.emplace_back(Args.MakeArgString("--should-extract=" + Arg));
9174+
91689175
// If this is OpenMP the device linker will need `-lompdevice`.
91699176
if (Kind == Action::OFK_OpenMP && !Args.hasArg(OPT_no_offloadlib) &&
91709177
(TC->getTriple().isAMDGPU() || TC->getTriple().isNVPTX()))

clang/test/Driver/openmp-offload-gpu.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,3 +395,12 @@
395395
// RUN: --offload-arch=sm_52 -foffload-lto=thin -nogpulib -nogpuinc %s 2>&1 \
396396
// RUN: | FileCheck --check-prefix=THINLTO-SM52 %s
397397
// THINLTO-SM52: --device-compiler=nvptx64-nvidia-cuda=-flto=thin
398+
399+
//
400+
// Check the requested architecture is passed if provided.
401+
//
402+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp=libomp \
403+
// RUN: --offload-arch=gfx906 -foffload-lto=thin -nogpulib -nogpuinc %s 2>&1 \
404+
// RUN: | FileCheck --check-prefix=SHOULD-EXTRACT %s
405+
//
406+
// SHOULD-EXTRACT: clang-linker-wrapper{{.*}}"--should-extract=gfx906"

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,9 @@ getDeviceInput(const ArgList &Args) {
13021302
// after every regular input file so that libraries may be included out of
13031303
// order. This follows 'ld.lld' semantics which are more lenient.
13041304
bool Extracted = true;
1305+
llvm::DenseSet<StringRef> ShouldExtract;
1306+
for (auto &Arg : Args.getAllArgValues(OPT_should_extract))
1307+
ShouldExtract.insert(Arg);
13051308
while (Extracted) {
13061309
Extracted = false;
13071310
for (OffloadFile &Binary : ArchiveFilesToExtract) {
@@ -1315,8 +1318,9 @@ getDeviceInput(const ArgList &Args) {
13151318
CompatibleTargets.emplace_back(ID);
13161319

13171320
for (const auto &[Index, ID] : llvm::enumerate(CompatibleTargets)) {
1318-
// Only extract an if we have an an object matching this target.
1319-
if (!InputFiles.count(ID))
1321+
// Only extract an if we have an an object matching this target or it
1322+
// was specifically requested.
1323+
if (!InputFiles.count(ID) && !ShouldExtract.contains(ID.second))
13201324
continue;
13211325

13221326
Expected<bool> ExtractOrErr =
@@ -1330,7 +1334,7 @@ getDeviceInput(const ArgList &Args) {
13301334

13311335
// Skip including the file if it is an archive that does not resolve
13321336
// any symbols.
1333-
if (!Extracted)
1337+
if (!Extracted && !ShouldExtract.contains(ID.second))
13341338
continue;
13351339

13361340
// If another target needs this binary it must be copied instead.

clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ def override_image : Joined<["--"], "override-image=">,
5959
Flags<[WrapperOnlyOption]>, MetaVarName<"<kind=file>">,
6060
HelpText<"Uses the provided file as if it were the output of the device link step">;
6161

62+
def should_extract : CommaJoined<["--"], "should-extract=">,
63+
Flags<[WrapperOnlyOption]>, MetaVarName<"<kind=file>">,
64+
HelpText<"Set of device architectures we should always extract if found.">;
65+
6266
// Flags passed to the device linker.
6367
def arch_EQ : Joined<["--"], "arch=">,
6468
Flags<[DeviceOnlyOption, HelpHidden]>, MetaVarName<"<arch>">,

0 commit comments

Comments
 (0)