[lld] r318547 - All .xdata sections are eligble for ICF

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 17 11:50:10 PST 2017


Author: rnk
Date: Fri Nov 17 11:50:10 2017
New Revision: 318547

URL: http://llvm.org/viewvc/llvm-project?rev=318547&view=rev
Log:
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

Added:
    lld/trunk/test/COFF/icf-xdata.s
Modified:
    lld/trunk/COFF/ICF.cpp

Modified: lld/trunk/COFF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=318547&r1=318546&r2=318547&view=diff
==============================================================================
--- lld/trunk/COFF/ICF.cpp (original)
+++ lld/trunk/COFF/ICF.cpp Fri Nov 17 11:50:10 2017
@@ -73,12 +73,23 @@ uint32_t ICF::getHash(SectionChunk *C) {
 // 2017) says that /opt:icf folds both functions and read-only data.
 // Despite that, the MSVC linker folds only functions. We found
 // a few instances of programs that are not safe for data merging.
-// Therefore, we merge only functions just like the MSVC tool.
+// Therefore, we merge only functions just like the MSVC tool. However, we merge
+// identical .xdata sections, because the address of unwind information is
+// insignificant to the user program and the Visual C++ linker does this.
 bool ICF::isEligible(SectionChunk *C) {
+  // Non-comdat chunks, dead chunks, and writable chunks are not elegible.
+  bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
+  if (!C->isCOMDAT() || !C->isLive() || Writable)
+    return false;
+
+  // Code sections with external symbols are eligible.
   bool Global = C->Sym && C->Sym->isExternal();
   bool Executable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
-  bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
-  return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable;
+  if (Global && Executable)
+    return true;
+
+  // .xdata unwind info sections are eligble.
+  return C->getSectionName().split('$').first == ".xdata";
 }
 
 // Split an equivalence class into smaller classes.

Added: lld/trunk/test/COFF/icf-xdata.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/icf-xdata.s?rev=318547&view=auto
==============================================================================
--- lld/trunk/test/COFF/icf-xdata.s (added)
+++ lld/trunk/test/COFF/icf-xdata.s Fri Nov 17 11:50:10 2017
@@ -0,0 +1,86 @@
+# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj
+# RUN: lld-link %t.obj -dll -noentry -out:%t.dll
+# RUN: llvm-readobj -sections %t.dll | FileCheck %s
+
+# There shouldn't be much xdata, because all three .pdata entries (12 bytes
+# each) should use the same .xdata unwind info.
+# CHECK:         Name: .pdata
+# CHECK-NEXT:    VirtualSize: 0x24
+# CHECK:         Name: .xdata
+# CHECK-NEXT:    VirtualSize: 0x8
+
+	.text
+callee:
+	ret
+
+	.def	 xdata1;
+	.scl	2;
+	.type	32;
+	.endef
+	.section	.text,"xr",one_only,xdata1
+	.globl	xdata1                  # -- Begin function xdata1
+	.p2align	4, 0x90
+xdata1:                                 # @xdata1
+.seh_proc xdata1
+# BB#0:                                 # %entry
+	subq	$40, %rsp
+	.seh_stackalloc 40
+	.seh_endprologue
+	callq	callee
+	nop
+	addq	$40, %rsp
+	jmp	callee                  # TAILCALL
+	.seh_handlerdata
+	.section	.text,"xr",one_only,xdata1
+	.seh_endproc
+                                        # -- End function
+	.def	 xdata2;
+	.scl	2;
+	.type	32;
+	.endef
+	.section	.text,"xr",one_only,xdata2
+	.globl	xdata2                  # -- Begin function xdata2
+	.p2align	4, 0x90
+xdata2:                                 # @xdata2
+.seh_proc xdata2
+# BB#0:                                 # %entry
+	subq	$40, %rsp
+	.seh_stackalloc 40
+	.seh_endprologue
+	callq	callee
+	callq	callee
+	nop
+	addq	$40, %rsp
+	jmp	callee                  # TAILCALL
+	.seh_handlerdata
+	.section	.text,"xr",one_only,xdata2
+	.seh_endproc
+                                        # -- End function
+	.def	 xdata3;
+	.scl	2;
+	.type	32;
+	.endef
+	.section	.text,"xr",one_only,xdata3
+	.globl	xdata3                  # -- Begin function xdata3
+	.p2align	4, 0x90
+xdata3:                                 # @xdata3
+.seh_proc xdata3
+# BB#0:                                 # %entry
+	subq	$40, %rsp
+	.seh_stackalloc 40
+	.seh_endprologue
+	callq	callee
+	callq	callee
+	callq	callee
+	nop
+	addq	$40, %rsp
+	jmp	callee                  # TAILCALL
+	.seh_handlerdata
+	.section	.text,"xr",one_only,xdata3
+	.seh_endproc
+                                        # -- End function
+	.section	.drectve,"yn"
+	.ascii	" -export:xdata1"
+	.ascii	" -export:xdata2"
+	.ascii	" -export:xdata3"
+




More information about the llvm-commits mailing list