Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7944 Discussions

ICC 19.0.3.199 generates wrong debug info

helloqirun
Beginner
452 Views

The value of "l_1081" should be 7. However, with "-O3", the debugger outputs a wrong value of 2815.

= ICC and gdb versions =

$ ~/intel/bin/icc -v
icc version 19.0.3.199 (gcc version 7.3.0 compatibility)

$ ~/intel/bin/gdb-ia -v
GNU gdb (GDB) 8.0.1.19.ac119e063b+77c0a7e7d9+d6612c60e0+f9aa08edde

= Files to reproduce =

$ cat abc.c
 

int a, d;
int b[1];
short c;
char e, f;
char *g;
void h() {
  short l_1081 = 7;
  optimize_me_not();
  for (; 0;) {
    int i[] = {6};
    for (;;)
      for (;;) {
        int j[][1] = {
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j, j,
            j, j, j, j, j, j, j, j, j, j, j, j, j, j, 0, b};
        int k[][1] = {k, k, k, k, k, k, k, k, k, k, k, k, k,  k,       k, k,
                      k, k, k, k, k, k, k, k, k, k, k, k, k,  k,       k, k,
                      k, k, k, k, k, k, k, k, k, k, k, k, k,  k,       k, k,
                      k, k, k, k, k, k, k, k, k, k, k, k, k,  k,       k, k,
                      k, k, k, k, k, k, k, k, k, k, k, k, k,  k,       k, k,
                      k, k, k, k, k, k, k, k, k, k, k, k, &c, &l_1081, 1};
        int l[][1][3] = {{i, a}, {i, a}, {i, a}, {i, a}, {i, a}, {i, a}, 7,
                         i,      a,      {i, a}, {i, a}, {i, a}, {i, a}, {i, a},
                         {i, a}, {i, a}, 7,      i,      a,      {i, a}, {i, a},
                         {i, a}, {i, a}, {i, a}, {i, a}, {i, a}, 7,      i,
                         a,      i,      a,      i};
        int m = l;
        short n[] = {0};
        char *o = (*o = e = (g[2] = o) && f & n >= d ^ 1) | 1;
      }
  }
}
int main() { h(); }

 

$ cat cmds
b 8
r
p l_1081
kill
q

$ cat outer.c
optimize_me_not() {}

 

# Expected output#

$ ~/intel/bin/icc abc.c outer.c -g

$ ~/intel/bin/gdb-ia -x cmds -batch a.out
Breakpoint 1 at 0x400624: file abc.c, line 8.

Breakpoint 1, h () at abc.c:8
8         optimize_me_not();
$1 = 7

 

#Wrong output at -O3#

$ ~/intel/bin/icc abc.c outer.c -g -O3

$ ~/intel/bin/gdb-ia -x cmds -batch a.out
Breakpoint 1 at 0x400b10: file abc.c, line 8.

Breakpoint 1, h () at abc.c:8
8         optimize_me_not();
$1 = 2815

 

 

 

 

 

0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
452 Views

What may be happening is your for(;0;) excludes the loop from being generated, and in doing so, eliminates the only use of l_1081, and in doing so, permits the compiler to eliminate the variable l_1081 from generating the data storages (but not eliminating the symbol from the debug symbol table).

At the end of h, place

int64_t lookie = __rdtsc() + l_1081;
cout << lookie << endl;

Then place your break point on the _rdtsc line and examine l_1081;

Jim Dempsey

0 Kudos
helloqirun
Beginner
452 Views

Hi Jim,

Thank you for your reply. Isn't it an issue with icc since it shows that the optimizer does not preserve the debug info?

The expected behavior is to show the variable "l_1081" has been optimized out or prints the correct value. Printing a wrong value for this well-formed program will potentially confuse end-users.

Moreover, gcc can correctly optimize out the variable (by removing it from the symbol table) and clang prints the correct value of 7.

 

 

 

jimdempseyatthecove wrote:

What may be happening is your for(;0;) excludes the loop from being generated, and in doing so, eliminates the only use of l_1081, and in doing so, permits the compiler to eliminate the variable l_1081 from generating the data storages (but not eliminating the symbol from the debug symbol table).

At the end of h, place

int64_t lookie = __rdtsc() + l_1081;
cout << lookie << endl;

Then place your break point on the _rdtsc line and examine l_1081;

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
452 Views

>>optimizer does not preserve the debug info?

It is your choice as to if to keep the debug info or not.

Debug build defaults to keep debug symbols (although you can say via option to not).
Release (optimized) build defaults to not keep debug symbols (although you can say via option to keep).

Do you not use VTune? When you use VTune (on Release build) you must select the compiler (and linker) option to keep the Debug symbols. Not doing so results in, nearly useless reports.

>>Moreover, gcc can correctly optimize out the variable (by removing it from the symbol table) and clang prints the correct value of 7.

Not quite

gcc apparently a) optimized out the data storage space for the symbol .AND. b) removed the symbol from the Debug database.

Your initial complaint was the Debugger displayed an incorrect value for, essentially, an undefined variable. While you can argue that the compiler ought to have removed the symbol as well, this is not materially important to the correctness of the (execution of the) code.

The fact that fact that Clang didn't optimize out the code, including the symbol, as well as optimizing out the function call h() in main is immaterial.

Jim Dempsey

0 Kudos
jimdempseyatthecove
Honored Contributor III
452 Views

BTW the lookie "fix" is likely not sufficient to thwart the storage of I_1081 from being optimized out. The compiler optimization may realize that l_1018 is only defined and initialize once to a constant, then used once in the lookie= statement. Realizing this it may substituted the constant value 7 for the (removed) variable l_1081 (and still keep the Debug symbol just to confuse you). Also, for something a little less trivial, a variable can exist in two places: a) the named storage, and b) in a register. Your code may have two paths, one of which uses the memory storage and the other that uses the register copy. Depending on the debugger and compiler, and possibly other factors, the debugger might not be able to know if the "current" value of the variable is in register or in the memory storage. This is something you will have to learn when you debug optimized code.

In debugging optimized code, you have to be mindful that what you see in the source code, is not necessarily what you observe while stepping through the code with the debugger.

Jim Dempsey

0 Kudos
Reply