
`IRMover` links in referenced private global values unconditionally, see `IRLinker::shouldLink()`. If they are part of a non-prevailing comdat, this leads to duplication of the values. Full and Thin LTO avoid duplication by changing the linkage of members of non-prevailing comdat groups to `available_externally`, which was implemented in https://reviews.llvm.org/D34803 and https://reviews.llvm.org/D135427. This patch does the same for `Linker`, but limits the effect only to private members without aliases to minimize interference. Motivation example: ``` > cat foo.h inline int foo(int a) { return a + 1; } > cat bar.cpp #include "foo.h" int bar(int a) { return foo(a + 1); } > cat main.cpp #include "foo.h" int bar(int a); int main(int argc, const char* argv[]) { return bar(argc) + foo(argc); } > clang++ -c -flto -fprofile-instr-generate main.cpp -o main.o > clang++ -c -flto -fprofile-instr-generate bar.cpp -o bar.o > clang++ -fuse-ld=lld -fprofile-instr-generate main.o bar.o -o test1 > ./test1 > llvm-profdata merge --text default.profraw -o - _Z3fooi # Counter Values: 2 > llvm-link main.o bar.o -o combined.o > clang++ -fuse-ld=lld -fprofile-instr-generate combined.o -o test2 > ./test2 > llvm-profdata merge --text default.profraw -o - _Z3fooi # Counter Values: 4 ```
55 lines
1.6 KiB
LLVM
55 lines
1.6 KiB
LLVM
; RUN: rm -rf %t && split-file %s %t
|
|
; RUN: llvm-link -S %t/1.ll %t/1-aux.ll -o - | FileCheck %s
|
|
; RUN: llvm-link -S %t/2.ll %t/2-aux.ll -o - | FileCheck %s --check-prefix=CHECK2
|
|
|
|
;--- 1.ll
|
|
$c = comdat any
|
|
|
|
@v = global i32 0, comdat ($c)
|
|
|
|
; CHECK: @v = global i32 0, comdat($c)
|
|
; CHECK: @v3 = external global i32
|
|
; CHECK: @v2 = external dllexport global i32
|
|
|
|
;--- 1-aux.ll
|
|
$c = comdat any
|
|
|
|
@v2 = weak dllexport global i32 0, comdat ($c)
|
|
define ptr @f2() {
|
|
ret ptr @v2
|
|
}
|
|
|
|
@v3 = weak alias i32, ptr @v2
|
|
define ptr @f3() {
|
|
ret ptr @v3
|
|
}
|
|
|
|
;--- 2.ll
|
|
;; Check that a private global variable from a non-prevailing comdat group is
|
|
;; converted into 'available_externally' and excluded from the comdat group.
|
|
|
|
; CHECK2: $__profc_foo = comdat any
|
|
; CHECK2: @llvm.compiler.used = appending global [2 x ptr] [ptr @__profd_foo.[[SUFFIX:[0-9]+]], ptr @__profd_foo]
|
|
; CHECK2: @__profd_foo.[[SUFFIX]] = private global ptr @__profc_foo, comdat($__profc_foo)
|
|
; CHECK2: @__profc_foo = linkonce_odr global i64 1, comdat
|
|
; CHECK2: @__profd_foo = available_externally dso_local global ptr @__profc_foo{{$}}
|
|
|
|
$__profc_foo = comdat any
|
|
@__profc_foo = linkonce_odr global i64 1, comdat
|
|
@__profd_foo = private global ptr @__profc_foo, comdat($__profc_foo)
|
|
@llvm.compiler.used = appending global [1 x ptr] [ ptr @__profd_foo ]
|
|
|
|
define ptr @bar() {
|
|
ret ptr @__profc_foo
|
|
}
|
|
|
|
;--- 2-aux.ll
|
|
$__profc_foo = comdat any
|
|
@__profc_foo = linkonce_odr global i64 1, comdat
|
|
@__profd_foo = private global ptr @__profc_foo, comdat($__profc_foo)
|
|
@llvm.compiler.used = appending global [1 x ptr] [ ptr @__profd_foo ]
|
|
|
|
define ptr @baz() {
|
|
ret ptr @__profc_foo
|
|
}
|