https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127460
Bug ID: 127460
Summary: [PRU] Debug information causes an extra repeat-loop
NOP with -fno-var-tracking
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: yqtian668 at gmail dot com
Target Milestone: ---
Created attachment 65622
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65622&action=edit
source c file to trigger this bug
I see one additional ordinary NOP in PRU repeat-loop code when compiling the
same source with `-g -fno-var-tracking` instead of `-g0 -fno-var-tracking`.
The difference reproduces on current GCC master revision
`11ae0ce305601ebf85b1a09b130cb3e7b46157f9`.
Test case (`source.c`, also attached):
```c
unsigned int
test_loop (unsigned int n, unsigned int x)
{
unsigned int i;
if (n >= 0x10000)
return 0;
if (!n)
return 0;
for (i = 0; i < n; i++)
x <<= 2;
return x;
}
```
Commands:
```text
xgcc -B/path/to/gcc -O1 -mloop -S -Wall -Wextra \
-fno-var-tracking -g0 source.c -o g0.s
xgcc -B/path/to/gcc -O1 -mloop -S -Wall -Wextra \
-fno-var-tracking -g source.c -o g.s
```
Both commands exit successfully with no diagnostics. The only difference in
the ordinary instruction sequence is the extra NOP:
```diff
loop .L7, r14
lsl r15, r15, 2
nop
+nop
mov r14, r15
ret
```
I repeated the pair five times on an unmodified build. Every `-g0` compilation
emitted one NOP and every `-g` compilation emitted two. Removing NOPs makes the
remaining ordinary instruction sequences identical.
Expected result: adding debug information should not change the number of
ordinary padding instructions in the repeat loop.
The difference requires `-fno-var-tracking`. With GCC's default variable
tracking, the `-g0` and `-g` ordinary instruction sequences are identical and
both contain one NOP. Disabling only variable-tracking assignments also does
not trigger the difference:
```text
options -g0 NOPs -g NOPs
default 1 1
-fno-var-tracking 1 2
-fno-var-tracking-assignments 1 1
both options disabled 1 2
```
The apparent cause is in `pru_insert_loop_label_last` in
`gcc/config/pru/pru.cc`. Its backward scan counts the last two recognized
opcodes, but it sends every `INSN_P` member to `recog_memoized`. A surviving
`DEBUG_INSN` has a negative recognition code, so the scan stops before counting
the preceding ordinary opcode and inserts one additional NOP. This paragraph
is cause analysis; the emitted assembly difference above is the directly
observed result.
Compiler information:
```text
Using built-in specs.
COLLECT_GCC=/build/gcc/xgcc
Target: pru-unknown-elf
Configured with: /source/configure --target=pru-unknown-elf \
--disable-bootstrap --disable-multilib --disable-nls \
--enable-languages=c --without-headers --disable-werror
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 17.0.0 20260918 (experimental) (GCC)
```
Build host: x86_64 GNU/Linux, Ubuntu 24.04.4 LTS, Linux 5.15.0-153-generic.