Author: Joseph Huber Date: 2023-06-20T08:02:59-05:00 New Revision: efacdfc235e327341d2b8a733d9963fb526cf17b
URL: https://github.com/llvm/llvm-project/commit/efacdfc235e327341d2b8a733d9963fb526cf17b DIFF: https://github.com/llvm/llvm-project/commit/efacdfc235e327341d2b8a733d9963fb526cf17b.diff LOG: [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 Added: Modified: clang/test/Driver/linker-wrapper.c clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td Removed: ################################################################################ diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index 97058a96465f8..140cc72886692 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -130,3 +130,12 @@ // RUN: -o a.out 2>&1 | FileCheck %s --check-prefix=MISSING-LIBRARY // MISSING-LIBRARY: error: unable to find library -ldummy + +// RUN: clang-offload-packager -o %t.out \ +// RUN: --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 \ +// RUN: --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 +// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out +// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --clang-backend \ +// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CLANG-BACKEND + +// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.bc diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 0af0f2e371b18..c553cf86da8e3 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -427,6 +427,17 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args) { for (StringRef Arg : Args.getAllArgValues(OPT_linker_arg_EQ)) CmdArgs.push_back(Args.MakeArgString("-Wl," + Arg)); + for (StringRef Arg : Args.getAllArgValues(OPT_builtin_bitcode_EQ)) { + if (llvm::Triple(Arg.split('=').first) == Triple) + CmdArgs.append({"-Xclang", "-mlink-builtin-bitcode", "-Xclang", + Args.MakeArgString(Arg.split('=').second)}); + } + + // The OpenMPOpt pass can introduce new calls and is expensive, we do not want + // this when running CodeGen through clang. + if (Args.hasArg(OPT_clang_backend) || Args.hasArg(OPT_builtin_bitcode_EQ)) + CmdArgs.append({"-mllvm", "-openmp-opt-disable"}); + if (Error Err = executeCommands(*ClangPath, CmdArgs)) return std::move(Err); @@ -629,7 +640,7 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles, llvm::erase_if(InputFiles, [](OffloadFile &F) { return !F.getBinary(); }); // LTO Module hook to output bitcode without running the backend. - SmallVector<StringRef, 4> BitcodeOutput; + SmallVector<StringRef> BitcodeOutput; auto OutputBitcode = [&](size_t, const Module &M) { auto TempFileOrErr = createOutputFile(sys::path::filename(ExecutableName) + "-jit-" + Triple.getTriple(), @@ -648,7 +659,9 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles, // We assume visibility of the whole program if every input file was bitcode. auto Features = getTargetFeatures(BitcodeInputFiles); - auto LTOBackend = Args.hasArg(OPT_embed_bitcode) + auto LTOBackend = Args.hasArg(OPT_embed_bitcode) || + Args.hasArg(OPT_builtin_bitcode_EQ) || + Args.hasArg(OPT_clang_backend) ? createLTO(Args, Features, OutputBitcode) : createLTO(Args, Features); @@ -757,8 +770,12 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles, return Error::success(); } - // Append the new inputs to the device linker input. - for (StringRef File : Files) + // Append the new inputs to the device linker input. If the user requested an + // internalizing link we need to pass the bitcode to clang. + for (StringRef File : + Args.hasArg(OPT_clang_backend) || Args.hasArg(OPT_builtin_bitcode_EQ) + ? BitcodeOutput + : Files) OutputFiles.push_back(File); return Error::success(); diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td index 5dace9766e0c1..abab4d0b39b90 100644 --- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td +++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td @@ -25,9 +25,16 @@ def opt_level : Joined<["--"], "opt-level=">, def bitcode_library_EQ : Joined<["--"], "bitcode-library=">, Flags<[WrapperOnlyOption]>, MetaVarName<"<kind>-<triple>-<arch>=<path>">, HelpText<"Extra bitcode library to link">; +def builtin_bitcode_EQ : Joined<["--"], "builtin-bitcode=">, + Flags<[WrapperOnlyOption]>, MetaVarName<"<triple>=<path>">, + HelpText<"Perform a special internalizing link on the bitcode file. " + "This is necessary for some vendor libraries to be linked correctly">; def device_linker_args_EQ : Joined<["--"], "device-linker=">, Flags<[WrapperOnlyOption]>, MetaVarName<"<value> or <triple>=<value>">, HelpText<"Arguments to pass to the device linker invocation">; +def clang_backend : Flag<["--"], "clang-backend">, + Flags<[WrapperOnlyOption]>, + HelpText<"Run the backend using clang rather than the LTO backend">; def dry_run : Flag<["--"], "dry-run">, Flags<[WrapperOnlyOption]>, HelpText<"Print program arguments without running">; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits