Compilers these days tend to do a significant amount of optimizations. Do they also remove unused functions from the final output?

- 30,738
- 21
- 105
- 131

- 30,618
- 31
- 128
- 208
-
Do only the function prototypes get included or the whole function?? – Yunfei Chen Jul 03 '20 at 00:48
-
Related for GCC: https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld – Ciro Santilli OurBigBook.com Jul 17 '23 at 09:06
8 Answers
It depends on the compiler. Visual C++ 9 can do that - unused static
functions are removed at compilation phase (there's even a C4505 warning for that), unused functions with external linkage can be removed at link phase depending on linker settings.

- 6,683
- 4
- 39
- 48

- 167,383
- 100
- 513
- 979
MSVC (the Visual Studio compiler/linker) can do this if you compile with /Gy
and link with /OPT:REF
.
GCC/binutils can do this if you compile with -ffunction-sections -fdata-sections
and link with --gc-sections
.
Don't know about other compilers.

- 74,642
- 33
- 187
- 332
-
Note that `/OPT:REF` leads to nonstandard behaviour: it will optimize out functions of which only the address is taken, so that the address becomes invalid. This does not happen for GCC. – rubenvb Aug 10 '16 at 05:29
As a general rule, the answer is:
Yes: for unused static
functions.
No: for unused globally available functions.
The compiler doesn't know if some other compilation unit references it. Also, most object module types do not allow functions to be removed after compilation and also do not provide a way for the linker to tell if there exist internal references. (The linker can tell if there are external ones.) Some linkers can do it but many things work against this.
Of course, a function in its own module won't be loaded unnecessarily by any linker, unless it is part of a shared library. (Because it might be referenced in the future at runtime, obviously.)

- 143,651
- 25
- 248
- 329
-
I believe modern linkers won't load functions before they are used. At least, `dlopen` with `RTLD_LAZY` implies that it's possible. – Clearer Mar 31 '18 at 06:22
Many compilers do, but it depends on the particular implementation. Debug builds will often include all functions, to allow them to be invoked or examined from within the debugger. Many embedded systems compilers, for reasons I don't totally understand(*), will include all of the functions in an object file if they include any, but will omit entirely any object files that aren't used at all.
Note that in languages which support reflection (e.g., Java, C#, VB.NET, etc.) it's possible, given the name of a function, to create a reference to it at runtime even if no references exist in the code. For example, a routine could accept a string from the console, munge it in some fashion, and generate a call to a function by that name. There wouldn't be any way for a compiler or linker to know what names might be so generated, and thus no way to know what functions may be safely omitted from the code.
No such difficulty exists in C or C++, however, since there is no defined way for code to create a reference to a function, variable, or constant without an explicit reference existing in the code. Some implementations may arrange things so that consecutively-declared constants or variables will be stored consecutively, and one might thus create a reference to a later-declared one by adding an offset to an earlier-declared one, but the behavior of such tricks is explicitly not guaranteed by the C or C++ standards.
(*)I understand that it makes compiling and linking easier, but today's computers should have no trouble running more sophisticated compiling and linking algorithms than would have been practical in decades past. If nothing else, a two-pass pre-compile/pre-link/compile/link method could on the pre-compile/link phase produce a list of things that are used, and then on the "real" compile/link phase omit those that are not.

- 30,738
- 21
- 105
- 131

- 77,689
- 9
- 166
- 211
-
Though I guess some heady inline assembly could call a function that could otherwise be safely omitted from the code? – Andy Jul 06 '17 at 23:27
-
@Andy; Generally, only if it takes the address of the function in question. – supercat Jul 07 '17 at 05:43
-
@Andy: Yes, this is one of multiple reasons it's a bad idea to call functions from GNU C inline asm (which is opaque to the compiler). Or if you do, and declare all the requisite register clobbers (and red-zone), you should probably put `__attribute__((used))` on the target function to make sure a stand-alone definition of it exists even with `-fwhole-program` or `-flto` . Especially if its address hasn't been taken, e.g. as part of an array of function pointers. If the asm calls it by its symbol name, like `call foobar` not indirect, then the linker proper will see a reference to it. – Peter Cordes Sep 03 '22 at 12:08
GCC, if you turn on the optimizations, can remove unused functions and dead code.
More on GCC optimizations can be found here.

- 30,738
- 21
- 105
- 131

- 175
- 4
-
1Which optimization options did you mean, specifically? `-fwhole-program` or `-flto`? At compile-time, without those it can't remove global functions because something in another compilation unit could call them, as in: [For a function that takes a const struct, does the compiler not optimize the function body?](https://stackoverflow.com/a/73544513) – Peter Cordes Sep 03 '22 at 12:43
Quite a lot of the time, yes. It’s often called linker stripping.

- 30,738
- 21
- 105
- 131

- 61,365
- 24
- 124
- 204
When it comes to Microsoft, it's the linker that takes care of this during the link phase and the compiler might warn you about unused static functions (file scope).
If you want the linker to remove unused functions, you use the /OPT:REF option.

- 30,738
- 21
- 105
- 131

- 127,556
- 20
- 111
- 121
Under MSVC and with global functions or variable you can use __declspec( selectany ).
It will remove the function or variable if it has not being referenced in the code if the linker option /OPT:REF (Optimizations) is selected.

- 1,972
- 16
- 25

- 11
- 1