Debugging optimized programs presents special usability problems.
Optimization can change the sequence of operations, add or remove code, change
variable data locations, and perform other transformations that make it difficult
to associate the generated code with the original source statements.
For example:
- Data location issues
- With an optimized program, it is not always certain where the most current
value for a variable is located. For example, a value in memory may not be
current if the most current value is being stored in a register. Most debuggers
are incapable of following the removal of stores to a variable, and to the
debugger it appears as though that variable is never updated, or possibly
even set. This contrasts with no optimization where all values are flushed
back to memory and debugging can be more effective and usable.
- Instruction scheduling issues
- With an optimized program, the compiler may reorder instructions. That
is, instructions may not be executed in the order the programmer would expect
based on the sequence of lines in their original source code. Also, the sequence
of instructions may not be contiguous. As the user steps through their program
with a debugger, it may appear as if they are returning to a previously executed
line in their code (interleaving of instructions).
- Consolidating variable values
- Optimizations can result in the removal and consolidation of variables.
For example, if a program has two expressions that assign the same value to
two different variables, the compiler may substitute a single variable. This
can inhibit debug usability because a variable that a programmer is expecting
to see is no longer available in the optimized program.
There are a couple of different approaches you can take to improve debug
capabilities while also optimizing your program:
- Debug non-optimized code first
- Debug a non-optimized version of your program first, then recompile it
with your desired optimization options. See Debugging before optimization for
some compiler options that are useful in this approach.
- Use -qoptdebug
- When compiling with -O3 optimization or higher,
use the compiler option -qoptdebug to generate a
pseudocode file that more accurately maps to how instructions and variable
values will operate in an optimized program. With this option, when you load
your program into a debugger, you will be debugging the pseudocode for the
optimized program. See Using -qoptdebug to help debug optimized programs for
more information.