[Bug debug/105389] New: variable displayed as available at -O1 and -O3 but as optimized out at -Og and with an incorrect value at -O2

2022-04-26 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105389

Bug ID: 105389
   Summary: variable displayed as available at -O1 and -O3 but as
optimized out at -Og and with an incorrect value at
-O2
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variable l_43, defined within the scope of
function c, has wrong debug information definition that lead to optimized out
or incorrect value being shown at -Og and -O2 while it has always the correct
value with optimization levels -O1 and -O3.

At -Og the variable is marked as optimized out at line 6 when its value should
be 5 and it becomes available with its correct value only starting from line 9,
where it is assigned to 0 via pointer arithmetics. At -O2 the variable has a
wrong value at line 10 (the only one actually stepped), it should be 0 but the
value available during debugging is 5.

We provide a detailed analysis on x64 with a quick assessment of older gcc
versions.

$ cat a.c
int a ;
char b ;
void  c() {
   int l_43 = 5;
   int *d = &l_43;
e:  b++;
   for (;
   a != -8;
   --a) *d = 0;
   if (b) goto e;
}
int main() {
   c();
}

GCC and GDB version (GCC commit id: 500d3f0a302):
gcc (GCC) 12.0.0 20211227 (experimental)
GNU gdb (GDB) 11.2

GDB trace at -Og:
$ gcc -Og -g a.c -o opt-g
$ gdb -q opt-g
Reading symbols from opt-g...
(gdb) b c
Breakpoint 1 at 0x400486: file a.c, line 3.
(gdb) r
Starting program: /tmp/opt-g 

Breakpoint 1, c () at a.c:3
3   void  c() {
(gdb) info loc
l_43 = 
d = 
(gdb) n
6   e:  b++;
(gdb) info loc
l_43 = 
d = 
(gdb) n
7   for (;
(gdb) info loc
l_43 = 
d = 
(gdb) n
8   a != -8;
(gdb) info loc
l_43 = 
d = 
(gdb) n
9   --a) *d = 0;
(gdb) info loc
l_43 = 0
d = 
(gdb) n
8   a != -8;
(gdb) info loc
l_43 = 
d = 
(gdb) n
9   --a) *d = 0;
(gdb) info loc
l_43 = 0
d = 

GDB trace at -O2:
$ gcc -O2 -g a.c -o opt-2
$ gdb -q opt-2
Reading symbols from opt-2...
(gdb) b c
Breakpoint 1 at 0x4004a0: file a.c, line 10.
(gdb) r
Starting program: /tmp/opt-2 

Breakpoint 1, c () at a.c:10
10  if (b) goto e;
(gdb) info loc
l_43 = 5
d = 
e = 


ASM at -Og:
00400486 :
  400486:   eb 18   jmp4004a0 
  400488:   83 e8 01sub$0x1,%eax
  40048b:   89 05 9f 0b 20 00   mov%eax,0x200b9f(%rip)#
601030 
  400491:   8b 05 99 0b 20 00   mov0x200b99(%rip),%eax#
601030 
  400497:   83 f8 f8cmp$0xfff8,%eax
  40049a:   75 ec   jne400488 
  40049c:   84 d2   test   %dl,%dl
  40049e:   74 12   je 4004b2 
  4004a0:   0f b6 05 85 0b 20 00movzbl 0x200b85(%rip),%eax#
60102c 
  4004a7:   8d 50 01lea0x1(%rax),%edx
  4004aa:   88 15 7c 0b 20 00   mov%dl,0x200b7c(%rip)#
60102c 
  4004b0:   eb df   jmp400491 
  4004b2:   c3  retq

DWARF at -Og:
0x00ae: DW_TAG_variable
  DW_AT_name("l_43")
  DW_AT_decl_file   ("/tmp/a.c")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x0041 "int")
  DW_AT_location(0x000e: 
 [0x00400488, 0x00400491): DW_OP_lit0,
DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)


ASM and DWARF analysis at -Og:
>From DWARF information we can see how there is only a location range defined
for variable l_43 and it has value 0 associated with it.
The range includes the instructions associated with line 9 making the variable
available at line 9, but there is no location defined for the instructions
associated with line 6, thus making the variable marked as optimized out when
its value is 5. 

For instance, at -O1 this information is correctly computed:

ASM at -O1:
00400486 :
  400486:   0f b6 15 9f 0b 20 00movzbl 0x200b9f(%rip),%edx#
60102c 
  40048d:   8b 05 9d 0b 20 00   mov0x200b9d(%rip),%eax#
601030 
  400493:   b9 00 00 00 00  mov$0x0,%ecx
  400498:   be 01 00 00 00  mov$0x1,%esi
  40049d:   83 c2 01add$0x1,%edx
  4004a0:   83 f8 f8cmp$0xfff8,%eax
  4004a3:   74 0a   je 4004af 
  4004a5:   83 e8 01sub$0x1,%eax
  4004a8:   83 f8 f8cmp$0xfff8,%eax
  4004ab:   75 f8   jne4004a5 
  4004ad:   89 f1   mov%esi,%ecx
  4004af:

[Bug debug/105261] schedule-insns2 and ipa-sra make alive constant variables not available

2022-04-13 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105261

--- Comment #1 from Cristian Assaiante  ---
The gdb bug report can be found at:
https://sourceware.org/bugzilla/show_bug.cgi?id=29060

[Bug debug/105261] New: schedule-insns2 and ipa-sra make alive constant variables not available

2022-04-13 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105261

Bug ID: 105261
   Summary: schedule-insns2 and ipa-sra make alive constant
variables not available
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, none of the local variables from function b is
available when stepping on the call to function test() from another module,
despite the function taking them all as arguments. This happens when the
optimization level is -O2/-O3 or -Os/-Oz.

At -O2/-O3, a combination of schedule-insns2 and ipa-sra is behind the
incomplete DWARF information for variables l_5, l_53, l_54, l_55 and l_362
(note that all them are constant), as there is no const value or location
attribute for them. DWARF information for i and j is correctly computed but the
variables are not shown when debugging due to a possible gdb 11.2 bug.

At -Os/-Oz, the issue is caused by ipa-sra alone. By disabling it, all
variables appear in the frame and with their value available. 

Please find below a detailed analysis for -O2 on x64 and a quick assessment on
past gcc versions where the issue is sometimes not present.


$ cat a.c
int a;
static int b()
{
int l_5 = 0,  l_54 = 5,  l_362 = 4,  i, j;
short l_53 = 4,  l_55 = 0;
i = 0;
for (; i < 6; i++)
j = a ;
test(l_5, l_53, l_54, l_55, l_362, i, j);
}
int main ()
{
b();
}

$ cat lib.c
#include 

void test(int l_5, int l_53, int l_54, int l_55, int l_362, int i, int j) {
printf("%d %d %d %d %d %d %d", l_5, l_53, l_54, l_55, l_362, i, j);
}

GCC and GDB version:
- gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -O2 -g a.c lib.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 9
Breakpoint 1 at 0x400410: file a.c, line 9.
(gdb) r
Starting program: /tmp/opt 

Breakpoint 1, main () at a.c:9
9   test(l_5, l_53, l_54, l_55, l_362, i, j);
(gdb) info loc
No locals.

ASM at -O2:
00400410 :
  400410:   48 83 ec 10 sub$0x10,%rsp
  400414:   8b 05 1a 0c 20 00   mov0x200c1a(%rip),%eax#
601034 
  40041a:   31 c9   xor%ecx,%ecx
  40041c:   31 ff   xor%edi,%edi
  40041e:   41 b9 06 00 00 00   mov$0x6,%r9d
  400424:   41 b8 04 00 00 00   mov$0x4,%r8d
  40042a:   ba 05 00 00 00  mov$0x5,%edx
  40042f:   be 04 00 00 00  mov$0x4,%esi
  400434:   50  push   %rax
  400435:   31 c0   xor%eax,%eax
  400437:   e8 04 01 00 00  callq  400540 
  40043c:   31 c0   xor%eax,%eax
  40043e:   48 83 c4 18 add$0x18,%rsp
  400442:   c3  retq


