1

Consider this simple code:

#include <stdio.h>

extern "C"
{
    void p4nenc256v32();
    void p4ndec256v32();
}

void bigFunctionTest()
{
    p4nenc256v32();
    p4ndec256v32();
}

int main()
{
    printf("hello\n");
}

Code size of those p4nenc256v32/p4ndec256v32 functions is significant, roughly 1.5MB. This binary size when compiled with latest VS2022 with optimizations enabled is 1.5MB. If I comment out that unused bigFunctionTest function then resulting binary is smaller by 1.4MB. Any ideas why would this clearly unused function wouldn't be eliminated by compiler and/or linker in release builds? By default, VS2022 in release uses /Gy and /OPT:REF. I also tried mingw64 (gcc 12.2) with -fdata-sections -ffunction-sections -Wl,--gc-sections and results were much worse: when compiled with that dummy function exe grew by 5.2MB. Seem like ms and gcc compilers agree that for some reason these functions cannot be removed.

I created a working sample project that shows the issue: https://github.com/pps83/TestLinker.git (make sure to pull submodules as well) and filled an issue with VS issue tracker: Linker doesn't eliminate correctly dead code, however, I think I might get better explanation from SO users explaining what might be the reason for the problem.

Pavel P
  • 15,789
  • 11
  • 79
  • 128
  • What compiler/linker options did you use? Just saying "release build" does not mean much since each build configuration is configurable. I appreciate that I could look at your project, but requiring external code does not make a good SO question. There is information in your VS issue tracker that you have not included in this question. – Clifford Dec 24 '22 at 15:47
  • 1
    In particular, make sure you compile with [`/Gy`](https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking) and link with [`/OPT:REF`](https://learn.microsoft.com/en-us/cpp/build/reference/opt-optimizations) – Igor Tandetnik Dec 24 '22 at 16:19
  • I do use `/Gy` + `/OPT:REF`, these are defaults for VS2022 release builds. I updated the question. – Pavel P Dec 24 '22 at 17:16
  • I also tried g++ and results were even worse that with VS. – Pavel P Dec 24 '22 at 17:34
  • @PavelP: Is there some reason for the compiler to *assume* that `printf` (which is entirely opaque to the compiler) is *unable* to call `bigFunctionTest`? – Nicol Bolas Dec 24 '22 at 17:40
  • With gcc, `-flto` or `-fwhole-program` would help. – Marc Glisse Dec 24 '22 at 17:53
  • 1
    @NicolBolas I don't think it's about that. `printf` can be removed and result will be the same. E.g. it's not about compiler: this removal has to be done by the linker, as compiler cannot know if there are other files/modules in the program that could reference `bigFunctionTest`. If `bigFunctionTest` was static then compiler would know that the function is unused and would remove it. – Pavel P Dec 24 '22 at 17:54
  • @MarcGlisse yes, only `-flto` works with g++ (`-Wl,--gc-sections` has no effect). `/LTCG` with MS compiler makes it better, but still doesn't really work. – Pavel P Dec 24 '22 at 17:56
  • 3
    @PavelP: I guess my main question is why you think it *should* work. You filed a bug report on this; why do you think that a compiler/linker that doesn't eliminate this code is so deficient as to consider said deficient to be a bug? – Nicol Bolas Dec 24 '22 at 18:44
  • 1
    Is the `extern "C"` necessary? (I.e. if the large functions had C++ language linkage, would the linker optimize them away?) – JaMiT Dec 24 '22 at 20:22
  • @JaMiT I don't know, but that could certainly be the reason. I don't think that the lib in question could be compiled as C++ code though to verify. – Pavel P Dec 26 '22 at 15:15

0 Answers0