Skip to content

Commit 737bb8c

Browse files
committed
[DTLTO][Clang] Add support for Integrated Distributed ThinLTO
This patch introduces support for Integrated Distributed ThinLTO (DTLTO) in Clang. DTLTO enables the distribution of ThinLTO backend compilations via external distribution systems, such as Incredibuild, during the traditional link step: https://llvm.org/docs/DTLTO.html. Testing: - `lit` test coverage has been added to Clang's Driver tests. - The DTLTO cross-project tests will use this Clang support. For the design discussion of the DTLTO feature, see: llvm#126654 Note that I have removed the forwarding of -mllvm options to the backend compilations which was discussed in the design review from this patch. LTO configuration for DTLTO will be addressed in a follow-up patch. In the meantime -mllvm options can be forwarded manually if required.
1 parent e9be528 commit 737bb8c

File tree

5 files changed

+116
-19
lines changed

5 files changed

+116
-19
lines changed

clang/docs/ThinLTO.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,38 @@ The ``BOOTSTRAP_LLVM_ENABLE_LTO=Thin`` will enable ThinLTO for stage 2 and
240240
stage 3 in case the compiler used for stage 1 does not support the ThinLTO
241241
option.
242242

243+
Integrated Distributed ThinLTO (DTLTO)
244+
--------------------------------------
245+
246+
Integrated Distributed ThinLTO (DTLTO) enables the distribution of backend
247+
ThinLTO compilations via external distribution systems, such as Incredibuild,
248+
during the traditional link step.
249+
250+
The implementation is documented here: https://llvm.org/docs/DTLTO.html.
251+
252+
DTLTO requires the LLD linker (``-fuse-ld=lld``).
253+
254+
``-fthinlto-distributor=<path>``
255+
- Specifies the ``<path>`` to the distributor process executable for DTLTO.
256+
- If specified, ThinLTO backend compilations will be distributed by LLD.
257+
258+
``-Xthinlto-distributor=<arg>``
259+
- Passes ``<arg>`` to the distributor process (see ``-fthinlto-distributor=``).
260+
- Can be specified multiple times to pass multiple options.
261+
- Multiple options can also be specified by separating them with commas.
262+
263+
Examples:
264+
- ``clang -flto=thin -fthinlto-distributor=incredibuild.exe -Xthinlto-distributor=--verbose,--j10 -fuse-ld=lld``
265+
- ``clang -flto=thin -fthinlto-distributor=$(which python) -Xthinlto-distributor=incredibuild.py -fuse-ld=lld``
266+
267+
If ``-fthinlto-distributor=`` is specified, Clang supplies the path to a
268+
compiler to be executed remotely to perform the ThinLTO backend
269+
compilations. Currently, this is Clang itself.
270+
271+
Note that currently, DTLTO is only supported in some LLD flavors. Support will
272+
be added to other LLD flavours in the future.
273+
See `DTLTO <https://lld.llvm.org/dtlto.html>`_ for more information.
274+
243275
More Information
244276
================
245277

clang/include/clang/Driver/Options.td

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,13 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
990990
Visibility<[ClangOption, CLOption, FlangOption]>,
991991
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
992992
Group<Link_Group>;
993+
def Xthinlto_distributor_EQ : CommaJoined<["-"], "Xthinlto-distributor=">,
994+
Flags<[LinkOption]>,
995+
Visibility<[ClangOption, CLOption]>,
996+
HelpText<"Pass <arg> to the ThinLTO distributor process. Can be specified "
997+
"multiple times or with comma-separated values.">,
998+
MetaVarName<"<arg>">,
999+
Group<Link_Group>;
9931000
def Xoffload_linker : JoinedAndSeparate<["-"], "Xoffload-linker">,
9941001
Visibility<[ClangOption, FlangOption]>,
9951002
HelpText<"Pass <arg> to the offload linkers or the ones identified by -<triple>">,
@@ -4233,7 +4240,12 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
42334240
def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
42344241
HelpText<"Do not assume that any loop is finite.">,
42354242
Visibility<[ClangOption, CC1Option]>;
4236-
4243+
def fthinlto_distributor_EQ : Joined<["-"], "fthinlto-distributor=">,
4244+
Group<f_Group>,
4245+
HelpText<"Path to the ThinLTO distributor process. If specified, "
4246+
"ThinLTO backend compilations will be distributed by LLD">,
4247+
MetaVarName<"<path>">,
4248+
Visibility<[ClangOption, CLOption]>;
42374249
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
42384250
HelpText<"Process trigraph sequences">, Visibility<[ClangOption, CC1Option]>;
42394251
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,21 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
455455
addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs,
456456
D.getLTOMode() == LTOK_Thin);
457457

458+
// Forward the DTLTO options to the linker. We add these unconditionally,
459+
// rather than in addLTOOptions() as it is the linker that decides whether to
460+
// do LTO or not dependent upon whether there are any bitcode input files in
461+
// the link.
462+
if (Arg *A = Args.getLastArg(options::OPT_fthinlto_distributor_EQ)) {
463+
CmdArgs.push_back(
464+
Args.MakeArgString("--thinlto-distributor=" + Twine(A->getValue())));
465+
CmdArgs.push_back(
466+
Args.MakeArgString("--thinlto-remote-compiler=" +
467+
Twine(ToolChain.getDriver().getClangProgramPath())));
468+
469+
for (auto A : Args.getAllArgValues(options::OPT_Xthinlto_distributor_EQ))
470+
CmdArgs.push_back(Args.MakeArgString("--thinlto-distributor-arg=" + A));
471+
}
472+
458473
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
459474
CmdArgs.push_back("--no-demangle");
460475