DWARF info at -O2:
0x0093: DW_TAG_variable
  DW_AT_abstract_origin (0x0104 "l_5")

0x0098: DW_TAG_variable
  DW_AT_abstract_origin (0x010e "l_54")

0x009d: DW_TAG_variable
  DW_AT_abstract_origin (0x0119 "l_362")

0x00a2: DW_TAG_variable
  DW_AT_abstract_origin (0x0124 "i")
  DW_AT_location(0x001a: 
 [0x00400410, 0x00400410): DW_OP_lit0,
DW_OP_stack_value
 [0x00400410, 0x00400410): DW_OP_lit1,
DW_OP_stack_value
 [0x00400410, 0x00400410): DW_OP_lit2,
DW_OP_stack_value
 [0x00400410, 0x00400410): DW_OP_lit3,
DW_OP_stack_value
 [0x00400410, 0x00400410): DW_OP_lit4,
DW_OP_stack_value
 [0x00400410, 0x00400410): DW_OP_lit5,
DW_OP_stack_value
 [0x00400410, 0x0040043c): DW_OP_lit6,
DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)

0x00af: DW_TAG_variable
  DW_AT_abstract_origin (0x012c "j")
  DW_AT_location(0x0050: 
 [0x00400410, 0x0040043b): DW_OP_addr
0x601034)
  DW_AT_GNU_locviews(0x004e)

0x00bc: DW_TAG_variable
  DW_AT_abstract_origin (0x0134 "l_53")

0x00c1: DW_TAG_variable
  DW_AT_abstract_origin (0x013f "l_55")

>From DWARF info we can see how only variables i and j have correctly defined
locations and values, but those are not shown during debugging due to a
possible bug in gdb 11.2 that we report separately.

All the o

[Bug debug/105249] schedule-insns2 makes a variable not available and associates the code that assigns it to a different function frame

2022-04-12 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105249

--- Comment #1 from Cristian Assaiante  ---
This issue is similar to bug 105036 but it appears on different optimization
levels and, differently from the previously reported issue, it has a much
simpler code structure since we have only a call to a printf in the body of the
inlined routine.

[Bug debug/105249] New: schedule-insns2 makes a variable not available and associates the code that assigns it to a different function frame

2022-04-12 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105249

Bug ID: 105249
   Summary: schedule-insns2 makes a variable not available and
associates the code that assigns it to a different
function frame
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, induction variable i is not available when
stepping on line 9. At -Os we note that the address of the instruction that
assigns to variable a is associated in DWARF with locations from c(), thus
leading to a wrong current function frame when debugging. At -Og/-O1 the
behavior is instead correct. Apparently, schedule-insns2 is responsible for
generating overlapping locations for function c and induction variable i.

At -Oz/-O2/-O3, if we place a breakpoint on line 9 the line is never stepped,
but instead the program breaks inside the body of function c. For this scenario
too, the issue disappears with -fno-schedule-insns2.

Please find below a detailed analysis for -Os on x64 and a quick assessment on
past gcc versions where the issue is sometimes not present.

$ cat a.c
volatile int a;
int b[2];
static void c(int d3) { printf("%d", d3); }
int main() {
  int i;
  b[0] = 0;
  i = 0;
  for (; i < 2; i++)
a = b[i];
  c(0);
}

GCC and GDB version:
- gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Os -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 9
Breakpoint 1 at 0x400421: file a.c, line 9.
(gdb) r
Starting program: /tmp/opt 

Breakpoint 1, c (d3=) at a.c:9
9   a = b[i];
(gdb) info loc
No locals.


ASM at -Os:
00400410 :
  400410:   50  push   %rax
  400411:   8b 05 25 0c 20 00   mov0x200c25(%rip),%eax#
60103c 
  400417:   31 d2   xor%edx,%edx
  400419:   31 f6   xor%esi,%esi
  40041b:   89 15 1f 0c 20 00   mov%edx,0x200c1f(%rip)#
601040 
  400421:   bf b4 05 40 00  mov$0x4005b4,%edi
  400426:   89 05 14 0c 20 00   mov%eax,0x200c14(%rip)#
601040 
  40042c:   31 c0   xor%eax,%eax
  40042e:   89 15 04 0c 20 00   mov%edx,0x200c04(%rip)#
601038 
  400434:   e8 c7 ff ff ff  callq  400400 
  400439:   31 c0   xor%eax,%eax
  40043b:   59  pop%rcx
  40043c:   c3  retq

DWARF at -Os:
[ function c DIE ]
0x00a7: DW_TAG_inlined_subroutine
  DW_AT_abstract_origin (0x00f1 "c")
  DW_AT_entry_pc(0x0040042c)
  DW_AT_unknown_2138(0x03)
  DW_AT_ranges  (0x000c
 [0x00400419, 0x0040041b)
 [0x00400421, 0x00400426)
 [0x0040042c, 0x0040042e)
 [0x00400434, 0x00400439))
  DW_AT_call_file   ("/tmp/a.c")
  DW_AT_call_line   (10)
  DW_AT_call_column (0x03)

[ variable i DIE ]
0x0095: DW_TAG_variable
  DW_AT_name("i")
  DW_AT_decl_file   ("/tmp/a.c")
  DW_AT_decl_line   (5)
  DW_AT_decl_column (0x07)
  DW_AT_type(0x003d "int")
  DW_AT_location(0x0010: 
 [0x00400421, 0x0040042c): DW_OP_lit1,
DW_OP_stack_value
 [0x0040042c, 0x0040043d): DW_OP_lit2,
DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)


DEBUG line info at -Os:
AddressLine   Column File   ISA Discriminator Flags
-- -- -- -- --- - -
0x00400421  9  5  1   0 0  is_stmt

In the DWARF info function c is defined in the range [0x00400421,
0x00400426) and from the line info we can see how the begin address of
the range is associated with line 9. This causes the variable i to not be
available when debugging even if its location is correctly defined.

Through some testing we found out that the optimization that makes the variable
not available and introduces the location overlapping is -fschedule-insns2. If
we add -fno-schedule-insns2 to the previous compilation command line, the issue
is not present anymore since the DWARF location and line number association are
correctly computed. The option would also solve the correctness problem pointed
out for -Oz/-O2/-O3.

ASM at -Os with -fno-schedule-insns2:
00400410 :
  4004

[Bug debug/105248] New: Missing value or location attribute for constant live variable likely caused by tree-dse at -O1/-O2/-O3

2022-04-12 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105248

Bug ID: 105248
   Summary: Missing value or location attribute for constant live
variable likely caused by tree-dse at -O1/-O2/-O3
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variable l_56 is marked as optimized out when
stepping on a call to an external function that takes it as an argument. This
happens then the optimization level is -O1/-O2/-O3 while at -Og the debug
information is correctly defined. The variable has constant value.

Apparently, tree-dse optimization is responsible for a missing location
attribute in the DWARF DIE associated with variable l_56. If we prevent the
compiler from performing such optimization, the generated ASM will be identical
but the DWARF location info will be complete, making the variable available in
its uses.

Please find below a detailed analysis for -O1 on x64 and a quick assessment on
past gcc versions where the issue is sometimes not present.

$ cat a.c
void a()
{
int *b;
short l_47 = 5;
int l_56 = 6;
int **c = &b;
test(l_47, l_56);
*c = &l_56;
}
int main ()
{
a();
}

$ cat lib.c
#include 

void test(int l_47, int l_56) {
   printf("%d %d", l_47, l_56);
}

GCC and GDB version:
- gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -O1 -g a.c lib.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 7
Breakpoint 1 at 0x40054a: file a.c, line 7.
(gdb) r
Starting program: /tmp/opt 

Breakpoint 1, a () at a.c:7
7   test(l_47, l_56);
(gdb) info locals
b = 
l_47 = 5
l_56 = 
c = 

