Function elimination
Another type of dead code elimination that GCC can do the removal of entire unused symbols (functions or variables) which can be achieved with:
-fdata-sections -ffunction-sections -Wl,--gc-sections
as mentioned at: How to remove unused C/C++ symbols with GCC and ld?
These flags are not enabled in the various GCC -O levels (-O1, -O2, etc) by default.
Also as shown at: Does GCC LTO perform cross-file dead code elimination? if a function would be inlined due to LTO, then it doesn't count towards making a compilation unit get placed in the final output.
Let's try some intra-function DCE
Let's have some fun testing what GCC can do or not. Testing LLM models is boring.
main.c
int main(int argc, char **argv) {
if (0) {
argc += 0x33;
}
return argc;
}
Compile and disassemble:
gcc -O0 main.c
gdb -batch -ex 'disassemble/rs main' a.out
Output:
0x0000000000001129 <+0>: f3 0f 1e fa endbr64
0x000000000000112d <+4>: 55 push %rbp
0x000000000000112e <+5>: 48 89 e5 mov %rsp,%rbp
0x0000000000001131 <+8>: 89 7d fc mov %edi,-0x4(%rbp)
0x0000000000001134 <+11>: 48 89 75 f0 mov %rsi,-0x10(%rbp)
0x0000000000001138 <+15>: 8b 45 fc mov -0x4(%rbp),%eax
0x000000000000113b <+18>: 5d pop %rbp
0x000000000000113c <+19>: c3 ret
Yup, it's gone.
Some others:
Not removed in -O3
, it does not know that argc
has to be positive:
int main(int argc, char **argv) {
if (argc >= 0) {
argc += 0x33;
}
return argc;
}
The 0x44 is removed in -O3
but not -O4
, so it can do if/else arithmetic:
int main(int argc, char **argv) {
if (argc >= 0) {
argc += 0x33;
} else {
if (argc >= 0) {
argc += 0x44;
}
}
return argc;
}
The 0x33 is removed in -O3
so it can do ranges and +
:
int main(int argc, char **argv) {
if (argc < 10000) {
if (argc + 1 > 10000) {
argc += 0x33;
}
}
return argc;
}
0x33 is not removed, it can't reason about sqrt
:
#include <math.h>
int main(int argc, char **argv) {
if (argc < 10000) {
if (sqrt(argc) > 100) {
argc += 0x33;
}
}
return argc;
}