Does compiling with -g, in itself, degrade performance?

I do not think there is any performance difference. Indeed the generated code would be the same and -g is usable with -O according to the documentation here. Besides, debugging symbols aren't written into the code but into another section called "debug section" which isn't even loaded at runtime (only by a debugger)

-g will not change what optimizations are run, or code generated. This is gcc policy as stated here

However it might be useful to note that the same documentation states that:

The shortcuts taken by optimized code may occasionally be surprising: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values are already at hand; some statements may execute in different places because they have been moved out of loops. Nevertheless it is possible to debug optimized output. This makes it reasonable to use the optimizer for programs that might have bugs.

So in the end the debugging will never hurt your optimisation but the opposite is false and using -O3 might degrade your debugging information (by deleting useless variables for instance).

Note that it may be better in that case to use -Og (as stated here) since it will:

Optimize debugging experience. -Og enables optimizations that do not interfere with debugging. It should be the optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization while maintaining fast compilation and a good debugging experience.

However this would impact performance because some optimisation passes that would interfere with the debugging would not be done.


Edit:

The links and quotes answer your question for gcc.It might not apply to other compilers such as clang. However I have found some documentation as well for clang. For instance here:

Basically, the debug information allows you to compile a program with “-O0 -g” and get full debug information, allowing you to arbitrarily modify the program as it executes from a debugger. Compiling a program with “-O3 -g” gives you full debug information that is always available and accurate for reading (e.g., you get accurate stack traces despite tail call elimination and inlining), but you might lose the ability to modify the program and call functions where were optimized out of the program, or inlined away completely.


The -g flag adds debugging information to the binary. This exists in a separate section (.stab and .stabstr) of the executable from the .text CPU run bit. When run outside the debugger, the debug section is not loaded by the operating system loader. The debug info can also easily be stripped out using the strip utility to generate binaries that are identical to one compiled without the -g flag.

Normally however when you want to debug stuff you will compiled without optimizations and the NDEBUG preprocessor macro. However these things are not controlled by the -g flag.