-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[DTLTO][LLD][ELF] Add support for Integrated Distributed ThinLTO #142757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
d3e6ce0
da45393
f1ca7de
d256457
aa04aff
2006a77
8716e1c
cb5e266
96fa2cb
54b91cc
04fa090
d2a704a
6f9889e
af40a1e
47cd97e
ef5f7f6
a9449ee
b28d34e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Tests for DTLTO (Integrated Distributed ThinLTO) functionality. | ||
|
||
These are integration tests as DTLTO invokes `clang` for code-generation. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// REQUIRES: x86-registered-target,ld.lld | ||
|
||
/// Simple test that DTLTO works with a single input bitcode file and that | ||
/// --save-temps can be applied to the remote compilation. | ||
// RUN: rm -rf %t && mkdir %t && cd %t | ||
|
||
// RUN: %clang --target=x86_64-linux-gnu -c -flto=thin %s | ||
|
||
// RUN: ld.lld dtlto.o \ | ||
// RUN: --thinlto-distributor=%python \ | ||
// RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/local.py \ | ||
// RUN: --thinlto-remote-compiler=%clang \ | ||
// RUN: --thinlto-remote-compiler-arg=--save-temps | ||
|
||
/// Check that the required output files have been created. | ||
// RUN: ls | sort | FileCheck %s | ||
|
||
/// No files are expected before. | ||
// CHECK-NOT: {{.}} | ||
|
||
/// Linked ELF. | ||
// CHECK: {{^}}a.out{{$}} | ||
|
||
/// Produced by the bitcode compilation. | ||
// CHECK-NEXT: {{^}}dtlto.o{{$}} | ||
|
||
/// --save-temps output for the backend compilation. | ||
// CHECK-NEXT: {{^}}dtlto.s{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.0.preopt.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.1.promote.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.2.internalize.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.3.import.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.4.opt.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.5.precodegen.bc{{$}} | ||
// CHECK-NEXT: {{^}}dtlto.s.resolution.txt{{$}} | ||
|
||
/// No files are expected after. | ||
// CHECK-NOT: {{.}} | ||
|
||
int _start() { return 0; } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
if "clang" not in config.available_features: | ||
config.unsupported = True |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
Integrated Distributed ThinLTO (DTLTO) | ||
====================================== | ||
|
||
Integrated Distributed ThinLTO (DTLTO) enables the distribution of backend | ||
ThinLTO compilations via external distribution systems, such as Incredibuild, | ||
during the traditional link step. | ||
|
||
The implementation is documented here: https://llvm.org/docs/DTLTO.html. | ||
|
||
Currently, DTLTO is only supported in ELF LLD. Support will be added to other | ||
LLD flavours in the future. | ||
|
||
ELF LLD | ||
------- | ||
|
||
The command-line interface is as follows: | ||
|
||
- ``--thinlto-distributor=<path>`` | ||
Specifies the file to execute as the distributor process. If specified, | ||
ThinLTO backend compilations will be distributed. | ||
|
||
- ``--thinlto-remote-compiler=<path>`` | ||
Specifies the path to the compiler that the distributor process will use for | ||
backend compilations. The compiler invoked must match the version of LLD. | ||
|
||
- ``--thinlto-distributor-arg=<arg>`` | ||
Specifies ``<arg>`` on the command line when invoking the distributor. | ||
Can be specified multiple times. | ||
|
||
- ``--thinlto-remote-compiler-arg=<arg>`` | ||
Appends ``<arg>`` to the remote compiler's command line. | ||
Can be specified multiple times. | ||
|
||
Options that introduce extra input/output files may cause miscompilation if | ||
the distribution system does not automatically handle pushing/fetching them to | ||
remote nodes. In such cases, configure the distributor - possibly using | ||
``--thinlto-distributor-arg=`` - to manage these dependencies. See the | ||
distributor documentation for details. | ||
|
||
Some LLD LTO options (e.g., ``--lto-sample-profile=<file>``) are supported. | ||
Currently, other options are silently accepted but do not have the intended | ||
effect. Support for such options will be expanded in the future. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -147,3 +147,4 @@ document soon. | |
ELF/start-stop-gc | ||
ELF/warn_backrefs | ||
MachO/index | ||
DTLTO |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# REQUIRES: x86 | ||
|
||
## Check that DTLTO options are a no-op if no thinLTO is performed. | ||
|
||
RUN: rm -rf %t && split-file %s %t && cd %t | ||
|
||
RUN: opt t1.ll -o t1.o | ||
RUN: opt t2.ll -o t2.o | ||
|
||
## Common command-line arguments. Note that mock.py does not do any compilation; | ||
## instead, it simply writes the contents of the object files supplied on the | ||
## command line into the output object files in job order. | ||
RUN: echo "t1.o t2.o \ | ||
RUN: --thinlto-distributor=%python \ | ||
RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/mock.py \ | ||
RUN: --thinlto-distributor-arg=no-exist1.o \ | ||
RUN: --thinlto-distributor-arg=no-exist2.o" > l.rsp | ||
|
||
## Check linking succeeds when all input files are Full LTO. | ||
RUN: ld.lld @l.rsp | ||
|
||
RUN: llc -filetype=obj t1.ll -o t1.o | ||
RUN: llc -filetype=obj t2.ll -o t2.o | ||
|
||
## Check linking succeeds when all input files are relocatable files. | ||
RUN: ld.lld @l.rsp | ||
|
||
#--- t1.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @t1() { | ||
ret void | ||
} | ||
|
||
#--- t2.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @t2() { | ||
ret void | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# REQUIRES: x86 | ||
|
||
## Check that DTLTO creates imports lists if requested. | ||
|
||
RUN: rm -rf %t && split-file %s %t && cd %t | ||
|
||
RUN: opt -thinlto-bc t1.ll -o t1.bc | ||
RUN: opt -thinlto-bc t2.ll -o t2.bc | ||
|
||
## Generate object files for mock.py to return. | ||
RUN: llc t1.ll --filetype=obj -o t1.o | ||
RUN: llc t2.ll --filetype=obj -o t2.o | ||
|
||
## Common command-line arguments. Note that mock.py does not do any compilation; | ||
## instead, it simply writes the contents of the object files supplied on the | ||
## command line into the output object files in job order. | ||
RUN: echo "t1.bc t2.bc \ | ||
RUN: --thinlto-distributor=%python \ | ||
RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/mock.py \ | ||
RUN: --thinlto-distributor-arg=t1.o \ | ||
RUN: --thinlto-distributor-arg=t2.o" > l.rsp | ||
|
||
## Check that imports files are not created normally. | ||
RUN: ld.lld @l.rsp | ||
RUN: ls | FileCheck %s --check-prefix=NOIMPORTSFILES | ||
NOIMPORTSFILES-NOT: .imports | ||
|
||
## Check that imports files are created with --thinlto-emit-imports-files. | ||
RUN: ld.lld @l.rsp --thinlto-emit-imports-files | ||
RUN: ls | sort | FileCheck %s --check-prefix=IMPORTSFILES | ||
IMPORTSFILES: {{^}}t1.bc.imports{{$}} | ||
IMPORTSFILES: {{^}}t2.bc.imports{{$}} | ||
|
||
#--- t1.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @t1() { | ||
ret void | ||
} | ||
|
||
#--- t2.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
declare void @t1(...) | ||
|
||
define void @t2() { | ||
call void (...) @t1() | ||
ret void | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# REQUIRES: x86 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is quite similar to imports.test and can be merged into it. empty.test can be removed if it does not add additional coverage. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have pushed a commit to combine the coverage in |
||
|
||
## Check that DTLTO creates individual summary index files if requested. | ||
|
||
RUN: rm -rf %t && split-file %s %t && cd %t | ||
|
||
## Generate ThinLTO bitcode files. | ||
RUN: opt -thinlto-bc t1.ll -o t1.bc | ||
RUN: opt -thinlto-bc t1.ll -o t2.bc | ||
|
||
## Generate object files for mock.py to return. | ||
RUN: llc t1.ll --filetype=obj -o t1.o | ||
|
||
## Use a response file for the common command-line arguments. | ||
## Note that mock.py does not perform any compilation; instead, it copies the | ||
## contents of the specified object files into the output object files, in the | ||
## order the jobs are received. | ||
## The "--start-lib/--end-lib" options are used to exercise the special case | ||
## where unused lazy object inputs result in empty index files. | ||
RUN: echo "t1.bc --start-lib t2.bc --end-lib \ | ||
RUN: --thinlto-distributor=%python \ | ||
RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/mock.py \ | ||
RUN: --thinlto-distributor-arg=t1.o \ | ||
RUN: --thinlto-distributor-arg=t2.o" > l.rsp | ||
|
||
## Check that index files are not created normally. | ||
RUN: ld.lld @l.rsp | ||
RUN: ls | FileCheck %s --check-prefix=NOINDEXFILES | ||
NOINDEXFILES-NOT: .thinlto.bc | ||
|
||
## Check that index files are created with --thinlto-emit-index-files. | ||
RUN: ld.lld @l.rsp --thinlto-emit-index-files | ||
RUN: ls | sort | FileCheck %s --check-prefix=INDEXFILES | ||
INDEXFILES: {{^}}t1.bc.thinlto.bc{{$}} | ||
INDEXFILES: {{^}}t2.bc.thinlto.bc{{$}} | ||
|
||
#--- t1.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @t1() { | ||
ret void | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# REQUIRES: x86 | ||
|
||
## Test that DTLTO options are passed correctly to the distributor and | ||
## remote compiler. | ||
|
||
RUN: rm -rf %t && split-file %s %t && cd %t | ||
|
||
RUN: opt -thinlto-bc foo.ll -o foo.o | ||
|
||
## Note: validate.py does not perform any compilation. Instead, it validates the | ||
## received JSON, pretty-prints the JSON and the supplied arguments, and then | ||
## exits with an error. This allows FileCheck directives to verify the | ||
## distributor inputs. | ||
RUN: not ld.lld foo.o \ | ||
RUN: -o my.elf \ | ||
RUN: --thinlto-distributor=%python \ | ||
RUN: --thinlto-distributor-arg=%llvm_src_root/utils/dtlto/validate.py \ | ||
RUN: --thinlto-distributor-arg=darg1=10 \ | ||
RUN: --thinlto-distributor-arg=darg2=20 \ | ||
RUN: --thinlto-remote-compiler=my_clang.exe \ | ||
RUN: --thinlto-remote-compiler-arg=carg1=20 \ | ||
RUN: --thinlto-remote-compiler-arg=carg2=30 2>&1 | FileCheck %s | ||
|
||
CHECK: distributor_args=['darg1=10', 'darg2=20'] | ||
|
||
CHECK: "linker_output": "my.elf" | ||
|
||
CHECK: "my_clang.exe" | ||
CHECK: "carg1=20" | ||
CHECK: "carg2=30" | ||
|
||
CHECK: error: DTLTO backend compilation: cannot open native object file: | ||
|
||
#--- foo.ll | ||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
define void @foo() { | ||
ret void | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unneeded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a commit to remove this. Thanks.