Skip to content

Commit e28435c

Browse files
committed
[ThinLTO] Copy UnnamedAddr when spliting module.
The unnamedaddr property of a function is lost when using `-fwhole-program-vtables` and thinlto which causes size increase under linker's safe icf mode. The size increase of chrome on Linux when switching from all icf to safe icf drops from 5 MB to 3 MB after this change, and from 6 MB to 4 MB on Windows. There is a repro: ``` # a.h struct A { virtual int f(); virtual int g(); }; # a.cpp #include "a.h" int A::f() { return 10; } int A::g() { return 10; } # main.cpp #include "a.h" int g(A* a) { return a->f(); } int main(int argv, char** args) { A a; return g(&a); } $ clang++ -O2 -ffunction-sections -flto=thin -fwhole-program-vtables -fsplit-lto-unit -c main.cpp -o main.o && clang++ -Wl,--icf=safe -fuse-ld=lld -flto=thin main.o -o a.out && llvm-readobj -t a.out | grep -A 1 -e _ZN1A1fEv -e _ZN1A1gEv Name: _ZN1A1fEv (480) Value: 0x201830 -- Name: _ZN1A1gEv (490) Value: 0x201840 ``` Differential Revision: https://reviews.llvm.org/D100498
1 parent cc2b62a commit e28435c

File tree

2 files changed

+17
-5
lines changed

2 files changed

+17
-5
lines changed

llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,11 @@ void simplifyExternals(Module &M) {
158158
Function *NewF =
159159
Function::Create(EmptyFT, GlobalValue::ExternalLinkage,
160160
F.getAddressSpace(), "", &M);
161-
NewF->setVisibility(F.getVisibility());
161+
NewF->copyAttributesFrom(&F);
162+
// Only copy function attribtues.
163+
NewF->setAttributes(
164+
AttributeList::get(M.getContext(), AttributeList::FunctionIndex,
165+
F.getAttributes().getFnAttributes()));
162166
NewF->takeName(&F);
163167
F.replaceAllUsesWith(ConstantExpr::getBitCast(NewF, F.getType()));
164168
F.eraseFromParent();

llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
33
; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
44

5-
; M0: @g = external constant [9 x i8*]{{$}}
6-
; M1: @g = constant [9 x i8*]
7-
@g = constant [9 x i8*] [
5+
; M0: @g = external constant [10 x i8*]{{$}}
6+
; M1: @g = constant [10 x i8*]
7+
@g = constant [10 x i8*] [
88
i8* bitcast (i64 (i8*)* @ok1 to i8*),
99
i8* bitcast (i64 (i8*, i64)* @ok2 to i8*),
1010
i8* bitcast (void (i8*)* @wrongtype1 to i8*),
@@ -13,7 +13,8 @@
1313
i8* bitcast (i64 (i8*, i8*)* @wrongtype4 to i8*),
1414
i8* bitcast (i64 (i8*, i128)* @wrongtype5 to i8*),
1515
i8* bitcast (i64 (i8*)* @usesthis to i8*),
16-
i8* bitcast (i8 (i8*)* @reads to i8*)
16+
i8* bitcast (i8 (i8*)* @reads to i8*),
17+
i8* bitcast (i8* (i8*, i8)* @attributedFunc to i8*)
1718
], !type !0
1819

1920
; M0: define i64 @ok1
@@ -76,4 +77,11 @@ define i8 @reads(i8* %this) {
7677
ret i8 %l
7778
}
7879

80+
; Check function attributes are copied over splitted module
81+
; M0: declare dso_local noundef i8* @attributedFunc(i8* noalias, i8 zeroext) unnamed_addr #[[ATTR0:[0-9]+]]
82+
; M1: declare dso_local void @attributedFunc() unnamed_addr #[[ATTR1:[0-9]+]]
83+
declare dso_local noundef i8* @attributedFunc(i8* noalias, i8 zeroext) unnamed_addr alwaysinline willreturn
84+
; M0: attributes #[[ATTR0]] = { alwaysinline willreturn }
85+
; M1: attributes #[[ATTR1]] = { alwaysinline willreturn }
86+
7987
!0 = !{i32 0, !"typeid"}

0 commit comments

Comments
 (0)