Using -qoptdebug to help debug optimized programs
The purpose of the -qoptdebug compiler option is to aid the debugging of optimized programs. It does this by creating pseudocode that maps more closely to the instructions and values of an optimized program than the original source code. When a program compiled with -qoptdebug is loaded into a debugger, you will be debugging the pseudocode rather than your original source. By making optimizations explicit in pseudocode, you can gain a better understanding of how your program is really behaving under optimization. Files containing the pseudocode for your program are generated with file suffix .optdbg. Only line debugging is supported for this feature.
xlc myprogram.c -O3 -qhot -g -qoptdebug
In
this example, your source file is compiled to a.out.
The pseudocode for the optimized program is written to a file called myprogram.optdbg,
which can be referred to when you debug your program.- The -g or the -qlinedebug option must also be specified in order for the compiled executable to be debuggable. However, if neither of these options is specified, the pseudocode file <output_file>.optdbg that contains the optimized pseudocode is still generated.
- The -qoptdebug option takes effect only when one or more of the optimization options -qhot, -qsmp, -qpdf, or -qipa are specified, or when the optimization levels that imply these options are specified; that is, the optimization levels -O3, -O4, and -O5. The example shows the optimization options -qhot and -O3.
Debugging the optimized program
From the following examples, you can see how the compiler might apply optimizations to a simple program and how debugging it can differ from debugging your original source.
Example 1: Represents the original non-optimized code for a simple program. It presents a couple of optimization opportunities to the compiler. For example, the variables z and d are both assigned by the equivalent expressions x + y. Therefore, these two variables can be consolidated in the optimized source. Also, the loop can be unrolled. In the optimized source, you can see iterations of the loop listed explicitly.
Example 2: Represents a listing of the optimized source as shown in the debugger. Note the unrolled loop and the consolidation of values assigned by the x + y expression.
Example 3: Shows an example of stepping through the optimized source using the debugger. Note that there is no longer a correspondence between the line numbers for these statements in the optimized source as compared with the line numbers in the original source.
#include "stdio.h"
void foo(int x, int y, char* w)
{
char* s = w+1;
char* t = w+1;
int z = x + y;
int d = x + y;
int a = printf("TEST\n");
for (int i = 0; i < 4; i++)
printf("%d %d %d %s %s\n", a, z, d, s, t);
}
int main()
{
char d[] = "DEBUG";
foo(3, 4, d);
return 0;
}
(dbx) list
1 3 | void foo(long x, long y, char * w)
2 4 | {
3 9 | a = printf("TEST\n");
4 12 | printf("%d %d %d %s %s\n",a,x + y,x + y,
((char *)w + 1),((char *)w + 1));
5 printf("%d %d %d %s %s\n",a,x + y,x + y,
((char *)w + 1),((char *)w + 1));
6 printf("%d %d %d %s %s\n",a,x + y,x + y,
((char *)w + 1),((char *)w + 1));
7 printf("%d %d %d %s %s\n",a,x + y,x + y,
((char *)w + 1),((char *)w + 1));
8 13 | return;
9 } /* function */
10
11
12 15 | long main()
13 16 | {
14 17 | d$init$0 = "DEBUG";
15 18 | @PARM.x0 = 3;
16 @PARM.y1 = 4;
17 @PARM.w2 = &d;
18 9 | a = printf("TEST\n");
19 12 | printf("%d %d %d %s %s\n",a,@PARM.x0 + @PARM.y1,
@PARM.x0 + @PARM.y1,((char *)@PARM.w2 + 1),
((char *)@PARM.w2 + 1));
20 printf("%d %d %d %s %s\n",a,@PARM.x0 + @PARM.y1,
@PARM.x0 + @PARM.y1,((char *)@PARM.w2 + 1),
((char *)@PARM.w2 + 1));
21 printf("%d %d %d %s %s\n",a,@PARM.x0 + @PARM.y1,
@PARM.x0 + @PARM.y1,((char *)@PARM.w2 + 1),
((char *)@PARM.w2 + 1));
22 printf("%d %d %d %s %s\n",a,@PARM.x0 + @PARM.y1,
@PARM.x0 + @PARM.y1,((char *)@PARM.w2 + 1),
((char *)@PARM.w2 + 1));
23 19 | rstr = 0;
24 return rstr;
25 20 | } /* function */
(dbx) stop at 18
[1] stop at "myprogram.o.optdbg":18
(dbx) run
[1] stopped in main at line 18 in file "myprogram.o.optdbg"
18 9 | a = printf("TEST\n");
(dbx) cont
TEST
5 7 7 EBUG EBUG
5 7 7 EBUG EBUG
5 7 7 EBUG EBUG
5 7 7 EBUG EBUG
execution completed