ASM at -O1:
00400546 :
  400546:   48 83 ec 08 sub$0x8,%rsp
  40054a:   be 06 00 00 00  mov$0x6,%esi
  40054f:   bf 05 00 00 00  mov$0x5,%edi
  400554:   b8 00 00 00 00  mov$0x0,%eax
  400559:   e8 30 00 00 00  callq  40058e 
  40055e:   48 83 c4 08 add$0x8,%rsp
  400562:   c3  retq

DWARF info at -O1:
0x00a7: DW_TAG_variable
  DW_AT_name("l_56")
  DW_AT_decl_file   ("/tmp/a.c")
  DW_AT_decl_line   (5)
  DW_AT_decl_column (0x09)
  DW_AT_type(0x003d "int")

>From DWARF info we can see how the variable l_56 DIE is completely missing
either a const value or a location attribute and this lack of information
causes the unavailability of its value during debugging.

Through some testing we found out that the optimization that makes the variable
not available and that introduces the location overlapping is -ftree-dse. If we
add -fno-tree-dse to the previous compilation command line, the issue is not
present anymore since the DWARF location is correctly computed with the correct
value associated with it.


ASM at -O1 with -fno-tree-dse:
00400546 :
  400546:   48 83 ec 08 sub$0x8,%rsp
  40054a:   be 06 00 00 00  mov$0x6,%esi
  40054f:   bf 05 00 00 00  mov$0x5,%edi
  400554:   b8 00 00 00 00  mov$0x0,%eax
  400559:   e8 30 00 00 00  callq  40058e 
  40055e:   48 83 c4 08 add$0x8,%rsp
  400562:   c3  retq

DWARF info at -O1 with -fno-tree-dse:
0x00a7: DW_TAG_variable
  DW_AT_name("l_56")
  DW_AT_decl_file   ("/tmp/a.c")
  DW_AT_decl_line   (5)
  DW_AT_decl_column (0x09)
  DW_AT_type(0x003d "int")
  DW_AT_location(0x000e: 
 [0x0040054a, 0x0040055e): DW_OP_lit6,
DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)


We have also tested older gcc versions (6.4, 7.5, 8.4, 9.3, 10.3, 11.1) and the
results are identical to the git version.

[Bug debug/105176] New: -fdce causes a non-dead variable to show as optimized out when debugging only at -Os/Oz

2022-04-06 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105176

Bug ID: 105176
   Summary: -fdce causes a non-dead variable to show as optimized
out when debugging only at -Os/Oz
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

When debugging this minimized C example, variable l_83 appears as optimized out
at line 13, where it is used as a call argument to a function defined in
another module. This happens with -Os and -Oz but not with -Og/O1/O2/O3.

Apparently, -fdce causes the range in the location definition of variable l_83
to not include the call to the function test. By supplying -fno-dce, the value
is visible and the ASM stays unchanged. At other levels the location definition
seems richer and the ranges include the call.

Below we provide details for -Os on x64 (-Oz looks identical) and a partial
assessment of older gcc versions (no issue on 6.4, found in gcc-7+).

$ cat a.c  
enum
{
a
} b;
void c()
{
char d, l_122 = 0;
short l_83 = 4;
int l_126 = 0;
for (; b != 3; ++b)
{
char l_114 = l_83--;
test(l_83, l_122, l_126, l_114);
}
d = l_83;
}
int main ()
{
c();
}

$ cat lib.c  
#include 

void test(int l_83, int l_122, int l_126, int l_114) {
printf("%d %d %d %d", l_83, l_122, l_126, l_114);
}


GCC and GDB version:
- gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Os -g a.c lib.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 13
Breakpoint 1 at 0x400517: file a.c, line 13.
(gdb) r
Starting program: /tmp/opt 

Breakpoint 1, c () at a.c:13
13  test(l_83, l_122, l_126, l_114);
(gdb) info loc
l_114 = 4 '\004'
d = 
l_122 = 0 '\000'
l_83 = 
l_126 = 0


ASM at -Os:
00400506 :
  400506:   53  push   %rbx
  400507:   bb 04 00 00 00  mov$0x4,%ebx
  40050c:   83 3d 21 0b 20 00 03cmpl   $0x3,0x200b21(%rip)#
601034 
  400513:   74 1e   je 400533 
  400515:   ff cb   dec%ebx
  400517:   31 d2   xor%edx,%edx
  400519:   31 f6   xor%esi,%esi
  40051b:   31 c0   xor%eax,%eax
  40051d:   8d 4b 01lea0x1(%rbx),%ecx
  400520:   0f bf fbmovswl %bx,%edi
  400523:   0f be c9movsbl %cl,%ecx
  400526:   e8 0a 00 00 00  callq  400535 
  40052b:   ff 05 03 0b 20 00   incl   0x200b03(%rip)# 601034

  400531:   eb d9   jmp40050c 
  400533:   5b  pop%rbx
  400534:   c3  retq   


DWARF at -Os:
0x00cf: DW_TAG_variable
  DW_AT_name("l_83")
  DW_AT_decl_line   (8)
  DW_AT_decl_column (0x0b)
  DW_AT_type(0x0159 "short int")
  DW_AT_location(0x0010: 
 [0x00400506, 0x0040050c): DW_OP_lit4,
DW_OP_stack_value
 [0x00400515, 0x00400517): DW_OP_breg3
RBX-1, DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)


>From DWARF location info at -Os, the range does not include the call to the
test function since it is at address 400526.

Through some testing we found out that the flag involved in the issue is likely
-fdce. If we add -fno-dce to the compilation command line used above, the
variable l_83 appears in the current frame with its value correctly shown at
line 13. The DWARF location info is correctly defined for the variable
throughout its whole lifetime.

DWARF at -Os with -fno-dce:
0x00cf: DW_TAG_variable
  DW_AT_name("l_83")
  DW_AT_decl_line   (8)
  DW_AT_decl_column (0x0b)
  DW_AT_type(0x0159 "short int")
  DW_AT_location(0x0010: 
 [0x00400506, 0x0040050c): DW_OP_lit4,
DW_OP_stack_value
 [0x0040050c, 0x00400534): DW_OP_reg3 RBX)
  DW_AT_GNU_locviews(0x000c)

>From DWARF location info at -Os with -fno-dce, the range is larger than it is
at -Os, thus including the call at address 400526.

We also tested older gcc versions (6.4, 7.5, 8.4, 9.3, 10.3, 11.1) and the
behavior described above for the git version is also reproduced for all
versions except gcc-6.4, where the variable is correctly available.

[Bug debug/105161] New: variable constant-folded in its uses appears as optimized out depending on where it is assigned

2022-04-05 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105161

Bug ID: 105161
   Summary: variable constant-folded in its uses appears as
optimized out depending on where it is assigned
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C code, variable j is shown as optimized out when debugging
line 8, where it is used to index an access to global array b for assigning
volatile global variable a. The other two variables i and k used for the access
are instead available. This happens at possibly any optimization level: we
tested -Og, -O1, -O2, and -O3.

We suppose the operation (j)*k is constant-folded to 0 when computing the
offset for accessing b. The variable remains optimized out also under other
value choices for j that we tested. But it becomes visible if we make j
non-constant (for instance with “(j++)*k” at line 8).

We also note that if the assignment is done at declaration time (e.g., “int i =
0, j = 0, k;” with line 6 becoming simply “k=0;”), then variable j becomes
visible with 0 value.

Furthemore, for the modified code, older versions of gdb (e.g. 8.1) will not
list j among local variables: we believe this may be a then-fixed gdb bug, but
perhaps still worth mentioning.

We provide details for -Og on x64 and a quick assessment of older gcc versions
below.

$ cat a.c
volatile int a;
int b[10][2];
int main() {
  int i = 0, j, k;
  for (; i < 10; i++) {
j = k = 0;
for (; k < 1; k++)
  a = b[i][(j)*k];
  }
}

GCC and GDB version:
- gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 8
Breakpoint 1 at 0x40048d: file a.c, line 8.
(gdb) r
Starting program: /home/stepping/37/reduce/opt 

