> The flip side of this technique is to be careful about blowing up the size of the final executable since everything gets included.
Yeah, the 1970s linker model is very silly like this. The good news is that link-time optimization will handle this for you nowadays without any special per-symbol mark-up. As an experiment, put an unused 'deadfunc' function definition in a file called ltotest.c and then compare
gcc -O2 ltotest.c -o ltotest && (objdump -D ltotest | grep deadfunc)
and gcc -O2 -flto ltotest.c -o ltotest && (objdump -D ltotest | grep deadfunc)