https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128020
Bug ID: 128020
Summary: [DebugInfo] AArch64: loop unrolling gives a stale
constant DWARF location for a loop counter
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: debug
Assignee: unassigned at gcc dot gnu.org
Reporter: MrEven132 at outlook dot com
Target Milestone: ---
With GCC 17.0.0 20261003 (experimental) and GDB 17.2 on AArch64, enabling loop
unrolling makes GDB print `i = 0` after the first loop iteration, although `i`
is 1 and the register holding its value is 1. Disabling loop unrolling makes
GDB print `i = 1` at the same source line.
Test case (case.c):
/* Reduced from gcc/testsuite/gcc.dg/guality/loop-1.c. */
void __attribute__((noipa, noinline))
foo (int n)
{
if (n == 0)
return;
int i = 0;
do
{
++i;
}
while (i < n);
/* Keep the final value live at a stable source-level inspection point.
*/
__asm__ volatile ("nop" : : "g" (i) : "memory");
}
int
main (void)
{
foo (1);
return 0;
}
Build on AArch64:
gcc -O3 -g -fno-tree-scev-cprop -fno-tree-vectorize -funroll-loops case.c
-o unrolled
gcc -O3 -g -fno-tree-scev-cprop -fno-tree-vectorize -funroll-loops
-fno-unroll-loops case.c -o no-unroll
In separate GDB sessions, load each executable, break at case.c:16 (the
`__asm__ volatile ("nop" : : "g" (i) : "memory");` line), run, and print `i`.
The call is `foo(1)`, so the loop has incremented `i` once before this line.
With unrolling enabled, GDB prints `i = 0` while register `x5` is 1. With
unrolling disabled, GDB prints `i = 1` while register `x1` is 1.
At case.c:16 in the unrolled executable, the DWARF location for `i` incorrectly
describes the variable as the constant zero:
DW_OP_lit0, DW_OP_stack_value
At case.c:16 in the no-unroll executable, the DWARF location for `i` is
`DW_OP_reg1 W1`. The unrolled location list appears to retain `i`'s initial
value beyond the increment, causing the stale GDB value.