Breakpoint 1, main () at a.c:8
8 a = b[i][(j)*k];
(gdb) info loc
i = 0
j = 
k = 0


ASM of main function at Og:
00400486 :
 400486:   ba 00 00 00 00  mov$0x0,%edx
 40048b:   eb 1a   jmp4004a7 
 40048d:   48 63 camovslq %edx,%rcx
 400490:   8b 0c cd 60 10 60 00mov0x601060(,%rcx,8),%ecx
 400497:   89 0d 13 0c 20 00   mov%ecx,0x200c13(%rip)#
6010b0 
 40049d:   83 c0 01add$0x1,%eax
 4004a0:   85 c0   test   %eax,%eax
 4004a2:   7e e9   jle40048d 
 4004a4:   83 c2 01add$0x1,%edx
 4004a7:   83 fa 09cmp$0x9,%edx
 4004aa:   7f 07   jg 4004b3 
 4004ac:   b8 00 00 00 00  mov$0x0,%eax
 4004b1:   eb ed   jmp4004a0 
 4004b3:   b8 00 00 00 00  mov$0x0,%eax
 4004b8:   c3  retq
 4004b9:   0f 1f 80 00 00 00 00nopl   0x0(%rax)



DWARF at -Og:
0x009b: DW_TAG_variable
  DW_AT_name("i")
  DW_AT_decl_column (0x07)
  DW_AT_type(0x0041 "int")
  DW_AT_location(0x0010: 
 [0x00400486, 0x0040048d): DW_OP_lit0,
DW_OP_stack_value
 [0x0040048d, 0x004004b9): DW_OP_reg1 RDX)
  DW_AT_GNU_locviews
(0x000c)

0x00ab: DW_TAG_variable
  DW_AT_name("j")
  DW_AT_decl_file   ("/home/stepping/37/reduce/a.c")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x0e)
  DW_AT_type(0x0041 "int")

0x00b5: DW_TAG_variable
  DW_AT_name("k")
  DW_AT_decl_column (0x11)
  DW_AT_type(0x0041 "int")
  DW_AT_location(0x001e: 
 [0x0040048d, 0x004004a7): DW_OP_reg0 RAX)
  DW_AT_GNU_locviews
(0x001c)


>From DWARF information, attributes location and const value are completely
missing for variable j, while other variables have a correct location
definition that makes them available at line 8.

Interestingly, if we modify the source code by initializing variable j earlier
at line 4, the const value attribute is correctly added to variable’s DIE and
therefore the variable is correctly available at line 8 at every optimization
level.

DWARF at -Og (with j initialization at line 4):
0x009b: DW_TAG_variable
  DW_AT_name("i")
  DW_AT_decl_column (0x07)
  DW_AT_type(0x0041 "int")
  DW_AT_location(0x0010: 
 [0x00400486, 0x0040048d): DW_OP_lit0,
DW_OP_st

[Bug debug/105145] New: dropped DWARF location information at -O1/-O2/-O3 upon ftree-dse

2022-04-04 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105145

Bug ID: 105145
   Summary: dropped DWARF location information at -O1/-O2/-O3 upon
ftree-dse
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

When debugging this minimized C example, pointer variable l_158 appears as
optimized out at every stepped line, including line 14 where it is used to
compute the value of a function call argument. This happens at -O1/O2/O3 but
not at -Og.

Apparently, -ftree-dse makes the DWARF DIE for l_158 drop a location definition
while the ASM stays unchanged. When adding -fno-tree-dse to -O1/O2/O3, the
variable value appears at lines 13 and 14. However, it stays as optimized out
between line 10 (where it is assigned) to 13. We were not able to pinpoint what
may be behind this latter fact, though.

Below we provide details for -O1 on x64 and a quick assessment of prior gcc
versions.

$ cat a.c
int *a;
int **d = &a;
int *e = &d;
int f;
volatile char g;
short h(int b, int c) { return 0; }
int main() {
  int ***l_134 = e;
  int *l_133 = l_134;
  int l_141 = 0;
  int *l_158 = &l_141;
  short l_185 = 3;
  *d = l_158;
  g = ***l_134 + h(f != &l_158, l_185);
}

GCC and GDB version:
-  gcc (GCC) 12.0.0 20211227 (experimental) - commit id: 500d3f0a302
- GNU gdb (GDB) 11.2

GDB trace:
$ gcc -O1 -g a.c -o opt
$ gdb -q opt
root@1f83e51b6153:/tmp# gdb -q opt
Reading symbols from opt...
(gdb) b 14
Breakpoint 1 at 0x4004aa: file a.c, line 14.
(gdb) r
Starting program: /tmp/opt 

Breakpoint 1, main () at a.c:14
14g = ***l_134 + h(f != &l_158, l_185);
(gdb) info locals
l_134 = 0x601030 
l_133 = 0x601030 
l_141 = 0
l_158 = 
l_185 = 3

ASM at -O1:
0040048c :
  40048c:   48 8b 05 95 0b 20 00mov0x200b95(%rip),%rax#
601028 
  400493:   c7 44 24 fc 00 00 00movl   $0x0,-0x4(%rsp)
  40049a:   00 
  40049b:   48 8d 4c 24 fc  lea-0x4(%rsp),%rcx
  4004a0:   48 8b 15 89 0b 20 00mov0x200b89(%rip),%rdx#
601030 
  4004a7:   48 89 0amov%rcx,(%rdx)
  4004aa:   48 8b 00mov(%rax),%rax
  4004ad:   48 8b 00mov(%rax),%rax
  4004b0:   8b 00   mov(%rax),%eax
  4004b2:   88 05 88 0b 20 00   mov%al,0x200b88(%rip)#
601040 
  4004b8:   b8 00 00 00 00  mov$0x0,%eax
  4004bd:   c3  retq

DWARF at -O1:
0x0101: DW_TAG_variable
  DW_AT_name("l_158")
  DW_AT_decl_file   ("/tmp/a.c")
  DW_AT_decl_line   (11)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x0041 "int*")

Through some testing we found out that the optimization flag involved in the
issue is likely -ftree-dse. If we add -fno-tree-dse to the compilation command
line used above, the pointer variable l_158 appears in the current frame with
its value correctly shown at line 14.
The DWARF location info is correctly defined for the variable throughout its
whole lifetime.

ASM at -O1 with -fno-tree-dse:
0040048c :
  40048c:   48 8b 05 95 0b 20 00mov0x200b95(%rip),%rax#
601028 
  400493:   c7 44 24 fc 00 00 00movl   $0x0,-0x4(%rsp)
  40049a:   00 
  40049b:   48 8d 4c 24 fc  lea-0x4(%rsp),%rcx
  4004a0:   48 8b 15 89 0b 20 00mov0x200b89(%rip),%rdx#
601030 
  4004a7:   48 89 0amov%rcx,(%rdx)
  4004aa:   48 8b 00mov(%rax),%rax
  4004ad:   48 8b 00mov(%rax),%rax
  4004b0:   8b 00   mov(%rax),%eax
  4004b2:   88 05 88 0b 20 00   mov%al,0x200b88(%rip)#
601040 
  4004b8:   b8 00 00 00 00  mov$0x0,%eax
  4004bd:   c3  retq

DWARF at -O1 with -fno-tree-dse:
0x0101: DW_TAG_variable
  DW_AT_name("l_158")
  DW_AT_decl_line   (11)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x0041 "int*")
  DW_AT_location(0x0020: 
 [0x0040049b, 0x004004a0): DW_OP_fbreg -12,
DW_OP_stack_value
 [0x004004a0, 0x004004b8): DW_OP_reg2 RCX)
  DW_AT_GNU_locviews(0x001c)

In short, the ASM of the main function stays identical but we have an accurate
location definition that leads to the correct availability of the value of
l_158 in its usage at line 14.

We have also tested older gcc versions (6.4, 7.5, 8.4, 9.3, 10.3, 11.1) and for
the tested optimization levels the behavior is identical to the git version
original

