https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105194
Bug ID: 105194
Summary: -ftree-dce leads to intermittent visibility of
variable due to partial DWARF location ranges
Product: gcc
Version: 12.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: debug
Assignee: unassigned at gcc dot gnu.org
Reporter: dc.delia at protonmail dot com
Target Milestone: ---
When debugging this code, the value of variable l_33 is available when stepping
on line 8 and 10 but appears as optimized out on line 9. We tested and found
the issue at -Og/-O1/-O2/-O3.
Apparently, with -ftree-dce we get DWARF location info for l_33 that does not
include the address of the instruction mapped to line 9. By disabling it,
instead of a location attribute we see in DWARF a const value 1 for l_33 set
(as in the reassignment at line 9 the program compares a boolean expression
against 0), which makes the variable value always available.
We found this issue on x64 using gdb 11.2 with gcc commit 500d3f0a302. As for
past gcc versions, the issue is found in gcc 9/10/11 (we tested 9.3, 10.3,
11.1) but not in 6/7/8 (6.4, 7.5, 8.4). Attaching an analysis for -Og below:
$ cat a.c
short a;
int b;
char c(int d) { return 0; }
char e(int d) { return d; }
void f(int d) {
int l_33 = 1;
for (;;) {
b = e(l_33);
l_33 = a = (d || c(l_33 = 0)) >= 0;
if (b)
break;
}
}
int main() { f(4); }
GDB trace:
$ gcc -Og -g a.c -o opt
$ gdb -q
Reading symbols from opt...
(gdb) b f
Breakpoint 1 at 0x40048f: file a.c, line 8.
(gdb) r
Starting program: /tmp/opt
Breakpoint 1, f (d=4) at a.c:8
8 b = e(l_33);
(gdb) info loc
l_33 = 1
(gdb) n
9 l_33 = a = (d || c(l_33 = 0)) >= 0;
(gdb) info loc
l_33 = <optimized out>
(gdb) n
10 if (b)
(gdb) info loc
l_33 = 1
Code at -Og:
000000000040048f <f>:
40048f: bf 01 00 00 00 mov $0x1,%edi
400494: e8 f3 ff ff ff callq 40048c <e>
400499: 0f be c0 movsbl %al,%eax
40049c: 89 05 8a 0b 20 00 mov %eax,0x200b8a(%rip) #
60102c <b>
4004a2: 66 c7 05 85 0b 20 00 movw $0x1,0x200b85(%rip) #
601030 <a>
4004a9: 01 00
4004ab: 85 c0 test %eax,%eax
4004ad: 74 e0 je 40048f <f>
4004af: c3 retq
DWARF info at -Og:
0x000000c6: DW_TAG_variable
DW_AT_name ("l_33")
DW_AT_decl_file ("/tmp/a.c")
DW_AT_decl_line (6)
DW_AT_decl_column (0x07)
DW_AT_type (0x0000005b "int")
DW_AT_location (0x0000001b:
[0x000000000040048f, 0x00000000004004a2): DW_OP_lit1,
DW_OP_stack_value
[0x00000000004004ab, 0x00000000004004b0): DW_OP_lit1,
DW_OP_stack_value)
DW_AT_GNU_locviews (0x00000017)
The transformation behind the issue may be -ftree-dce. If we add -fno-tree-dce
to the compilation command line, the value of variable l_33 is correctly shown
at line 9. In particular, the DWARF location info is not generated but a const
value attribute is emmitted.
Code at -Og with -fno-tree-dce:
000000000040048f <f>:
40048f: 55 push %rbp
400490: 53 push %rbx
400491: 89 fd mov %edi,%ebp
400493: bf 01 00 00 00 mov $0x1,%edi
400498: e8 ef ff ff ff callq 40048c <e>
40049d: 0f be d8 movsbl %al,%ebx
4004a0: 89 1d 86 0b 20 00 mov %ebx,0x200b86(%rip) #
60102c <b>
4004a6: 85 ed test %ebp,%ebp
4004a8: 66 c7 05 7f 0b 20 00 movw $0x1,0x200b7f(%rip) #
601030 <a>
4004af: 01 00
4004b1: 85 db test %ebx,%ebx
4004b3: 74 de je 400493 <f+0x4>
4004b5: 5b pop %rbx
4004b6: 5d pop %rbp
4004b7: c3 retq
DWARF info at -Og with -fno-tree-dce:
0x000000c6: DW_TAG_variable
DW_AT_name ("l_33")
DW_AT_decl_file ("/tmp/a.c")
DW_AT_decl_line (6)
DW_AT_decl_column (0x07)
DW_AT_type (0x0000005b "int")
DW_AT_const_value (0x01)