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.
Chrome built with safe-icf on Linux and Windows reduced 2Mb binary size after
this change.
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++ -O2 -ffunction-sections -flto=thin -fwhole-program-vtables -fsplit-lto-unit -c a.cpp -o a.o && clang++ -Wl,--icf=safe -fuse-ld=lld -flto=thin a.o 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
Instead of iterating over return and parameter attributes, I suggest you build a new AttributeList that consists of nothing but function attributes. This code might work, but I haven't actually compiled it:
NewF->setAttributes(AttributeList::get(M.getContext(), {AttributeList::FunctionIndex, F.getAttributes().getFnAttributes()}));This has a nice side effect of not leaking lots of temporary AttributeList objects.