[Bug debug/105179] New: -fcprop-registers shrinks a DWARF location range making a variable optimized out at -Og
dc.delia at protonmail dot com
gcc-bugzilla@gcc.gnu.org
Wed Apr 6 13:57:03 GMT 2022
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105179
Bug ID: 105179
Summary: -fcprop-registers shrinks a DWARF location range
making a variable optimized out at -Og
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: ---
In this code, the value of variable l_36 from function e is available when
debugging on line 23, which uses it as (dead) call argument for a function in
the same module, but is optimized out at the very next line 24, which uses it
as call argument for a function from an external module.
This seems to affect only -Og, as at -O1/O2/O3 the value is available.
Apparently, with -fcprop-registers the range in the DWARF location definition
of l_36 does not include the call to the external function, while it does if
disabled and the compiled code is unchanged. At -Og the location of the
variable is defined using DW_OP_reg, while other levels see a DW_OP_addr.
We found this issue on x64 using gdb 11.2 with gcc commit 500d3f0a302; as for
gcc releases, the issue is found in gcc-10 (we tested 10.3) and 11 (11.1),
while the variable value was available in, e.g., 6.4, 7.5, 8.4, and 9.3.
$ cat a.c
short a;
int c;
short b()
{
return a;
}
short d(unsigned short f)
{
return 0;
}
void e(char f)
{
short g;
char l_36;
int l_51, l_57 = 0 ;
for (; c <= 0; c++)
{
int l_30 = 0, l_80 = 2;
char l_81 = f;
g = b();
l_36 = g;
l_51 = d(l_36);
test(l_36, l_51, l_57, l_30, l_80, l_81);
}
}
int main ()
{
e(8);
}
$ cat lib.c
#include <stdio.h>
void test(int l_36, int l_51, int l_57, int l_30, int l_80, int l_81) {
printf("%d %d %d %d %d %d %d", l_36, l_51, l_57, l_30, l_80, l_81);
}
GDB trace:
$ gcc -Og -g a.c lib.c -o opt
$ gdb -q opt
Reading symbols from opt...
(gdb) b 24
Breakpoint 1 at 0x400529: file a.c, line 24.
(gdb) r
Starting program: /tmp/opt
Breakpoint 1, e (f=f@entry=8 '\b') at a.c:24
24 test(l_36, l_51, l_57, l_30, l_80, l_81);
(gdb) info loc
l_30 = 0
l_80 = 2
l_81 = 8 '\b'
g = 0
l_36 = <optimized out>
l_51 = 0
l_57 = 0
Code at -Og:
0000000000400504 <e>:
400504: 55 push %rbp
400505: 53 push %rbx
400506: 48 83 ec 08 sub $0x8,%rsp
40050a: 89 fd mov %edi,%ebp
40050c: eb 43 jmp 400551 <e+0x4d>
40050e: b8 00 00 00 00 mov $0x0,%eax
400513: e8 de ff ff ff callq 4004f6 <b>
400518: 89 c3 mov %eax,%ebx
40051a: 66 0f be f8 movsbw %al,%di
40051e: 0f b7 ff movzwl %di,%edi
400521: e8 d8 ff ff ff callq 4004fe <d>
400526: 0f bf f0 movswl %ax,%esi
400529: 0f be fb movsbl %bl,%edi
40052c: 44 0f be cd movsbl %bpl,%r9d
400530: 41 b8 02 00 00 00 mov $0x2,%r8d
400536: b9 00 00 00 00 mov $0x0,%ecx
40053b: ba 00 00 00 00 mov $0x0,%edx
400540: b8 00 00 00 00 mov $0x0,%eax
400545: e8 2f 00 00 00 callq 400579 <test>
40054a: 83 05 e3 0a 20 00 01 addl $0x1,0x200ae3(%rip) #
601034 <c>
400551: 83 3d dc 0a 20 00 00 cmpl $0x0,0x200adc(%rip) #
601034 <c>
400558: 7e b4 jle 40050e <e+0xa>
40055a: 48 83 c4 08 add $0x8,%rsp
40055e: 5b pop %rbx
40055f: 5d pop %rbp
400560: c3 retq
DWARF at -Og:
0x000000e7: DW_TAG_variable
DW_AT_name ("l_36")
DW_AT_decl_line (15)
DW_AT_decl_column (0x0a)
DW_AT_type (0x000001c4 "char")
DW_AT_location (0x00000036:
[0x000000000040051a, 0x0000000000400525): DW_OP_reg0 RAX)
DW_AT_GNU_locviews (0x00000034)
In the DWARF location info from -Og, the range does not include the call to the
test function at address 400545.
Through some testing we found out that the transformation behind the issue is
likely -fcprop-registers. With -fno-cprop-registers, variable l_36 appears with
its value when stepping at line 24 and the DWARF location info seems correctly
defined for the whole lifetime of the variable.
DWARF at -Og with -fno-cprop-registers:
0x000000e7: DW_TAG_variable
DW_AT_name ("l_36")
DW_AT_decl_line (15)
DW_AT_decl_column (0x0a)
DW_AT_type (0x000001d9 "char")
DW_AT_location (0x00000036:
[0x000000000040051a, 0x0000000000400551): DW_OP_reg3 RBX)
DW_AT_GNU_locviews (0x00000034)
The range is now larger than it was at -Og, capturing the call at 400545.
If helpful, please find below what happens at other optimization levels:
Code at -O1:
0000000000400504 <e>:
400504: 83 3d 29 0b 20 00 00 cmpl $0x0,0x200b29(%rip) #
601034 <c>
40050b: 7f 43 jg 400550 <e+0x4c>
40050d: 53 push %rbx
40050e: 40 0f be df movsbl %dil,%ebx
400512: 0f be 3d 1f 0b 20 00 movsbl 0x200b1f(%rip),%edi #
601038 <a>
400519: 41 89 d9 mov %ebx,%r9d
40051c: 41 b8 02 00 00 00 mov $0x2,%r8d
400522: b9 00 00 00 00 mov $0x0,%ecx
400527: ba 00 00 00 00 mov $0x0,%edx
40052c: be 00 00 00 00 mov $0x0,%esi
400531: b8 00 00 00 00 mov $0x0,%eax
400536: e8 2e 00 00 00 callq 400569 <test>
40053b: 8b 05 f3 0a 20 00 mov 0x200af3(%rip),%eax #
601034 <c>
400541: 83 c0 01 add $0x1,%eax
400544: 89 05 ea 0a 20 00 mov %eax,0x200aea(%rip) #
601034 <c>
40054a: 85 c0 test %eax,%eax
40054c: 7e c4 jle 400512 <e+0xe>
40054e: 5b pop %rbx
40054f: c3 retq
400550: c3 retq
DWARF at -O1 (same for -O2/-O3):
0x000000e7: DW_TAG_variable
DW_AT_name ("l_36")
DW_AT_decl_line (15)
DW_AT_decl_column (0x0a)
DW_AT_type (0x000001b7 "char")
DW_AT_location (0x0000003e:
[0x0000000000400512, 0x000000000040053a): DW_OP_addr
0x601038)
DW_AT_GNU_locviews (0x0000003c)
More information about the Gcc-bugs
mailing list