ELF: Implement ICF.
authorRui Ueyama <ruiu@google.com>
Thu, 25 Feb 2016 18:43:51 +0000 (18:43 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 25 Feb 2016 18:43:51 +0000 (18:43 +0000)
commit0b28952993ae0f0d17153b4059900c60013ecb63
tree3d0cb615d417a33251b1e5343cf4e6a6e9c22373
parent2c6c01a4fc9344aeef6a60c63bd26019ac6e176e
ELF: Implement ICF.

This patch implements the same algorithm as LLD/COFF's ICF. I'm
not going to repeat the same description about how it works, so you
want to read the comment in ICF.cpp in this patch if you want to know
the details. This algorithm should be more powerful than the ICF
algorithm implemented in GNU gold. It can even merge mutually-recursive
functions (which is harder than one might think).

ICF is a fairly effective size optimization. Here are some examples.

 LLD:   37.14 MB -> 35.80 MB (-3.6%)
 Clang: 59.41 MB -> 57.80 MB (-2.7%)

The lacking feature is "safe" version of ICF. This merges all
identical sections. That is not compatible with a C/C++ language
requirement that two distinct functions must have distinct addresses.

But as long as your program do not rely on the pointer equality
(which is in many cases true), your program should work with the
feature. LLD works fine for example.

GNU gold implements so-called "safe ICF" that identifies functions
that are safe to merge by heuristics -- for example, gold thinks
that constructors are safe to merge because there is no way to
take an address of a constructor in C++. We have a different idea
which David Majnemer suggested that we add NOPs at beginning of
merged functions so that two or more pointers can have distinct
values. We can do whichever we want, but this patch does not
include neither.

http://reviews.llvm.org/D17529

llvm-svn: 261912
20 files changed:
lld/ELF/CMakeLists.txt
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/ICF.cpp [new file with mode: 0644]
lld/ELF/ICF.h [new file with mode: 0644]
lld/ELF/InputFiles.cpp
lld/ELF/InputSection.cpp
lld/ELF/InputSection.h
lld/ELF/Options.td
lld/ELF/OutputSections.cpp
lld/ELF/Symbols.cpp
lld/ELF/Symbols.h
lld/test/ELF/Inputs/icf2.s [new file with mode: 0644]
lld/test/ELF/icf1.s [new file with mode: 0644]
lld/test/ELF/icf2.s [new file with mode: 0644]
lld/test/ELF/icf3.s [new file with mode: 0644]
lld/test/ELF/icf4.s [new file with mode: 0644]
lld/test/ELF/icf5.s [new file with mode: 0644]
lld/test/ELF/icf6.s [new file with mode: 0644]
lld/test/ELF/icf7.s [new file with mode: 0644]