Skip to content

Commit efacdfc

Browse files
committed
[LinkerWrapper] Support linking vendor bitcode late
The GPU vendors currently provide bitcode files for their device runtime. These files need to be handled specially as they are not built to be linked in with a standard `llvm-link` call or through LTO linking. This patch adds an alternative to use the existing clang handling of these libraries that does the necessary magic to make this work. We do this by causing the LTO backend to emit bitcode before running the backend. We then pass this through to clang which uses the existing support which has been fixed to support this by D152391. The backend will then be run with the merged module. This patch adds the `--builtin-bitcode=<triple>=file.bc` to specify a single file, or just `--clang-backend` to let the toolchain handle its defaults (currently nothing for NVPTX and the ROCm device libs for AMDGPU). This may have a performance impact due to running the optimizations again, we could potentially disable optimizations in LTO and only do the linking if this is an issue. This should allow us to resolve issues when relying on the `linker-wrapper` to do a late linking that may depend on vendor libraries. Depends on D152391 Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D152442
1 parent 8784b6a commit efacdfc

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

clang/test/Driver/linker-wrapper.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,12 @@
130130
// RUN: -o a.out 2>&1 | FileCheck %s --check-prefix=MISSING-LIBRARY
131131

132132
// MISSING-LIBRARY: error: unable to find library -ldummy
133+
134+
// RUN: clang-offload-packager -o %t.out \
135+
// RUN: --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 \
136+
// RUN: --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908
137+
// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
138+
// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --clang-backend \
139+
// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CLANG-BACKEND
140+
141+
// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.bc

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,17 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) {
427427
for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ))
428428
CmdArgs.push_back(Args.MakeArgString("-Wl," + Arg));
429429

430+
for (StringRef Arg : Args.getAllArgValues(OPT_builtin_bitcode_EQ)) {
431+
if (llvm::Triple(Arg.split('=').first) == Triple)
432+
CmdArgs.append({"-Xclang", "-mlink-builtin-bitcode", "-Xclang",
433+
Args.MakeArgString(Arg.split('=').second)});
434+
}
435+
436+
// The OpenMPOpt pass can introduce new calls and is expensive, we do not want
437+
// this when running CodeGen through clang.
438+
if (Args.hasArg(OPT_clang_backend) || Args.hasArg(OPT_builtin_bitcode_EQ))
439+
CmdArgs.append({"-mllvm", "-openmp-opt-disable"});
440+
430441
if (Error Err = executeCommands(*ClangPath, CmdArgs))
431442
return std::move(Err);
432443

@@ -629,7 +640,7 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
629640
llvm::erase_if(InputFiles, [](OffloadFile &F) { return !F.getBinary(); });
630641

631642
// LTO Module hook to output bitcode without running the backend.
632-
SmallVector<StringRef, 4> BitcodeOutput;
643+
SmallVector<StringRef> BitcodeOutput;
633644
auto OutputBitcode = [&](size_t, const Module &M) {
634645
auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) +
635646
"-jit-" + Triple.getTriple(),
@@ -648,7 +659,9 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
648659

649660
// We assume visibility of the whole program if every input file was bitcode.
650661
auto Features = getTargetFeatures(BitcodeInputFiles);
651-
auto LTOBackend = Args.hasArg(OPT_embed_bitcode)
662+
auto LTOBackend = Args.hasArg(OPT_embed_bitcode) ||
663+
Args.hasArg(OPT_builtin_bitcode_EQ) ||
664+
Args.hasArg(OPT_clang_backend)
652665
? createLTO(Args, Features, OutputBitcode)
653666
: createLTO(Args, Features);
654667

@@ -757,8 +770,12 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
757770
return Error::success();
758771
}
759772

760-
// Append the new inputs to the device linker input.
761-
for (StringRef File : Files)
773+
// Append the new inputs to the device linker input. If the user requested an
774+
// internalizing link we need to pass the bitcode to clang.
775+
for (StringRef File :
776+
Args.hasArg(OPT_clang_backend) || Args.hasArg(OPT_builtin_bitcode_EQ)
777+
? BitcodeOutput
778+
: Files)
762779
OutputFiles.push_back(File);
763780

764781
return Error::success();

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,16 @@ def opt_level : Joined<["--"], "opt-level=">,
2525
def bitcode_library_EQ : Joined<["--"], "bitcode-library=">,
2626
Flags<[WrapperOnlyOption]>, MetaVarName<"<kind>-<triple>-<arch>=<path>">,
2727
HelpText<"Extra bitcode library to link">;
28+
def builtin_bitcode_EQ : Joined<["--"], "builtin-bitcode=">,
29+
Flags<[WrapperOnlyOption]>, MetaVarName<"<triple>=<path>">,
30+
HelpText<"Perform a special internalizing link on the bitcode file. "
31+
"This is necessary for some vendor libraries to be linked correctly">;
2832
def device_linker_args_EQ : Joined<["--"], "device-linker=">,
2933
Flags<[WrapperOnlyOption]>, MetaVarName<"<value> or <triple>=<value>">,
3034
HelpText<"Arguments to pass to the device linker invocation">;
35+
def clang_backend : Flag<["--"], "clang-backend">,
36+
Flags<[WrapperOnlyOption]>,
37+
HelpText<"Run the backend using clang rather than the LTO backend">;
3138
def dry_run : Flag<["--"], "dry-run">,
3239
Flags<[WrapperOnlyOption]>,
3340
HelpText<"Print program arguments without running">;

0 commit comments

Comments
 (0)