A compiler option that helps debug optimized code

Enhancements for IBM XL C/C++ and XL Fortran

Debugging optimized code has always been a challenging task, because it could make the program state not available to debuggers. 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. In this article, Daniel Chen and Tommy Hoffner introduce a compiler option that helps debug optimized code.

Share:

Daniel Chen (cdchen@ca.ibm.com), Software Developer, IBM

Author1 photoDaniel Chen is a Fortran compiler front-end developer at IBM in Canada.



Tommy Hoffner (thoffner@ca.ibm.com), Software Developer, IBM

Author1 photoTommy Hoffner is a C/C++ and Fortran compiler back-end developer at IBM in Canada.



10 July 2012

Also available in Chinese Russian

The challenge of debugging optimized code

Debugging optimized code has always been a challenging task because it could make the program state not available to debuggers. 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, if a variable is used only in computing another expression, the compiler can chose to generate the value of the final expression directly, without explicitly generating the variable value at any point. This can inhibit debug usability because a variable that a programmer is expecting to see is no longer available in the optimized program.


Current debug support in IBM XL C/C++ and XL Fortran

IBM® XL C/C++ and XL Fortran provide a set of mechanisms for debug support:

  • Compiler option –g generates debug information for use by a symbolic debugger. Although it provides full debug support at no-opt, it doesn't really work well with the optimized code. As we described in the previous section, the program state is not captured due to optimization.
  • Compiler option –qkeepparm targets the procedure parameters in particular. It ensures that the initial values of procedure parameters are available to the debugger even during optimization. This has a small impact on execution performance. The -qkeepparm option then provides access to the values of incoming parameters to debuggers by simply preserving those values on the stack
  • Compiler option -qoptdebug creates a modified source code that matches the optimized code after some high-level transformations have been done. This pseudo code maps more closely to the instructions and values of an optimized program than the original source code. When a program compiled with this option is loaded into a debugger, you will be debugging the pseudo code rather than your original source code.

Enhancements for debugging optimized code

Debug option –g is enhanced to control the debugging support and to make debugging optimized code easier, specifically with –O2. When the –O2 optimization level is in effect the debug capability is completely supported. When an optimization level is higher than –O2 is in effect the debug capability is limited. The debug option –g has levels that range from 0 to 9.

  • -g0: No debug information is generated. No program state is preserved (best performance).
  • -g1: Generates debug information about line numbers and source file names. No program state is preserved.
  • -g2: Generates debug information about types, line numbers, source file names and view-only debug information about variables. No program state is guaranteed when the code is optimized.
  • -g3, -g4: Same behavior as –g2 plus procedure parameter values are available to the debugger at the beginning of each procedure.
  • -g5, -g6, -g7: Same behavior as –g3 and –g4 plus program state is available to the debugger at the following selected language constructs at –O2.
    • Before and after loops
    • Before and after conditional branching statements
    • Before and after function calls as well as the first executable statement of a function.
  • -g8: Same behavior as –g3 and –g4 plus program state is available to the debugger at beginning of every executable statement at –O2.
  • -g9: Same behavior as –g8 plus users can modify a variable in the debugger at –O2. Being able to modify a variable in the debugger is also the default behavior of debugging no-opt code (best debug support).

The debug support for optimized code is enhanced at –g5 and above, where the program state is made available at –O2. For example, when debugging the following test case at –g8:

	T1 = X * Y - 1;
	T2 = X * Y * 3;
	Q = T1 + T2;

At –O2 without the debug support, the compiler might generate the following code, where GRX and GRY are registers:

	GRX = X * Y;
	GRY = GRX << 2;
	Q = GRY – 1;

Because the program never calculates the value of T1 and T2, the debugger might not display the correct values of T1 and T2.

At –O2 –g8, the compiler generates code like this:

	GRX = X * Y;
	GRY = GRX << 2;
	T1 = GRY – 1;
	T2 – GRY – GRX;
	Q = GRY – 1;

The program stores the current values of T1 and T2 back to the memory so they are available to the debugger.


Debugging an inlined function

Function inlining is one of the common optimization techniques. It also causes much trouble for debugging such a function. The debugger does not even recognize that it is an inlined function, because only the line number entries are generated. Formal parameters and local variables of the inlined function might not be available to the debuggers after the inlining.

As an improvement of debugging support, the compiler makes the inlined function scope explicit so that users can step through the function body. Users can also examine the formal parameters and the local variables of the inlined function. However, currently, users are not able to "stop in function" and get debuggers to find any inlined instances for the inlined functions.


Performance consideration

Even though the enhancement of the debug ability negatively impacts the performance (because preserving the program state eliminates some optimization opportunities), the compilers still generate optimized code at –O2 that is fully debuggable. As we measured at –g8 –O2, we can get in average 80% of the –O2 execution time at a 14% increase of the compile time. Of course, the degradation of the execution and the compile time are heavily dependent on the applications.

To limit the performance impact, you can also try with different –g levels. For example, because loops are where optimization techniques are heavily applied, –g5 is designed to preserve only the program state before and after computational loops so that the debug information does not interfere with the optimization algorithms applied to the loop body.


Summary

The support of debugging optimized code has been improved. It now allows you to scale between debug ability and the performance. Currently, only optimization done at level –O2 is with full debug support. We are continuing work on the improvement of debug support for the optimization done for higher optimization levels.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=823988
ArticleTitle=A compiler option that helps debug optimized code
publish-date=07102012