Search code examples
c++gccoptimizationcompilationcode-elimination

disable all obvious elimination when compiling with gcc (without changing my source code!)


I want to keep all dead code (or anything that is even obviously can be optimized) when compiling with gcc, but even with -O0, some dead code are still optimized. How can I keep all code without changing my source code? The sample code is as follows, and when compiling with g++ -S -O0 main.cc, the if-statement will be optimized in assembly code (there will be no cmpl and jmp code).

int main() {
  constexpr int a = 123; // or const int a = 0; I do not want to remove `const` or `constexpr` qualifier.
  if (a) // or just if (123)
    return 1;
  return 0;
}

A related question is here: Disable "if(0)" elimination in gcc. But the answers there need you to change your source code (remove const/constexpr qualifier) which I do not want to do.

Could it be that I do not change my source code but only use some compiler flags to achieve this?


Solution

  • This is not possible with GCC to keep the conditional in this case since it is removed during a very early stage of the compilation.

    First of all, here is the compilation steps of GCC:

    1. Code parsing (syntax & semantics) producing an AST in GENERIC representation (HL-IR)
    2. High-level GIMPLE generation (ML-IR)
    3. Low-level GIMPLE generation (ML-IR)
    4. Tree SSA optimization (ML-IR)
    5. RTL generation (LL-IR)
    6. Code optimization
    7. Assembly generation

    The conditional is already removed after the generation of the (theoretically unoptimized) high-level GIMPLE representation. Thus, before any optimization step. One can check this by using the GCC flag -fdump-tree-all and look at the first generated GIMPLE code. Here is the result:

    ;; Function int main() (null)
    ;; enabled by -tree-original
    {
      const int a = 123;
    
      <<cleanup_point   const int a = 123;>>;
      return <retval> = 1;
      return <retval> = 0;
    }
    return <retval> = 0;
    

    One can note that the resulting code is the same with both constexpr and const. Actually, constexpr is treated as a simple const variable in the HL GIMPLE code.

    It is hard to know when the conditional is exactly removed in Step 1 as GENERIC is an implementation-dependent internal representation of GCC. It is not very flexible/customizable. AFAIK, it is not even yet possible to generate the AST/GENERIC representation. You can extract it yourself with some GCC plugins, but this is a quite tricky task.