[Bug debug/105124] -Og loses DWARF value for a reassigned variable that is kept instead by other optimization levels

2022-04-01 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105124

--- Comment #1 from Cristian Assaiante  ---
We suspect this may be related to bug
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108 but this time the behaviors
at -O1 and -Og are different

[Bug debug/105124] New: -Og loses DWARF value for a reassigned variable that is kept instead by other optimization levels

2022-04-01 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105124

Bug ID: 105124
   Summary: -Og loses DWARF value for a reassigned variable that
is kept instead by other optimization levels
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C code, variable l_62 appears as optimized out at line 6,
where it is assigned again with the same value and used in the assignment of
global variable a. The variable is then available at line 8 with its correct
value 6 coming from the update at line 7.

This behavior only occurs when the optimization level is Og, while at -O1 and
higher optimization levels the variable is always visible with a correct value
available.

Interestingly, if we assign l_62 for instance with 2 at line 4, then the issue
is no longer present at Og and the value 2 is displayed at line 6 (just like at
-O1/O2/O3). We also note that, in this case, at -O1/-Og the DWARF info contains
values 0 and 6, while at -O2/-O3 also value 0 which is in use only between line
6 and 7.

We provide below a detailed analysis on x64.

$ cat a.c
short a;
int foo1() { return 0; }
short foo0(int d) {
  int e, f = 11, l_62 = 0;
  e = foo1();
  a = f | (l_62 = e) >= d;
  l_62 = 6;
  return d;
}
int main() { foo0(0); }


GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)

$ gdb --version
GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 6
Breakpoint 1 at 0x40048f: file a.c, line 6.
(gdb) r
Starting program: /home/stepping/4/reduce/opt 

Breakpoint 1, foo0 (d=d@entry=0) at a.c:6
6 a = f | (l_62 = e) >= d;
(gdb) info loc
e = 
f = 11
l_62 = 
(gdb) n
8 return d;
(gdb) info loc
e = 
f = 11
l_62 = 6


ASM of foo0 function:
0040048c :
 40048c:   53  push   %rbx
 40048d:   89 fb   mov%edi,%ebx
 40048f:   66 c7 05 92 0b 20 00movw   $0xb,0x200b92(%rip)#
60102a 
 400496:   0b 00  
 400498:   89 d8   mov%ebx,%eax
 40049a:   5b  pop%rbx
 40049b:   c3  retq 


DWARF at -Og:
0x00c9: DW_TAG_variable
  DW_AT_name("l_62")
  DW_AT_decl_file   ("/home/stepping/4/reduce/a.c")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x12)
  DW_AT_type(0x007f "int")
  DW_AT_location(0x0010: 
 [0x0040048f, 0x0040048f): DW_OP_lit0,
DW_OP_stack_value
 [0x00400498, 0x0040049c): DW_OP_lit6,
DW_OP_stack_value)
  DW_AT_unknown_2137(0x000c)



>From a quick analysis of DWARF symbols, the problem seems to be in the location
definition of the variable. The first entry is an empty range when it should
probably include the instruction at 40048f which is associated with line 6. We
tried to manually patch the executable file from -Og by setting the first entry
of the location [0x0040048f, 0x0040048f) to
[0x0040048f, 0x00400498). After the change, the variable is
displayed. 

At -O1 and higher optimization levels, the first entry of the DWARF location
info contains the correct range that includes the ASM instruction associated
with line 6.

DWARF at O1 (identical at O2/O3, only addresses change):
0x00a1:   DW_TAG_variable
DW_AT_abstract_origin   (0x00e2 "l_62")
DW_AT_location  (0x0020: 
   [0x004003a0, 0x004003ac): DW_OP_lit0,
DW_OP_stack_value
   [0x004003ac, 0x004003af): DW_OP_lit6,
DW_OP_stack_value)
DW_AT_unknown_2137  (0x001c)

 If we interpret the code correctly, foo1 is always
inlined/constant-propagated, while foo0 is inlined at other optimization levels
but not at -Og.


We have also tested older gcc versions (6.4, 7.5, 8.4, 9.3, 10.3, 11.1) and the
variable l_62 is always optimized out on line 6 at each optimization level.
The only exception is gcc-7 that produces (only at Og) a wrong debug
information, since at line 6 l_62 has 6 as current value.

[Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant

2022-03-31 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #9 from Cristian Assaiante  ---
Created attachment 52728
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52728&action=edit
Executable file at -Og with l_144 = 8

[Bug debug/105108] incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant

2022-03-31 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

--- Comment #8 from Cristian Assaiante  ---
(In reply to Jakub Jelinek from comment #3)
> And I certainly can't reproduce the wrong-debug issue you're talking about.
> If I change it to char l_144 = 8;
> then optimized dump has:
>[local count: 1073741824]:
>   # DEBUG BEGIN_STMT
>   # DEBUG l_144 => 8
>   # DEBUG BEGIN_STMT
>   # DEBUG l_165 => 128
>   # DEBUG BEGIN_STMT
>   # DEBUG l_144 => NULL
>   # DEBUG BEGIN_STMT
>   a = 1;
>   return 0;
> and in the debugger it correctly says that
> (gdb) p l_144
> $1 = 
> because at the a = 1 store the value is unknown.

I have tested again the C example with l_144 = 8 and in gdb l_144 is not marked
as optimized out, instead it has 8 as value:

$ cat a.c
int a;
char b() { return 0; }
int main() {
 char l_144 = 8;
 short l_165 = 128;
 l_144 = b();
 a = l_144 != l_165;
}

$ gcc -Og -g a.c -o opt

DWARF info for l_144:
0x006b: DW_TAG_variable
  DW_AT_name("l_144")
  DW_AT_decl_file   ("/home/stepping/a.c")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x07)
  DW_AT_type(0x008d "char")
  DW_AT_location(0x000e: 
 [0x0040048c, 0x0040048c): DW_OP_lit8,
DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)

GDB trace:
Reading symbols from opt...
(gdb) b 6
Breakpoint 1 at 0x40048c: file a.c, line 6.
(gdb) r
Starting program: /home/stepping/opt 

Breakpoint 1, main () at a.c:7
7a = l_144 != l_165;
(gdb) p l_144
$1 = 8 '\b'


I will add the executable file as an attachment.

[Bug debug/105108] New: incomplete/incorrect DWARF information at -O1 and -Og after inlining a function returning a constant

2022-03-30 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105108

Bug ID: 105108
   Summary: incomplete/incorrect DWARF information at -O1 and -Og
after inlining a function returning a constant
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variable l_144 is not available when debugging
(optimized out) when used in the assignment of variable a.

We found this odd since -O2/-O3 generate nearly identical ASM but with complete
debug information for l_144. At -O1/-Og the DIE of the variable misses instead
the const value attribute.

We were not able to pinpoint the root cause to a specific compilation option,
but suspect an interaction of inlining and constant propagation. We provide
below additional analysis for x64.

Then, much to our surprise, when we modify line 4 to assign l_144 with e.g. 8,
the debugger shows 8 instead of 0 as its value at line 7, therefore exposing
incorrect debug information. At a first look, this happened also with -O2/O3:
however, we then found -O2/-O3 DWARF information to be correct (also, lldb
displays 0), with the issue likely being a bug in gdb that we will report
separately.

$ cat a.c
int a;
char b() { return 0; }
int main() {
 char l_144;
 short l_165 = 128;
 l_144 = b();
 a = l_144 != l_165;
}


GCC and GDB version (GCC commit id: 500d3f0a302):
> gcc (GCC) 12.0.0 20211227 (experimental)
> GNU gdb (GDB) 11.2

GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb opt
Reading symbols from opt...
(gdb) b 7
Breakpoint 1 at 0x40048c: file a.c, line 7.
(gdb) r
Starting program: /home/stepping/35/reduce/opt 

Breakpoint 1, main () at a.c:7
7 a = l_144 != l_165;
(gdb) info locals
l_144 = 
l_165 = 128


ASM at Og (identical at O1):
0040048c :
 40048c:   c7 05 96 0b 20 00 01movl   $0x1,0x200b96(%rip)#
60102c 
 400493:   00 00 00  
 400496:   b8 00 00 00 00  mov$0x0,%eax
 40049b:   c3  retq
 40049c:   0f 1f 40 00 nopl   0x0(%rax)

DWARF at Og (identical at O1):
0x0049:   DW_TAG_subprogram
DW_AT_external  (true)
DW_AT_name  ("main")
DW_AT_decl_file ("/home/stepping/35/reduce/a.c")
DW_AT_decl_line (3)
DW_AT_decl_column   (0x05)
DW_AT_type  (0x0042 "int")
DW_AT_low_pc(0x0040048c)
DW_AT_high_pc   (0x0040049c)
DW_AT_frame_base(DW_OP_call_frame_cfa)
DW_AT_call_all_calls(true)
DW_AT_sibling   (0x0085)

0x006b: DW_TAG_variable
  DW_AT_name("l_144")
  DW_AT_decl_file   ("/home/stepping/35/reduce/a.c")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x0085 "char")

