Skip to content

Commit d99ac29

Browse files
committed
All .xdata sections are eligble for ICF
Summary: Many small functions have identical unwind info because they push the same sets of CSRs in the same order and have the same stack and prologue size. The VC linker merges duplicate .xdata, and so should LLD. This reduces the .xdata section size of clang.exe from 1.8MB to 94KB. Reviewers: pcc, ruiu Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D40160 llvm-svn: 318547
1 parent dd01ddb commit d99ac29

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

lld/COFF/ICF.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,23 @@ uint32_t ICF::getHash(SectionChunk *C) {
7373
// 2017) says that /opt:icf folds both functions and read-only data.
7474
// Despite that, the MSVC linker folds only functions. We found
7575
// a few instances of programs that are not safe for data merging.
76-
// Therefore, we merge only functions just like the MSVC tool.
76+
// Therefore, we merge only functions just like the MSVC tool. However, we merge
77+
// identical .xdata sections, because the address of unwind information is
78+
// insignificant to the user program and the Visual C++ linker does this.
7779
bool ICF::isEligible(SectionChunk *C) {
80+
// Non-comdat chunks, dead chunks, and writable chunks are not elegible.
81+
bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
82+
if (!C->isCOMDAT() || !C->isLive() || Writable)
83+
return false;
84+
85+
// Code sections with external symbols are eligible.
7886
bool Global = C->Sym && C->Sym->isExternal();
7987
bool Executable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
80-
bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
81-
return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable;
88+
if (Global && Executable)
89+
return true;
90+
91+
// .xdata unwind info sections are eligble.
92+
return C->getSectionName().split('$').first == ".xdata";
8293
}
8394

8495
// Split an equivalence class into smaller classes.

lld/test/COFF/icf-xdata.s

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj
2+
# RUN: lld-link %t.obj -dll -noentry -out:%t.dll
3+
# RUN: llvm-readobj -sections %t.dll | FileCheck %s
4+
5+
# There shouldn't be much xdata, because all three .pdata entries (12 bytes
6+
# each) should use the same .xdata unwind info.
7+
# CHECK: Name: .pdata
8+
# CHECK-NEXT: VirtualSize: 0x24
9+
# CHECK: Name: .xdata
10+
# CHECK-NEXT: VirtualSize: 0x8
11+
12+
.text
13+
callee:
14+
ret
15+
16+
.def xdata1;
17+
.scl 2;
18+
.type 32;
19+
.endef
20+
.section .text,"xr",one_only,xdata1
21+
.globl xdata1 # -- Begin function xdata1
22+
.p2align 4, 0x90
23+
xdata1: # @xdata1
24+
.seh_proc xdata1
25+
# BB#0: # %entry
26+
subq $40, %rsp
27+
.seh_stackalloc 40
28+
.seh_endprologue
29+
callq callee
30+
nop
31+
addq $40, %rsp
32+
jmp callee # TAILCALL
33+
.seh_handlerdata
34+
.section .text,"xr",one_only,xdata1
35+
.seh_endproc
36+
# -- End function
37+
.def xdata2;
38+
.scl 2;
39+
.type 32;
40+
.endef
41+
.section .text,"xr",one_only,xdata2
42+
.globl xdata2 # -- Begin function xdata2
43+
.p2align 4, 0x90
44+
xdata2: # @xdata2
45+
.seh_proc xdata2
46+
# BB#0: # %entry
47+
subq $40, %rsp
48+
.seh_stackalloc 40
49+
.seh_endprologue
50+
callq callee
51+
callq callee
52+
nop
53+
addq $40, %rsp
54+
jmp callee # TAILCALL
55+
.seh_handlerdata
56+
.section .text,"xr",one_only,xdata2
57+
.seh_endproc
58+
# -- End function
59+
.def xdata3;
60+
.scl 2;
61+
.type 32;
62+
.endef
63+
.section .text,"xr",one_only,xdata3
64+
.globl xdata3 # -- Begin function xdata3
65+
.p2align 4, 0x90
66+
xdata3: # @xdata3
67+
.seh_proc xdata3
68+
# BB#0: # %entry
69+
subq $40, %rsp
70+
.seh_stackalloc 40
71+
.seh_endprologue
72+
callq callee
73+
callq callee
74+
callq callee
75+
nop
76+
addq $40, %rsp
77+
jmp callee # TAILCALL
78+
.seh_handlerdata
79+
.section .text,"xr",one_only,xdata3
80+
.seh_endproc
81+
# -- End function
82+
.section .drectve,"yn"
83+
.ascii " -export:xdata1"
84+
.ascii " -export:xdata2"
85+
.ascii " -export:xdata3"
86+

0 commit comments

Comments
 (0)