clang/test/Driver/DTLTO/dtlto.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// REQUIRES: lld
2+
3+
/// Check DTLTO options are forwarded to the linker.
4+
5+
// RUN: echo "--target=x86_64-linux-gnu \
6+
// RUN: -Xthinlto-distributor=distarg1 \
7+
// RUN: -Xthinlto-distributor=distarg2,distarg3 \
8+
// RUN: -fuse-ld=lld" > %t.rsp
9+
10+
/// Check that options are forwarded as expected with --thinlto-distributor=.
11+
// RUN: %clang -### @%t.rsp -fthinlto-distributor=dist.exe %s 2>&1 | \
12+
// RUN: FileCheck %s --implicit-check-not=warning
13+
14+
// CHECK: ld.lld
15+
// CHECK-SAME: "--thinlto-distributor=dist.exe"
16+
// CHECK-SAME: "--thinlto-remote-compiler={{.*}}clang
17+
// CHECK-SAME: "--thinlto-distributor-arg=distarg1"
18+
// CHECK-SAME: "--thinlto-distributor-arg=distarg2"
19+
// CHECK-SAME: "--thinlto-distributor-arg=distarg3"
20+
21+
22+
/// Check that options are not added without --thinlto-distributor= and
23+
/// that there is an unused option warning issued for -Xthinlto-distributor=
24+
/// options. We specify -flto here as these options should be unaffected by it.
25+
// RUN: %clang -### @%t.rsp -flto=thin %s 2>&1 | \
26+
// RUN: FileCheck %s --check-prefixes=NONE,NOMORE --implicit-check-not=warning
27+
28+
// NONE: warning: argument unused during compilation: '-Xthinlto-distributor=distarg1'
29+
// NONE: warning: argument unused during compilation: '-Xthinlto-distributor=distarg2,distarg3'
30+
// NONE: ld.lld
31+
// NOMORE-NOT: distributor
32+
// NOMORE-NOT: remote-compiler
33+
34+
35+
/// Check the expected arguments are forwarded by default with only
36+
/// --thinlto-distributor=.
37+
// RUN: %clang --target=x86_64-linux-gnu -fthinlto-distributor=dist.exe \
38+
// RUN: -fuse-ld=lld -Werror -### %s 2>&1 | \
39+
// RUN: FileCheck %s --check-prefixes=DEFAULT,NOMORE
40+
41+
// DEFAULT: ld.lld
42+
// DEFAULT-SAME: "--thinlto-distributor=dist.exe"
43+
// DEFAULT-SAME: "--thinlto-remote-compiler={{.*}}clang

cross-project-tests/dtlto/ld-dtlto.c

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55

66
// RUN: rm -rf %t && mkdir %t && cd %t
77

8-
// RUN: %clang --target=x86_64-linux-gnu -c -flto=thin %s -o dtlto.o
9-
10-
// RUN: ld.lld dtlto.o \
11-
// RUN: --thinlto-distributor=%python \
12-
// RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/local.py \
13-
// RUN: --thinlto-remote-compiler=%clang \
14-
// RUN: --thinlto-remote-compiler-arg=--save-temps
8+
// RUN: %clang --target=x86_64-linux-gnu %s -flto=thin -fuse-ld=lld \
9+
// RUN: -fthinlto-distributor=%python \
10+
// RUN: -Xthinlto-distributor=%llvm_src_root/utils/dtlto/local.py \
11+
// RUN: -Wl,--thinlto-remote-compiler-arg=--save-temps \
12+
// RUN: -nostdlib -Werror
1513

1614
/// Check that the required output files have been created.
1715
// RUN: ls | sort | FileCheck %s
@@ -22,18 +20,15 @@
2220
/// Linked ELF.
2321
// CHECK: {{^}}a.out{{$}}
2422

25-
/// Produced by the bitcode compilation.
26-
// CHECK-NEXT: {{^}}dtlto.o{{$}}
27-
2823
/// --save-temps output for the backend compilation.
29-
// CHECK-NEXT: {{^}}dtlto.s{{$}}
30-
// CHECK-NEXT: {{^}}dtlto.s.0.preopt.bc{{$}}
31-
// CHECK-NEXT: {{^}}dtlto.s.1.promote.bc{{$}}
32-
// CHECK-NEXT: {{^}}dtlto.s.2.internalize.bc{{$}}
33-
// CHECK-NEXT: {{^}}dtlto.s.3.import.bc{{$}}
34-
// CHECK-NEXT: {{^}}dtlto.s.4.opt.bc{{$}}
35-
// CHECK-NEXT: {{^}}dtlto.s.5.precodegen.bc{{$}}
36-
// CHECK-NEXT: {{^}}dtlto.s.resolution.txt{{$}}
24+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP:[a-zA-Z0-9_]+]].s{{$}}
25+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.0.preopt.bc{{$}}
26+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.1.promote.bc{{$}}
27+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.2.internalize.bc{{$}}
28+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.3.import.bc{{$}}
29+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.4.opt.bc{{$}}
30+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.5.precodegen.bc{{$}}
31+
// CHECK-NEXT: {{^}}ld-dtlto-[[TMP]].s.resolution.txt{{$}}
3732

3833
/// No files are expected after.
3934
// CHECK-NOT: {{.}}

0 commit comments

Comments
 (0)