0x0077: DW_TAG_variable
  DW_AT_name("l_165")
  DW_AT_decl_file   ("/home/stepping/35/reduce/a.c")
  DW_AT_decl_line   (5)
  DW_AT_decl_column (0x09)
  DW_AT_type(0x008c "short int")
  DW_AT_const_value (0x80)


At higher optimization levels the ASM is nearly the same, except the use of xor
instead of mov to set the return value to zero:

004003a0 :
 4003a0:   c7 05 82 0c 20 00 01movl   $0x1,0x200c82(%rip)#
60102c 
 4003a7:   00 00 00  
 4003aa:   31 c0   xor%eax,%eax
 4003ac:   c3  retq
 4003ad:   0f 1f 00nopl   (%rax)

But the variable is correctly visible when stepping on line 7 since the const
value attribute is present in its debug information:

0x0045:   DW_TAG_subprogram
DW_AT_external  (true)
DW_AT_name  ("main")
DW_AT_decl_file ("/home/stepping/35/reduce/a.c")
DW_AT_decl_line (3)
DW_AT_decl_column   (0x05)
DW_AT_type  (0x003e "int")
DW_AT_low_pc(0x004003a0)
DW_AT_high_pc   (0x004003ad)
DW_AT_frame_base(DW_OP_call_frame_cfa)
DW_AT_call_all_calls(true)
DW_AT_sibling   (0x0080)

0x0067: DW_TAG_variable
  DW_AT_name("l_144")
  DW_AT_decl_line   (4)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x0080 "char")
  DW_AT_const_value (0x00)

