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)