0x0073: DW_TAG_variable
  DW_AT_name("l_165")
  DW_AT_decl_line   (

[Bug debug/105036] Missing variables when debugging due to overlapping ranges after unrolling, instruction scheduling, and inlining at -O3

2022-03-24 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105036

--- Comment #2 from Cristian Assaiante  ---
Indeed, we understand some information may be lost for the sake of keeping
debug info correct.

We reported this in the first place because, besides the missing variables, a
wrong function (i.e., foo) is reported as executing in gdb, while the program
is executing a line located in its caller (i.e., main).

Perhaps, if it would be possible to fix the ranges as not to overlap, also the
missing variables would become visible? Since DWARF info for i=0, j=0 is
emitted but not in a way “retrievable” by gdb during source-level debugging.

[Bug debug/105036] New: Missing variables when debugging due to overlapping ranges after unrolling, instruction scheduling, and inlining at -O3

2022-03-23 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105036

Bug ID: 105036
   Summary: Missing variables when debugging due to overlapping
ranges after unrolling, instruction scheduling, and
inlining at -O3
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variables i and j that index the two nested loops
are missing when putting a breakpoint on the statement in the inner loop and
executing it for the very first time. Then, they become visible when executing
it at iteration (0,1) and still are when about to exit the outer loop, as
expected with unrolling.

This behavior appears to be caused by i and j’s DWARF location info, for the
(0,0) iteration only, overlapping with DWARF location info for the inlined
function foo. We observe the issue at -O3 with the root cause likely being
schedule-insns2, combined with the effects of inlining foo and loop unrolling.
We also noted that if we shorten the loop counts in the example, for instance
to have i stopping at 3 and j at 4, the issue is no longer present.

Please find below a detailed analysis for -O3 on x64 and a quick assessment on
past gcc versions where the issue is sometimes not present.

$ cat a.c
volatile int a;
int b;
unsigned c[35];
int d;
void foo() {
  b = 3;
  for (; b >= -10; b = b - 4) {
d++;
  }
}
int main() {
  int i, j;
  foo();
  i = 0;
  for (; i < 5; i++) {
j = 0;
for (; j < 7; j++)
  a = c[i * 5 + j];
  }
}

GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gdb --version
GNU gdb (GDB) 11.2
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GDB trace:
$ gcc -O3 -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 18
Breakpoint 1 at 0x4003b6: /home/stepping/50/reduce/a.c:18. (2 locations)
(gdb) r
Starting program: /home/stepping/50/reduce/opt 

Breakpoint 1, foo () at test.c:18
18a = c[i * 5 + j];
(gdb) info locals
No locals.
(gdb) n

Breakpoint 1, main () at test.c:18
18a = c[i * 5 + j];
(gdb) info locals
i = 0
j = 1
(gdb) n
15for (; i < 5; i++) {
(gdb) info locals
i = 5
j = 7

GDB trace with instruction stepping: 
$ gdb -q opt
Reading symbols from opt...
(gdb) b 18
Breakpoint 1 at 0x4003b6: /home/stepping/50/reduce/a.c:18. (2 locations)
(gdb) r
Starting program: /home/stepping/50/reduce/opt 

Breakpoint 1, foo () at test.c:18
18a = c[i * 5 + j];
(gdb) info loc
No locals.
(gdb) si
0x004003bd in main () at test.c:18
18a = c[i * 5 + j];
(gdb) info loc
i = 0
j = 0
(gdb) si

Breakpoint 1, main () at test.c:18
18a = c[i * 5 + j];
(gdb) info loc
i = 0
j = 1

We can see how in the source-level stepping GDB trace, when the breakpoint at
line 18 is hit for the first time, variables i and j are not available due to
the location overlap. Instead, when stepping through instructions, we see the
correct value of i and j from the second instruction associated with the first
execution of line 18 (since the first one is the only one overlapping).

ASM at -O3 (shortened):
004003a0 :
  4003a0:   8b 05 da 0c 20 00   mov0x200cda(%rip),%eax#
601080 
  4003a6:   8b 15 e8 0c 20 00   mov0x200ce8(%rip),%edx#
601094 
  4003ac:   c7 05 56 0d 20 00 f3movl   $0xfff3,0x200d56(%rip)  
 # 60110c 
  4003b3:   ff ff ff 
  4003b6:   83 05 a3 0c 20 00 04addl   $0x4,0x200ca3(%rip)#
601060 
  4003bd:   89 05 4d 0d 20 00   mov%eax,0x200d4d(%rip)#
601110 
  4003c3:   8b 05 bb 0c 20 00   mov0x200cbb(%rip),%eax#
601084 
[ . . . ]
  400519:   8b 05 c9 0b 20 00   mov0x200bc9(%rip),%eax#
6010e8 
  40051f:   89 05 eb 0b 20 00   mov%eax,0x200beb(%rip)#
601110 
  400525:   31 c0   xor%eax,%eax
  400527:   c3  retq   
  400528:   0f 1f 84 00 00 00 00nopl   0x0(%rax,%rax,1)
  40052f:   00 


>From the ASM we see that function foo is inlined within the function main and
all the loops are fully unrolled.

DWARF info at -O3:
0x00a0:   DW_TAG_subprogram
DW_AT_external  (true)
DW_AT_name  ("main")
DW_AT_decl_file ("/home/stepping/50/reduce/a.c")
  

[Bug debug/105007] Missing variables at -O2/O3 likely caused by incorrect debug info after inlining

2022-03-21 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105007

--- Comment #1 from Cristian Assaiante  ---
The gdb bug report can be found at:
https://sourceware.org/bugzilla/show_bug.cgi?id=28987

[Bug debug/105007] New: Missing variables at -O2/O3 likely caused by incorrect debug info after inlining

2022-03-21 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105007

Bug ID: 105007
   Summary: Missing variables at -O2/O3 likely caused by incorrect
debug info after inlining
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variables i and l_3, defined within the scope of
the inlined function foo, are associated with DWARF symbols having possibly
wrong location definition, which causes variables to not be available during
debugging (in the example, the variables are used as call arguments to a
function defined in an external module). We observe the bug at -O2 and -O3 with
the root cause possibly being inlining. Please find below a detailed analysis
for -O2 (with -O3 DWARF info looks identical) on x64, including a comparison
with past gcc versions where the bug is sometimes not present.

Furthermore, once we make both variables appear by disabling some
optimizations, the program reveals a possible bug in gdb, which ends up
displaying an incorrect value for variable i while lldb shows the correct one.
We are filing a separate bug report, linking it in a comment below, as the
behavior is quite articulated.

$ cat a.c
void foo()
{ 
   int l_3 = 5, i = 0;
   for (; i < 8; i++)
   ;
   test(l_3, i);
}
int main()
{
   foo();
}
$ cat lib.c
#include 

void test(int l_3, int i) {
   printf("%d %d", l_3, i);
}

GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gdb --version
GNU gdb (GDB) 11.2
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GDB trace:
$ gcc -O2 -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 6
Breakpoint 1 at 0x400410: /home/stepping/2/reduce/a.c:6. (2 locations)
(gdb) r
Starting program: /home/stepping/2/reduce/opt

Breakpoint 1, main () at a.c:6
6   test(l_3, i);
(gdb) info loc
No locals.

ASM at -O2:
00400410 :
 400410:   48 83 ec 08 sub$0x8,%rsp
 400414:   be 08 00 00 00  mov$0x8,%esi
 400419:   bf 05 00 00 00  mov$0x5,%edi
 40041e:   31 c0   xor%eax,%eax
 400420:   e8 1b 01 00 00  callq  400540 
 400425:   31 c0   xor%eax,%eax
 400427:   48 83 c4 08 add$0x8,%rsp
 40042b:   c3  retq
 40042c:   0f 1f 40 00 nopl   0x0(%rax)

DWARF info at -O2:
0x0065: DW_TAG_inlined_subroutine
 DW_AT_abstract_origin (0x00ac "foo")
 DW_AT_entry_pc(0x00400410)
 DW_AT_unknown_2138(0x02)
 DW_AT_ranges  (0x000c
[0x00400410, 0x00400410)
[0x00400414, 0x00400425))
 DW_AT_call_file   ("/home/stepping2/reduce/a.c")
 DW_AT_call_line   (10)
 DW_AT_call_column (0x05)

0x007a:   DW_TAG_lexical_block
   DW_AT_ranges(0x000c
  [0x00400410, 0x00400410)
  [0x00400414, 0x00400425))

0x007f: DW_TAG_variable
 DW_AT_abstract_origin (0x00b9 "l_3")

0x0084: DW_TAG_variable
 DW_AT_abstract_origin (0x00c3 "i")
 DW_AT_location(0x000e:  
[0x00400410, 0x00400410): DW_OP_lit0,
DW_OP_stack_value)
 DW_AT_unknown_2137(0x000c)

0x0091: DW_TAG_call_site
 DW_AT_call_return_pc  (0x00400425)
 DW_AT_call_origin (0x002a)

0x009e:   DW_TAG_call_site_parameter
   DW_AT_location  (DW_OP_reg5 RDI)
   DW_AT_call_value(DW_OP_lit5)

0x00a3:   DW_TAG_call_site_parameter
   DW_AT_location  (DW_OP_reg4 RSI)
   DW_AT_call_value(DW_OP_lit8)

...

0x00da:   DW_TAG_subprogram
   DW_AT_abstract_origin   (0x00ac "foo")
   DW_AT_low_pc(0x00400520)
   DW_AT_high_pc   (0x00400531)
   DW_AT_frame_base(DW_OP_call_frame_cfa)
   DW_AT_call_all

[Bug debug/104938] New: Possibly wrong location definition in DWARF with -ftree-cpp at -Og only

2022-03-15 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104938

Bug ID: 104938
   Summary: Possibly wrong location definition in DWARF with
-ftree-cpp at -Og only
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example, variable l_3, which is initialized at line 5, is
associated to DWARF symbols having a possibly wrong location definition. This
causes the variable to not be available during debugging, for instance at line
6, until line 11 is reached. We observe the bug at -Og with the cause likely
being -ftree-ccp, while with other optimizations levels the variable is
correctly available at the lines where gdb can step (line 6 with -O1/O2/O3/Os,
also line 8 with -O1/Os). Please find below a detailed analysis for -Og on x64.

$ cat a.c
char a;
int b;
void foo(int *d) { a = 0; }
int main() {
int *l_3 = &b;
int **e = &l_3;
f:
if (a)
goto f;
*e = l_3;
foo(*e);
 }

GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gdb --version
GNU gdb (GDB) 11.2
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) start
Temporary breakpoint 1 at 0x40048e: file a.c, line 8.
Starting program: /home/stepping/132/reduce/opt 

Temporary breakpoint 1, main () at a.c:8
8 if (a)
(gdb) info locals
l_3 = 
e = 
(gdb) n
11foo(*e);
(gdb) info locals
l_3 = 0x60102c 
e = 

By dumping the DWARF info, we can see how the location associated to the
variable is defined with a range that does not include the instruction
associated to line 8, where the variable's value is not available despite the
original program has assigned (and, incidentally, also used) it by then.

ASM:
0040048e :
  40048e:   80 3d 9b 0b 20 00 00cmpb   $0x0,0x200b9b(%rip)#
601030 
  400495:   75 f7   jne40048e 
  400497:   bf 2c 10 60 00  mov$0x60102c,%edi
  40049c:   e8 e5 ff ff ff  callq  400486 
  4004a1:   b8 00 00 00 00  mov$0x0,%eax
  4004a6:   c3  retq   
  4004a7:   66 0f 1f 84 00 00 00nopw   0x0(%rax,%rax,1)
  4004ae:   00 00

DWARF info:
0x0084: DW_TAG_variable
  DW_AT_name("l_3")
  DW_AT_decl_file   ("/home/stepping/132/reduce/a.c")
  DW_AT_decl_line   (5)
  DW_AT_decl_column (0x08)
  DW_AT_type(0x00cc "int*")
  DW_AT_location(0x000e: 
 [0x00400497, 0x004004a1): DW_OP_addr
0x60102c, DW_OP_stack_value)
  DW_AT_GNU_locviews(0x000c)

Through some testing we found out that the optimization flag that introduces
the bug is likely -ftree-ccp. If we add -fno-tree-ccp to the compilation
command line used above, variable l_3 appears in the current frame with its
value correctly available at line 8. The location of the variable appears now
to be correctly defined with the range including the cmp instruction that
corresponds to line 8 according to the line number table in DWARF info.

ASM with -fno-tree-ccp:
  40048e:   48 83 ec 10 sub$0x10,%rsp
  400492:   48 c7 44 24 08 2c 10movq   $0x60102c,0x8(%rsp)
  400499:   60 00 
  40049b:   80 3d 8e 0b 20 00 00cmpb   $0x0,0x200b8e(%rip)#
601030 
  4004a2:   75 f7   jne40049b 
  4004a4:   bf 2c 10 60 00  mov$0x60102c,%edi
  4004a9:   e8 d8 ff ff ff  callq  400486 
  4004ae:   b8 00 00 00 00  mov$0x0,%eax
  4004b3:   48 83 c4 10 add$0x10,%rsp
  4004b7:   c3  retq   
  4004b8:   0f 1f 84 00 00 00 00nopl   0x0(%rax,%rax,1)
  4004bf:   00

DWARF info with -fno-tree-ccp:
0x0093: DW_TAG_variable
  DW_AT_name("e")
  DW_AT_decl_file   ("/home/stepping/132/reduce/a.c")
  DW_AT_decl_line   (6)
  DW_AT_decl_column (0x09)
  DW_AT_type(0x00d4 "int**")
  DW_AT_location(0x000e: 
 [0x0040049b, 0x004004b8): DW_OP_fbreg -16,
DW_OP_stack

[Bug debug/104891] New: Possibly wrong location definition in DWARF with -fschedule-insns2 at -O2/-O3

2022-03-12 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104891

Bug ID: 104891
   Summary: Possibly wrong location definition in DWARF with
-fschedule-insns2 at -O2/-O3
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In this minimized C example variables l_29 and l_30, which are defined and used
in the scope within brackets spanning lines 4-8, are associated to DWARF
symbols having a possibly wrong location definition, which causes variables to
not be available during debugging, despite their DIEs being correctly defined.
We observe the bug at -O2 and -O3 with the cause likely being
-fschedule-insns2. Please find below a detailed analysis for -O3 on x64,
including a comparison with prior gcc versions where the bug is sometimes not
present.

$ cat a.c
volatile char a;
int main() {
  int print_hash_value = 0;
  {
int l_29 = 7, l_30 = 9551615;
a = l_30 >= l_29;
printf("%X\n", 0);
  }
}

GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gdb --version
GNU gdb (GDB) 11.2
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GDB trace:
$ gcc -O3 -g a.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 6
Breakpoint 1 at 0x400410: file a.c, line 6.
(gdb) r
Starting program: /home/stepping/debuginfo-analysis/dd-mismatches/66/reduce/opt 

Breakpoint 1, main () at a.c:6
6   a = l_30 >= l_29;
(gdb) info locals
print_hash_value = 0

By dumping the DWARF info, we can see how the location of the lexical block
associated to the inner scope is defined by ranges where the first one is empty
(400410-400410), while the values for l_29 and l_30 are correctly specified:

ASM:
00400410 :
  400410:   48 83 ec 08 sub$0x8,%rsp
  400414:   31 f6   xor%esi,%esi
  400416:   bf a4 05 40 00  mov$0x4005a4,%edi
  40041b:   31 c0   xor%eax,%eax
  40041d:   c6 05 0d 0c 20 00 01movb   $0x1,0x200c0d(%rip)#
601031 
  400424:   e8 d7 ff ff ff  call   400400 
  400429:   31 c0   xor%eax,%eax
  40042b:   48 83 c4 08 add$0x8,%rsp
  40042f:   c3  ret 

DWARF info:
0x007d: DW_TAG_lexical_block
  DW_AT_ranges  (0x000c
 [0x00400410, 0x00400410)
 [0x00400414, 0x00400429))

0x0082:   DW_TAG_variable
DW_AT_name  ("l_29")
DW_AT_decl_file ("/home/test/dd/66/reduce/a.c")
DW_AT_decl_line (5)
DW_AT_decl_column   (0x09)
DW_AT_type  (0x00d6 "int")
DW_AT_const_value   (0x07)

0x008e:   DW_TAG_variable
DW_AT_name  ("l_30")
DW_AT_decl_file ("/home/test/dd/66/reduce/a.c")
DW_AT_decl_line (5)
DW_AT_decl_column   (0x13)
DW_AT_type  (0x00d6 "int")
DW_AT_const_value   (0x0091beff)

When we manually patch the first range to be (400410-400414), the variables are
displayed correctly in gdb.

Through some testing we found out that the optimization flag that introduces
the bug is likely -fschedule-insns2. If we add -fno-schedule-insns2 to the
compilation command line used above, variables l_29 and l_30 appear in the
current frame with their values correctly available at line 6. The location of
the lexical block appears now to be correctly defined (see low pc and high pc
attributes):

ASM with -fno-schedule-insns2:
00400410 :
  400410:   48 83 ec 08 sub$0x8,%rsp
  400414:   c6 05 16 0c 20 00 01movb   $0x1,0x200c16(%rip)#
601031 
  40041b:   31 f6   xor%esi,%esi
  40041d:   bf a4 05 40 00  mov$0x4005a4,%edi
  400422:   31 c0   xor%eax,%eax
  400424:   e8 d7 ff ff ff  call   400400 
  400429:   31 c0   xor%eax,%eax
  40042b:   48 83 c4 08 add$0x8,%rsp
  40042f:   c3  ret

DWARF info with -fno-schedule-insns2:
0x007d: DW_TAG_lexical_block
  DW_AT_low_pc  (0x00400414)

[Bug debug/104549] Missing variable at O2/O3 likely caused by -fearly-inlining

2022-02-17 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104549

--- Comment #4 from Cristian Assaiante  ---
We have tested also multiple versions of gdb. 
With versions 9.2 and 11.2 we have the same behavior: variable i is visible for
gcc4 and gcc7 and not visible for more recent gcc versions.
With version 10.2 we have that variable i is marked as optimized out for gcc4
and gcc7 and not visible for more recent gcc versions.

[Bug debug/104549] Missing variable at O2/O3 likely caused by -fearly-inlining

2022-02-17 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104549

--- Comment #3 from Cristian Assaiante  ---
I have tested multiple older gcc versions (4.3, 7.5, 9.4, 11.2) and apparently
the variable is visible in 4.3 and 7.5. 
The asm for the main function of the binary from gcc7.5:
main:
.LFB1:
# a.c:9
.loc 1 9 0
.cfi_startproc
# BLOCK 2 freq:1 seq:0
# PRED: ENTRY [100.0%]  (FALLTHRU)
.LVL2:
subq$8, %rsp
.cfi_def_cfa_offset 16
.LBB4:
.LBB5:
# a.c:5
.loc 1 5 0
xorl%edi, %edi
xorl%eax, %eax
calltest@PLT
.LVL3:
.LBE5:
.LBE4:
# a.c:11
.loc 1 11 0
xorl%eax, %eax
addq$8, %rsp
.cfi_def_cfa_offset 8
# SUCC: EXIT [100.0%] 
ret

Differently from more recent versions, the inlined a is in the LBB5...LBE5
range only. So there is no empty range associated to it and the debug info in
correctly visualized in gdb.

[Bug debug/104549] New: Missing variable at O2/O3 likely caused by -fearly-inlining

2022-02-15 Thread assaiante at diag dot uniroma1.it via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104549

Bug ID: 104549
   Summary: Missing variable at O2/O3 likely caused by
-fearly-inlining
   Product: gcc
   Version: 12.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: assaiante at diag dot uniroma1.it
  Target Milestone: ---

In the following testing code, local variable i, which gets passed as argument
to a function defined in an external module, is not visible upon the call when
debugging. This behavior only occurs when the optimization level is O2 or O3.


$ cat a.c
void a()
{
int i = 0;
for (; i ; ) {}
test(i)
 ;
}
int main()
{
a();
}

$ cat lib.c
#include 

void nop() {
printf("\n");
}

void test(int i) {
printf("%d", i);
}


GCC and GDB version (GCC commit id: 500d3f0a302):
$ gcc --version
gcc (GCC) 12.0.0 20211227 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gdb --version
GNU gdb (GDB) 11.2
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


GDB trace:
$ gcc -O2 -g a.c lib.c -o opt # <- same exact with O3
$ gdb -q opt
Reading symbols from opt...
(gdb) b 5
Breakpoint 1 at 0x400460: /home/stepping/66/reduce/a.c:5. (2 locations)
(gdb) r
Starting program: /home/stepping/66/reduce/opt 

Breakpoint 1, main () at a.c:5
5   test(i)
(gdb) info locals
No locals.


Through some testing we found out that the optimization flag that introduces
the bug is likely -fearly-inlining, which makes main() call the test() function
directly. Indeed, if we add the flag -fno-early-inlining to the compilation
command line used above, the variable i will appear in the current frame with
its value correctly available.